- an Evalezy API key (
vak_eval_…) with the scopesevaluation:readandevaluation:write. The last step, finalize, also needsevaluation:finalize. See Get an API key. - credits on your institute’s account
curl, Python 3 withrequests, or Node.js 18 or later (for the built-infetch)
The Node snippets in these docs use top-level
await. Save them in a .mjs file, or set "type": "module" in your package.json.Get an API key
1
Get the Evaluation API enabled
Evalezy turns the Evaluation API on for your institute. If it is not on yet, write to hello@evalezy.com.
2
Create a key in the dashboard
An institute admin opens the Vacademy admin dashboard and goes to Settings → Integrations → API keys, then clicks Create key. For this guide, tick all four permissions.
3
Store it safely
The key is shown once. Save it in your secret manager or an environment variable:
Response
401 means the key is wrong or revoked. A 403 product_not_enabled means the Evaluation API is not on for your institute yet. See Authentication.
Part 1: grade a typed answer
1
Create and open an exam
The exam has one The response is If you are following along with curl, save the exam’s
mcq_single question and one long_answer question with a rubric. The rubric’s criterion marks must add up to the question’s max_marks (here, 3). "open": true opens the exam for submissions straight away.201 Created. Trimmed:id for the next steps:2
Submit the candidate's answers
Send the candidate inline. Evalezy creates them (keyed by your The response is With curl, save the submission’s The
external_id) and registers them on the exam. Answer each question by its label: option_labels for the MCQ, text for the long answer.Send an Idempotency-Key built from your own ids. If the request times out and you send it again with the same key, you get the original response back instead of a second submission.202 Accepted: the submission is queued for grading. Trimmed:id:quote is the fixed price: 1 credit for one non-blank long answer. The MCQ is marked against the answer key at no charge.Each candidate can have only one live submission per exam. Submitting again for the same candidate returns
409 submission_exists. To replace a submission on purpose, send "replace": true.3
Poll until it is graded
Read
GET /submissions/{id} every few seconds until status is one of graded, partially_graded, failed or cancelled. While it waits, status moves through queued, processing, reading and grading.4
Read the result
Response
needs_review is true on a question, for example because the AI’s confidence was below 0.60, have a teacher check it before you finalize. Teachers can review in the Vacademy dashboard (open dashboard_url), or you can build review into your own product with the review endpoints.5
Finalize
Finalizing turns the draft marks into final marks. This call needs a key with the To finalize every graded copy of an exam at once, send
evaluation:finalize scope, which new keys do not have by default.Response
{"all_graded": true} instead of submission_ids. Copies that are not graded yet are left out entirely, not listed in skipped; GET /exams/{id}/submissions?finalized=false shows what is still open. skipped is filled only when you name copies in submission_ids, with a reason such as not_graded or already_finalized.Once a submission is finalized, overriding its marks or re-evaluating it returns 409 submission_finalized. To change marks after that, for example after a re-evaluation request, call POST /submissions/{id}/unfinalize with a reason.Full script: Python
Full script: Python
Full script: Node.js
Full script: Node.js
Part 2: grade a handwritten copy
For a handwritten exam, you upload the scanned answer copy as a PDF and submit itsupload_id instead of answers. Use the same question labels as the printed paper (“1”, “2”, “3a” …) so the AI can match each answer to its question.
1
Create a handwritten exam
The same call as in Part 1, with
"mode": "handwritten" and a new external_ref. This one has a single 3-mark long answer.2
Ask for an upload URL
Send the file name, type and exact size in bytes. PDFs only, up to 50 MB.With curl, save the upload’s The
Response
id and upload_url:upload_url works for one hour. To upload a whole class at once, send up to 100 files in files[].3
Upload the PDF
PUT the file to upload_url with the headers you were given. Do not send your X-API-Key to this URL. It is a pre-signed storage URL, not the Evalezy API.4
Wait for the upload to be ready
Evalezy checks the file (type, size, page count) on the first read after your PUT. Read This copy has 12 pages, so it will cost 12 credits.
GET /uploads/{id} until status is ready (with pages) or rejected (with reject_reason).Response
5
Submit the copy
id as HW_SUBMISSION_ID for the last step.Copies of 41 to 80 pages are accepted with a pages_beyond_vision_limit warning and marked for human review. Copies of more than 80 pages are refused with 422 too_many_pages.6
Poll, read the result, download the checked copy
Poll and read the result exactly as in Part 1. Handwritten copies take longer than typed answers because the handwriting has to be read first (Then finalize as in Part 1.
status: "reading"). In the result, extracted_answer shows the text Evalezy read for each question.When checked_copy.available is true, download the annotated PDF:Next steps
Authentication
Scopes, key safety and auth errors.
Rubrics
Write criteria the AI follows closely.
Handwritten exams
Scanning tips, bulk uploads and checked copies.
Syncing results
Grade a whole class without polling each copy.