Errors
The API uses conventional HTTP status codes: 2xx for success, 4xx for a problem with your request (a missing parameter, an entitlement you don’t have), and 5xx for a problem on our side.
Every error returns the same JSON envelope. code is a stable machine-readable string, message is human-readable, and details is optional structured context.
Common codes
| Code | Status | Meaning |
|---|---|---|
AUTHENTICATION_ERROR |
401 | Missing or invalid API key |
APP_NOT_ENABLED |
403 | Your subscription doesn’t include this app (ask, quiz, mark, exams_api, study, naplan_api) |
FORBIDDEN |
403 | Your key lacks the required role for this endpoint |
PARAMETER_MISSING |
400 | A required top-level parameter is absent |
NOT_FOUND |
404 | The resource doesn’t exist or isn’t yours |
VALIDATION_ERROR |
422 | A field failed validation — see details.fields |
INTERNAL_ERROR |
500 | Unexpected error on our side |
AI service errors
When the underlying AI provider fails, the code is derived from the provider error and the status reflects how to react:
| Code | Status | Meaning |
|---|---|---|
RATE_LIMIT_ERROR |
429 | AI provider rate limit hit — retry after a short wait |
SERVER_ERROR / SERVICE_UNAVAILABLE_ERROR / OVERLOADED_ERROR |
503 | AI provider temporarily unavailable — retry shortly |
BAD_REQUEST_ERROR / CONTEXT_LENGTH_EXCEEDED_ERROR |
422 | The AI couldn’t process the request (e.g. the conversation is too long) |
App-specific codes
| Code | Status | Meaning |
|---|---|---|
SUBJECT_NOT_FOUND / TOPIC_NOT_FOUND |
404 | Catalog id invalid or not authorised |
QUIZ_ERRORS::SUBJECT_REQUIRED / SUBJECT_NOT_ALLOWED / SUBJECT_NOT_VALID / TOPIC_NOT_IN_SUBJECT |
422 | Quiz subject/topic problems |
QUIZ_ERRORS::QUIZ_NOT_AVAILABLE |
422 | This subject doesn’t offer quizzes |
QUIZ_ERRORS::QUIZ_COULD_NOT_BE_CREATED |
409 | Quiz couldn’t be created from the given inputs |
QUIZ_ERRORS::QUIZ_NOT_FOUND |
404 | Quiz id invalid or not yours |
MARK_ERRORS::ASSESSMENT_NOT_FOUND / EXAMS_ATTEMPT_NOT_FOUND / SUBJECT_NOT_FOUND |
404 | Referenced id invalid or not yours |
MARK_ERRORS::FILE_REQUIRED / INVALID_FILE_TYPE / SUBJECT_NOT_ALLOWED / TOPIC_NOT_IN_SUBJECT / NO_SUBJECT_AVAILABLE |
422 | Marking request problems |
MARK_ERRORS::NOT_READY_FOR_REMARK / MARKING_IN_PROGRESS |
422 | Remark called too early |
EXAM_ERRORS::SUBJECT_REQUIRED / SUBJECT_NOT_ALLOWED / TOPICS_REQUIRED / INVALID_DIFFICULTY / INVALID_REQUEST |
422 | Exam request problems |
EXAM_ERRORS::EXAM_NOT_AVAILABLE |
422 | This subject has no exam paper blueprint yet |
STUDY_ERRORS::SUBJECT_REQUIRED / SUBJECT_NOT_ALLOWED / TOPIC_REQUIRED / TOPIC_NOT_IN_SUBJECT |
422 | Study request problems |
STUDY_ERRORS::SUBJECT_NOT_FOUND |
404 | Study subject id invalid or not yours |
STUDY_ERRORS::INVALID_AUDIO / EMPTY_ANSWER |
422 | Explain-back response problems |
STUDY_ERRORS::GENERATION_FAILED / SCORING_FAILED / TTS_FAILED |
502 | Transient study LLM/TTS failure — retry |
TOPIC_NOT_VALID / PERSONA_NOT_VALID / INVALID_CONTENT / CONVERSATION_TOO_LONG |
422 | Ask/chat request problems |
INAPPROPRIATE_CONTENT |
422 | Message blocked by content moderation |
INVALID_CHAT_ERROR / INVALID_CHAT |
400 / 422 | The chat can’t accept this request |
CHAT_FROZEN |
403 | This chat can no longer accept messages |
AGE_RESTRICTED |
403 | Conversational AI is unavailable for under-13 accounts |
STUDENT_NOT_FOUND |
404 | Unknown user_id for a student progress lookup |
PARAMETER_TOO_SHORT |
400 | A query parameter is below its minimum length |
Domain error codes are namespaced by app (e.g. QUIZ_ERRORS::…); the prefix is stable, so match on the full string.
Rate limits
Requests are limited to 100 per minute per API token. Exceeding the limit returns 429 Too Many Requests; check the Retry-After response header for how long to wait.