Skip to main content
This guide follows a school ERP through one term exam: a CBSE Class X Science half-yearly paper, graded from scanned answer sheets. It covers the whole loop, from turning the school’s marking scheme into rubrics to writing marks into report cards.
1

Create the exam

Send the questions, max marks, rubrics and model answers from the school’s marking scheme.
2

Register the class roster

Add students by your own student ID.
3

Open the exam

Lock the paper so copies can be submitted.
4

Scan, upload and submit

Scan one PDF per student, upload it, then submit it for that student.
5

Follow progress

Poll for changes until every copy is graded.
6

Teacher review

Teachers check the AI marks on the dashboard or through your UI.
7

Finalize and publish

Finalize, write marks into report cards and download the checked copies.

Before you start

  • An API key with evaluation:read and evaluation:write. Add evaluation:review if teachers will change marks in your UI, and evaluation:finalize for the system that publishes results. See Authentication.
  • Enough credits. A handwritten copy costs 1 credit per page of the uploaded PDF, blank pages included. A class of 40 students with 12-page copies costs about 480 credits.
  • A scanner that produces one PDF per student, with every page in order.
There is no sandbox: every key is live and every graded copy is charged. Test with a short exam and two or three copies.

1. Create the exam

Create the exam with the whole paper inline. Each question has a label (the number printed on the paper), a type, text and max_marks. For long answers, add a rubric and a model_answer from the school’s marking scheme. This is what makes the AI mark like the school’s own teachers. Set external_ref to your own ID for the exam. It is unique per institute, so a retried create cannot make a second copy of the exam.
The response is 201 Created with the exam in draft status, a dashboard_url where teachers can open it, and the price of one page:
Response (abridged)
Store the question id for each label. Results and teacher overrides refer to questions by ID.

Rubric rules

The API checks rubrics when you send them, so a mistake in the marking scheme is caught before any copy is graded. rubric and model_answer are only accepted on long_answer questions. A long answer with neither gets an auto_rubric warning: a rubric is generated from the question text on the first copy and reused for the rest (source: "generated"); review it with GET /exams/{id}/rubrics. A generated rubric is less consistent with the school’s scheme, so send at least a model answer for every long answer.
Negative marks do not apply to handwritten copies. A negative_marks value on a handwritten exam is ignored, and the response carries a negative_marks_ignored warning.
Choice groups (“attempt any N of M”) are in beta and enabled on request. They are currently switched off, so choice_groups returns 422 feature_not_available, and a question whose label looks like an OR question (for example 33-OR) gets an internal_choice_suspected warning: both alternatives count towards the total. Contact hello@evalezy.com if you need choice groups.

2. Register the class roster

Register students with your own student ID as external_id. Candidates belong to the institute, so a student registered once can sit every later exam with the same external_id.
Send up to 2,000 candidates per call. Registering is safe to repeat: students already on the exam come back in already_registered.
Registering the roster is optional. A submission that names a new candidate registers them on the exam automatically. Registering first lets you list who has not submitted yet: GET /exams/{id}/candidates returns each student with submission_id and submission_status.

3. Open the exam

Copies can only be submitted to an open exam. Opening checks that the exam has at least one question, every question has max marks, and every rubric adds up to its question’s max.
Opening an open exam again changes nothing. You can also pass "open": true when you create the exam. Once the exam is open, you can no longer add or remove questions. You can still edit a question’s text, model_answer, rubric, tags, word_limit and expects_diagram, and the exam’s title and details.

4. Scan the answer sheets

Good scans are the biggest factor in grading quality.
  • One PDF per student. All of the student’s pages, in order, in a single file. Supplementary sheets go at the end of the same PDF.
  • Every page is billed. The price is per page of the uploaded PDF, blank pages included. Remove blank and cover pages you don’t need graded.
  • Up to 40 pages is normal. Copies of 41 to 80 pages are accepted but marked needs_review with the reason pages_beyond_vision_limit. Copies over 80 pages are refused with 422 too_many_pages.
  • PDF only, up to 50 MB. Password-protected PDFs are rejected as unparseable. Phone photos are not accepted yet; see the Roadmap.
  • English answers only. Hindi and regional-language handwriting is not supported yet. Such a copy fails with language_not_supported and is not billed.

5. Upload the PDFs

