For the complete documentation index, see llms.txt. This page is also available as Markdown.

Errors

The error envelope, every error code, and how to react to each.

Every error — from any endpoint — returns the same envelope, so one handler covers the whole API.

The Envelope

{
  "errors": [
    {
      "status": "422",
      "code": "validation_error",
      "title": "Unprocessable Entity",
      "detail": "Unknown filter 'shcool_id'"
    }
  ]
}
Field
Use it for

status

The HTTP status, as a string.

code

Branch on this. A stable machine-readable identifier.

title

The standard HTTP status name.

detail

Human-readable specifics. Helpful in logs; do not parse.

errors is always an array, though today it always holds exactly one entry. Treat it as a list so your parser survives multi-error responses later.

Status Codes

Status
Meaning

200

Success.

401

Not authenticated — credentials or token problem.

403

Authenticated, but not allowed.

404

No such record in your district.

422

The request was understood but a parameter is invalid.

429

Rate limit exceeded.

5xx

Server-side problem. Retry with backoff.

Error Codes

401 — Authentication

Code
Cause
What to do

invalid_token

Missing, malformed, expired or revoked token; or bad credentials at the token endpoint.

Fetch a new token and retry once. If it fails again, the credential is bad — stop.

expired_client

The credential has passed its expiry date.

Not recoverable in code. Request a new credential.

revoked_credential

The credential was revoked.

Not recoverable. Contact Support.

unknown_district

The credential's district can no longer be resolved.

Not recoverable. Contact Support.

not_authorized

Authorisation failed for this request.

Check the token is being sent correctly.

403 — Forbidden

Code
Cause
What to do

feature_disabled

The API is not enabled for this district.

Contact Support to enable it. Retrying will not help.

insufficient_scope

The token lacks the scope this endpoint requires.

Check the scope table. On nested routes you need the child's scope.

forbidden

Access denied to this resource.

Do not retry.

404 — Not Found

Code
Cause

not_found

No such record in your district — it may not exist, or it may belong to someone else. The API does not distinguish the two.

An unknown report name also returns not_found.

422 — Invalid Parameters

All parameter problems share the code validation_error; detail says which.

detail

Cause

Unknown filter 'x'

Not an allowed filter for this endpoint.

Unknown sort 'x'

Not a sortable column for this endpoint.

filter must be an object, e.g. filter[key]=value

Sent ?filter=x instead of ?filter[key]=x.

sort must be a comma-separated string, e.g. sort=name,-created_at

Sent ?sort[]=x instead of ?sort=x.

page[number] must be an integer / must be >= 1

Non-numeric or zero/negative page.

page[size] must be an integer / must be between 1 and 100

Non-numeric or out-of-range page size.

filter[updated_since] must be a valid ISO 8601 datetime

Malformed timestamp.

Missing required filter(s): filter[x]

A report's required filter was omitted.

unsupported grant_type

grant_type was not client_credentials.

429 — Rate Limited

Slow down and honour Retry-After. See Rate Limits & Policies.

Handling Errors

A robust client distinguishes three classes:

Retry immediately, once. 401 invalid_token — your token probably just expired. Refresh and replay. If the replay also fails, stop; something is wrong with the credential, and hammering it wastes your token budget.

Retry later, with backoff. 429 and 5xx. Wait for Retry-After (or exponential backoff for 5xx), then retry. Cap your attempts.

Do not retry. 403, 404 and 422 are deterministic — the same request will always fail the same way. Log it and fix the request or the credential.

403 feature_disabled is the one that most often looks like a bug in your code but isn't. It means the credential is fine and the API simply is not switched on for that district yet.

Last updated

Was this helpful?