isFinal, wait for the AI.
Steps 1, 3, and 5 start background AI jobs. Exams report a
status, but model answer sheets and answer sheets do not, so you wait on the endpoint that returns the result: it answers 400 while the job runs and 200 when it is ready. The wait_for helper below does this for you.Set up
You need an access token. If you don’t have one, follow the Quickstart.Step 1: Create the exam and upload the question paper
Create the exam, upload the paper, then submit it withisFinal. Send one PDF of up to 50 pages, or any number of .jpg and .png images, but never a PDF and images together.
What you get back
What you get back
status is 0 Open, 1 In Progress, 2 Completed, or 3 Failed. The exam’s own status uses the same values, and you can read it with Get an exam.Step 2: Get the extracted questions
Wait for the questions, then show them to a teacher. Until extraction finishes, this call returns400 Exam is not processed yet.
What you get back
What you get back
Questions sit three levels deep: sections, then question groups, then the questions a student answers.
maxQuestionAttempt says how many items below count toward the score. Fix anything wrong now with Edit exam questions, answers, or marks: those edits lock as soon as the first answer sheet is submitted.Step 3: Upload the model answers
Create the model answer sheet, upload the answer key, then submit it. The same file rules apply.An exam has one model answer sheet. Creating it twice returns the same sheet, so the call is safe to repeat.
Step 4: Check the model answers
Wait for the answer key, then show it to a teacher. Every question now carries amodelAnswer and its step marking.
What you get back
What you get back
The same paper as step 2, with a
modelAnswer on every question:stepMarking splits a question’s marks across the steps of its answer, and that is what the AI grades against. When the marksplit values don’t add up to marks, isModelAnswerMarkMismatch is true. Fix it before you upload any answer sheet.Step 5: Upload a student’s answer sheet
Create an answer sheet for one student, upload the pages in order, then submit it. Repeat for every student.Step 6: Review the scores
Wait for the marks, show them to a teacher, and apply any correction. Nothing here is visible to students yet.An
answer edit that changes text or marks must include updateReason. It comes back as teacherFeedback. Editing questions and model answers is already locked at this point.What you get back
What you get back
Every question now has the model answer, the student’s answer, and why marks were lost.
answerText is No Answer when the student left a question blank, and those answers always score 0. Totals roll up into obtainedMarks on each group, each section, and the exam.Step 7: Publish the results
Publishing is what makes scores readable.pre-publish releases the provisional result, which is also what lets students raise queries.
{"entity": "final-publish"} and read Get final exam results. That response has the same body, so it includes every mark changed since.
What you get back
What you get back
provisionalPublishedDate is UTC, written as YYYY-MM-DD HH:MM:SS.Step 8: Handle student queries (optional)
A student who disagrees with a deduction raises a query against it. That sends the answer back to the AI for a second look.queryType is 1 Classification, 2 Re-evaluation Request, or 3 Other Concerns.
Poll the same GET to pick up the result. The AI’s justification arrives in the query’s responses with createdByRole of AI, and the query’s status becomes 3 Resolved. A teacher can also reply in the thread or close the query.
Good to know
Limits
Limits
Both daily limits are counted per API user, which is the credential your access token comes from. Separate API users each get their own count.
Use webhooks instead of polling
Use webhooks instead of polling
Register a webhook for each step, then fetch the result when the event arrives. See Async jobs and webhooks.
Every payload carries
status as Completed or Failed, exam_id, the event’s name and display_name, and the secret_hash you registered. Model answer events add model_answer_sheet_id, and answer sheet events add ans_sheet_id. Nothing else is included, so fetch the result yourself.Only the answer sheet event is retried, once, after 5 seconds if your endpoint doesn’t return 200 or 201. Keep polling as a fallback.Troubleshooting
Troubleshooting
Related
Exam Evaluation API reference
Every field, response, and error.
How the workflow fits a school
The same flow, without the code.
Use cases
Where schools and platforms use exam evaluation.
Embeddable UI
Ready-made screens for uploading and reviewing.