Uploads are two steps: ask for upload URLs, then PUT each file to its URL. One call can presign up to 100 files, so a class of 40 is one request.
Each entry in uploads[] has an id, the upload_url, the method and headers to use, and an expires_at one hour away. Send size_bytes as the exact file size; the URL only accepts that file. GET /uploads/{id} checks the file on the first read after the PUT and returns status:
An upload can be used by one submission only. A second submission with the same upload_id is refused with 409 upload_already_used. If you retry POST /uploads with the same Idempotency-Key, the replay does not contain the upload URLs (upload_url_redacted: true); request new uploads with a new key.

6. Submit each copy

Submit each ready upload for its student. Name the student inline by external_id (they are created and registered if they are new), or pass the candidate_id returned when you registered the roster.
The response is 202 Accepted. Grading runs in the background:
Response (abridged)
The quote is the fixed price of this copy. It is charged only when the copy is graded; failed and cancelled copies are free.

7. Follow progress

Don’t poll each submission. Poll the feed of everything that changed since your last check, across all exams. Syncing results has the full worker.
For a progress bar, GET /exams/{id}?include=stats returns counts: candidates, submissions, queued, processing, graded, partially_graded, failed and finalized. A submission moves through queued, processing, reading and grading to one of: For a failed copy, error.code tells you what to do next. copy_unreadable: rescan and submit again with "replace": true. timed_out, engine_unavailable and file_unavailable: call POST /submissions/{id}/re-evaluate. language_not_supported: the copy is in Hindi or another unsupported language and has to be marked by hand.
Re-evaluating a copy is charged again at the same price. Rescan unreadable copies rather than re-evaluating them.

8. Teacher review

AI marks are drafts. Nothing is published until you finalize, so teachers can check and correct every copy first. Start with the copies the AI flagged: GET /exams/{id}/submissions?needs_review=true. A question needs review when the AI could not grade it, when its confidence is below 0.60, or when the AI reported another reason in review_reasons. Copies of more than 40 pages are flagged as a whole with pages_beyond_vision_limit.
Exams created through the API also appear in the school’s Vacademy dashboard, tagged Source: API. Teachers open the exam from dashboard_url, see each copy with the AI’s marks and annotations, and change marks there. Their changes show up in the API results with source: "ai_reviewed".This needs no extra work in your ERP. Each teacher needs an account in the school’s Vacademy dashboard.

9. Finalize

Finalizing turns draft marks into final marks. After that, overrides and re-evaluation are refused with 409 submission_finalized until you unfinalize.
Response
  • "all_graded": true finalizes every copy that is graded and leaves all other copies out entirely: they do not appear in skipped. Add "allow_partial": true to include partially_graded and failed copies too; failed questions then count as 0, so review them first.
  • "submission_ids": [...] (up to 500) finalizes specific copies. Any that can’t be finalized come back in skipped with a reason: not_graded (still in the queue or grading), partially_graded or failed (without allow_partial), or already_finalized.
  • To find copies that are still not final, list GET /exams/{id}/submissions?finalized=false.
  • all_graded handles up to 500 copies per call. Call again while has_more is true.
Finalizing through the API sends nothing to students or parents: no emails, no PDFs, no notifications. Your ERP decides when and how results are published.
If a parent asks for a recheck after results are out, put the copy back on hold with a reason, correct it, and finalize again:

10. Write marks into report cards

Read the results of the whole exam, 50 copies per page, and map them onto your report card. finalized=true returns only final marks.
Each result has totals (awarded, max, percentage, questions_graded, questions_failed) and one entry per question with awarded, max, feedback and a per-criterion breakdown in criteria. Results come as JSON only; format=csv is not available yet.

11. Download checked copies

The checked copy is the student’s answer sheet with the AI’s marks and comments on it, ready for the parent-teacher meeting. A result says whether one exists in checked_copy.available.
The API streams the PDF. Store it in your own storage and serve it to parents from there; your API key must never reach a browser. A copy without a checked PDF returns 404 checked_copy_not_found.
?redirect=true may answer 302 with a short-lived link (expires_in 60 to 3,600 seconds, default 900) instead of streaming. If you use it, handle the redirect yourself and fetch the link without your X-API-Key header. Many HTTP clients forward custom headers on redirects.

Next steps

Syncing results

A polling worker that never misses a change.

Going live

Keys, retries, credits and quotas before your first school.