Flow
- Prepare question packages through the Question Import API and store
question_bank.id, or pick an existing question package withGET /question-banks. - Create the exam with its tests and sessions in one
POST /examsrequest. - Check
GET /exams/{exam}/readinessuntilreadyistrue. - Register participants and create access links through Exam Registration and Access Links.
- For tests scored with IRT, run
POST /exams/{exam}/irt-calculationsonce participants have finished. Scores are sent through theexam_result.scoredwebhook and are available in the Exam Results API.
Rules
- Kind of exam. Exams created through the API take no payment inside the CBT and are not multi-level. Multi-level exams and exams with payment inside the CBT that were created in the admin panel can still be read, but can only be changed or deleted in the admin panel. Manual-answer tests (essay/file upload) are created in the admin panel; through the API only their name, instructions and sessions can change.
- Edition (
edition):standard(Standard Exam): up to 4 tests, without CAT and without camera, screen or dual-monitor proctoring.professional(Professional Exam): up to 30 tests, with every feature.- Credit is used when a participant starts a test, not when the exam is created. A professional exam uses professional credit; a standard exam uses free credit first, then professional credit. Without credit an exam can still be created, but participants cannot start its tests.
- Times are sent in ISO 8601 with an offset, for example
2026-11-10T08:00:00+07:00or2026-11-10T01:00:00Z, and are returned in WIB (+07:00). A time without an offset, such as2026-11-10 08:00:00, is refused with422. An exam’send_atis at most one year from now. - Sessions must sit inside the exam’s time range and last at least as long as their test. A session’s question package must belong to the project, match its test’s type (CBT/CAT for CBT and CAT tests, manual answer for manual-answer tests) and hold at least one question; for a CAT test every question needs a difficulty level.
- Automatic sessions (
is_auto_assign_session, defaulttrue): registered participants get the first (earliest-created) session of every test. Participants registered before a test had a session get that session automatically when it is created. - Test order follows the order in which the tests were created. When
is_must_be_in_orderistrue, participants must finish the tests in that order. - Participants see an exam while it is inside its time range and not archived. A test can only be started during a session that has a question package.
What is locked
Error format
Invalid input is returned with status422 in the same error format as other endpoints. Error keys name the field, nested fields included, for example exam_quizzes.0.sessions.1.end_at.
409 and a code field:
Test settings
Exam endpoints
POST /exams — Create an exam with its tests and sessions
POST /exams — Create an exam with its tests and sessions
Parameters
Example request
Example response
Status201. The body is the same as the exam details, including exam_quizzes and sessions with their IDs. Store the exam, test and session IDs for later changes.PATCH /exams/{exam} — Change an exam
PATCH /exams/{exam} — Change an exam
POST /exams without exam_quizzes. The endpoint also accepts the PUT method.- The new time range must still contain every session; change the sessions first when needed.
- Changing
editiontostandardis refused when the exam has more than 4 tests or a test that uses a professional feature. - Changing
final_score_typerecalculates the participants’ final scores. - Turning
is_auto_assign_sessionon places participants without a session in the first session of every test right away.
Example request
POST /exams.DELETE /exams/{exam} — Delete an exam
DELETE /exams/{exam} — Delete an exam
409 (attempt_started) once a participant has started a test. Multi-level exams and exams with payment inside the CBT can only be deleted in the admin panel.Test endpoints
POST /exams/{exam}/quizzes — Add a test
POST /exams/{exam}/quizzes — Add a test
exam_quizzes item of POST /exams, sessions included. The new test goes last in the order. Participants already registered get the new test straight away, and its session when automatic sessions are on.201; the response holds the test with its sessions.PATCH /exams/{exam}/quizzes/{examQuiz} — Change a test
PATCH /exams/{exam}/quizzes/{examQuiz} — Change a test
name, exam_type, duration_minutes, score_type, description and the is_* settings. A new duration cannot be longer than the test’s existing sessions. On a manual-answer test only name and description can change; other fields are refused with 422. The endpoint also accepts the PUT method.DELETE /exams/{exam}/quizzes/{examQuiz} — Delete a test
DELETE /exams/{exam}/quizzes/{examQuiz} — Delete a test
409 (participants_registered) once participants are registered for the exam. The test’s sessions are deleted with it.Session endpoints
POST /exams/{exam}/quizzes/{examQuiz}/sessions — Add a session
POST /exams/{exam}/quizzes/{examQuiz}/sessions — Add a session
201:PATCH /exams/{exam}/sessions/{session} — Change a session
PATCH /exams/{exam}/sessions/{session} — Change a session
409 while a participant is working in this session, and the question package cannot be replaced once a participant has started. To switch to a new question package revision before the exam starts, send the new question_bank_id. The endpoint also accepts the PUT method.DELETE /exams/{exam}/sessions/{session} — Delete a session
DELETE /exams/{exam}/sessions/{session} — Delete a session
409 (participants_registered) once participants are placed in this session.Readiness and scoring
GET /exams/{exam}/readiness — Check whether an exam is ready
GET /exams/{exam}/readiness — Check whether an exam is ready
ready is true when there is no issue with severity error; a warning flags something to look at that does not block the exam.POST /exams/{exam}/irt-calculations — Run the IRT calculation
POST /exams/{exam}/irt-calculations — Run the IRT calculation
exam_result.scored webhook. While a calculation is still queued or running, another request is refused with 409 (calculation_running).202:GET /exams/{exam}/irt-calculations — IRT calculation status
GET /exams/{exam}/irt-calculations — IRT calculation status
Question packages
GET /question-banks — List question packages
GET /question-banks — List question packages
is_locked: true and a source naming its package and revision.
