Skip to main content
The Evalezy API is a JSON REST API. You create an exam, submit each candidate’s scanned copy or typed answers, and read question-wise marks with feedback. Every endpoint in this tab is generated from these docs’ copy of the OpenAPI document, which adds descriptions and examples to the one the API serves at /v1/openapi.json. Each endpoint page shows the request, the response and ready-to-run code samples.
Every call is live and billable, and there is no sandbox. Run the samples from your own server or terminal with a small test exam. Don’t paste your API key into a web page.

Base URL

There is one environment. There is no sandbox or test mode: every key is live and every graded copy is billed. To try things out, use a small exam with one or two short copies.

Authentication

Send your institute’s API key in the X-API-Key header on every request.
Keys look like vak_eval_ followed by 48 hex characters. Each key has scopes: evaluation:read, evaluation:write, evaluation:review and evaluation:finalize. New keys get read and write by default. Every endpoint page lists the scope it needs. A missing key returns 401; a key without the scope an endpoint needs returns 403 insufficient_scope.
Call the API only from your servers. Never put a key in a browser, a mobile app or a public repository. Anyone holding the key can spend your institute’s credits.
See Authentication for how to get a key, rotate it and revoke it.

Conventions

Request and response bodies are JSON. Send Content-Type: application/json; any other content type returns 415 unsupported_media_type. Field names are snake_case. Unknown fields are ignored on create and action endpoints. PATCH endpoints refuse unknown fields with 422 validation_failed (field code unknown_field), so a typo never looks like a successful edit.
Evalezy ids (exams, questions, candidates, uploads, submissions) are UUID strings. You can also attach your own ids: external_ref on exams and external_id on candidates. Both are unique within your institute, and you can look records up by them with Find exams by external_ref and Find candidates by external_id. Your own ids go in request bodies, never in URLs.
Timestamps are ISO 8601 in UTC, for example 2026-10-14T05:30:12Z. Dates such as conducted_on are YYYY-MM-DD. Filters such as updated_since take the same UTC timestamp format.
A question’s max_marks and teacher overrides are numbers in steps of 0.5. A question’s max_marks is greater than 0 and at most 1000. Rubric criterion marks may be other positive values; they are accepted with a rubric_marks_not_half_step warning.
All text you send is treated as plain text, never HTML. A NUL character (U+0000) anywhere in a body returns 422 validation_failed with field code invalid_characters. Short identifiers and names (exam title, question and option labels, section names, candidate names and roll numbers) cannot contain < or >.
A key sees only its own institute’s API exams. An id that belongs to another institute returns 404, the same as an id that does not exist. Exams created in the dashboard are not visible to API keys, while exams created through the API do appear in the dashboard, tagged Source: API, so teachers can review them there.

Status codes

Every error has the same envelope:
Branch on error.code, not on the message. The full list is in Errors.

Lists

List endpoints return {"data": [...], "next_cursor": "...", "has_more": true}, ordered by (updated_at, id). Pass next_cursor back as cursor for the next page. limit is 1 to 200 (default 50); exam results are heavier, so List an exam’s results takes 1 to 50 (default 20). See Pagination.

Retries and idempotency

Every POST that creates or changes something (exams, open, questions, candidates, uploads, submissions, re-evaluate, cancel, approve, finalize, unfinalize) accepts an optional Idempotency-Key header. Retrying with the same key within 48 hours returns the first response with Idempotent-Replayed: true instead of creating a second exam or a second submission. See Idempotency.

Useful response headers

Quickstart

Grade your first handwritten copy end to end.

Errors

Every error code and what to do about it.

Pagination

Cursors, updated_since and sync loops.

Idempotency

Safe retries for every POST.