Skip to main content
Evalezy uses standard HTTP status codes. 2xx means the request worked, 4xx means something in the request needs to change, and 5xx means something went wrong on our side. Every error the API returns, whatever the status, has the same JSON shape.

The error envelope

string
required
A stable machine code, such as exam_not_found or insufficient_credits. Branch on this, not on the message or the HTTP status alone. Codes never change once published.
string
required
A human-readable explanation. Safe to log and show to your operators. The wording can improve over time, so do not parse it.
string
required
The id of this request, such as req_3f2a9c41d8b04e6f9a7c2d1e5b8f0a63. The same value is returned in the X-Request-Id response header on every response, successful or not.
object
Extra machine-readable context when there is some, for example the id of the existing resource on a 409, or the list of invalid fields on a 422. Left out when empty.
Error responses are sent with Content-Type: application/json and Cache-Control: no-store.

Validation errors

422 validation_failed lists every field that failed in details.errors, so you can fix them all in one go:
Field-level codes you will meet most often:
All text you send is treated as plain text. Long text such as question text, model answers and typed answers can contain < and > (for example x < 5); they are kept exactly as sent and never rendered as markup.

Error codes

Ids that belong to another institute always answer 404, never 403. You cannot tell whether a resource exists elsewhere.

400 Bad Request

401 Unauthorized

402 Payment Required

403 Forbidden

404 Not Found

405, 413, 415

409 Conflict

A 409 means the request is valid but clashes with the current state. Most carry the id of the resource involved in details.

412 Precondition Failed

422 Unprocessable Entity

feature_not_available is returned for:
  • Choice groups (“attempt any N of M”): beta, enabled on request.
  • images[] on a submission or image files on POST /uploads (phone photos).
  • files[] on a submission (booklet plus supplements).
  • question_ids on POST /submissions/{id}/re-evaluate (re-grading single questions).
  • format=csv on GET /exams/{id}/results.
  • purge=true on DELETE /exams/{id}.
See the Roadmap.

429 Too Many Requests

See Rate limits and quotas.

5xx

Rarely, a gateway error (for example 502 or 504) arrives without the JSON envelope, sometimes with an HTML body. Treat any 5xx as retryable, and parse error bodies defensively.

Retry or fix?

Send an Idempotency-Key on every POST so that retries never create duplicates.

Submission error codes

Some problems only show up after a submission is accepted, while it is being graded. Those do not fail the HTTP request; instead the submission ends with status: "failed" and an error object:
A failed submission is never charged.

Question errors

When a copy finishes but the AI could not grade some answers, the submission’s status is partially_graded. In the result, each affected question has status: "failed", needs_review: true and its own error object with a code and the message “The AI could not grade this answer; review it by hand.” Mark those questions with PATCH /submissions/{id}/questions/{question_id}. Treat the question-level code as informational.

Warnings

A successful response can carry warnings: input that was accepted but deserves attention. Each warning has a code, a message and the field it is about.
Log warnings and surface them to your operators. They never block the request.

Reporting a problem

Every response carries X-Request-Id, and every error body repeats it as error.request_id. Log it with every failed call. When you need help, email hello@evalezy.com with:
  • the request_id (or several, if the problem repeats),
  • the endpoint and the time of the call (with time zone),
  • the error.code you received and what you expected instead.
With the request id we can find the exact call in our logs. Please never send your API key, and never include student answer sheets in email unless we ask for a specific one.