---
title: "Publish APIs"
description: "Register your application, choose a tier, and start making authenticated requests to the Education Data APIs."
url: "https://education.gough.run/guides/publish-apis"
image: "https://education.gough.run/_og/d/c_Ocean.takumi,title_Publish+APIs,description_~UmVnaXN0ZXIgeW91ciBhcHBsaWNhdGlvbiwgY2hvb3NlIGEgdGllciwgYW5kIHN0YXJ0IG1ha2luZyBhdXRoZW50aWNhdGVkIHJlcXVlc3RzIHRvIHRoZSBFZHVjYXRpb24gRGF0YSBBUElzLg,props_eyJ0aGVtZSI6eyJtb2RlIjoibGlnaHQiLCJjb2xvcnMiOnsicHJpbWFyeSI6IiM2NmFhMjMifX19,p_Ii9ndWlkZXMvcHVibGlzaC1hcGlzIg,s_xF9iSYDr_4pv-dvN.png"
---

## Publish APIs

Register your application, choose a tier, and start making authenticated requests to the Education Data APIs.

## [Onboarding overview](#onboarding-overview)

Accessing the Education Data Platform is a four-step process: register your application, choose a subscription tier, retrieve credentials, and make your first authenticated call. The whole flow takes under five minutes for the standard tiers.

Your application's tier determines its rate limits and quota. The list of schools your application can access is set when you onboard and can be expanded later via your partner support channel.

## Explore our APIs

Connect, create, and innovate with our easy-to-use APIs.

[Start building](https://education.gough.run/apis)

### [Step 1: Register your application](#step-1-register-your-application)

From the **Applications** section of this portal:

1.  Click **New Application**
2.  Give it a descriptive name (e.g. "Production Dashboard Integration")
3.  Choose a subscription tier (see comparison below)
4.  Submit the request

You'll be issued a `client_id` and `client_secret`. Store the secret in a secrets manager — it's only shown once.

### [Step 2: Choose a tier](#step-2-choose-a-tier)

We offer three subscription tiers, each with different rate limits and quotas:

Free is suitable for development and small-scale integrations. Standard is right for most production use cases. Premium is for high-volume integrations such as analytics platforms or multi-tenant systems.

### [Step 3: Get an access token](#step-3-get-an-access-token)

Exchange your `client_id` and `client_secret` for a Bearer JWT using OAuth 2.0 client credentials:

```bash
curl --request POST \
  --url https://auth.example.com/oauth/token \
  --header 'content-type: application/json' \
  --data '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "audience": "https://api.example.com",
    "grant_type": "client_credentials"
  }'
```

The response contains an `access_token` — that's your JWT. It contains custom claims describing your tier and approved schools:

```json
{
  "tier": "standard",
  "schools": ["oakwood-primary", "ravenscroft-high"],
  "client_id": "YOUR_CLIENT_ID",
  "iss": "https://auth.example.com/",
  "exp": 1780821709
}
```

Tokens are valid for one hour. Mint a fresh one before expiry or implement automatic refresh in your client.

### [Step 4: Make your first call](#step-4-make-your-first-call)

Use the access token in the `Authorization` header:

```bash
curl https://api.example.com/stats/v1/attendance/summary?school_id=oakwood-primary \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

The gateway:

-   Validates the JWT signature against the identity provider's JWKS
-   Maps the `tier` claim to a rate-limit policy
-   Forwards the `schools` claim to the upstream service
-   The upstream service enforces that the requested school is in your approved list

If everything checks out, you'll get a JSON response. If your token is missing a claim, expired, or invalid, you'll get a `401`. If you try to query a school not in your approved list, you'll get a `403`.

## [Authorisation model](#authorisation-model)

Every authenticated request flows through three layers of checks:

1.  **Authentication** — the JWT signature and expiry are verified at the gateway
2.  **Rate limiting** — your tier's request and cost quotas are checked
3.  **School-level authorisation** — the requested `school_id` is checked against your approved list

The third layer is enforced by the upstream services, with the approved list forwarded from the JWT as an `X-Claim-Schools` header. This means even if you bypass the rate limit, you can't access schools outside your approved set.

## [What to do if requests fail](#what-to-do-if-requests-fail)

| Status | Likely cause                       | Action                                            |
| :----- | :--------------------------------- | :------------------------------------------------ |
| 401    | Token missing, invalid, or expired | Mint a fresh token                                |
| 403    | School not in your approved list   | Check the schools claim; request access if needed |
| 429    | Rate limit or cost limit exceeded  | Check Retry-After header; consider upgrading tier |
| 500    | Server-side issue                  | Include X-Request-Id in any support ticket        |

Always include the `X-Request-Id` response header when contacting support — it lets us trace your request through all the systems involved.