Fetch the assessment (server)
Your server calls
client.getAssessment() — the API key never reaches the browser.Render each question
<EdpireQuestion> (React) or renderQuestion() (vanilla) renders one step at a time.Check answers per question
Your server proxies
POST /check for immediate per-question feedback. Stateless — no record created.1. Fetch (server)
Keep the API key server-side — never call Edpire directly from the browser. Expose a thin proxy your browser can call:2. Flatten — flattenAssessment()
FlatStep[] — one entry per question, in the order a learner would see them (exercise order, then question order).
3. Render — <EdpireQuestion> or renderQuestion()
Generate your If you wait until step 4 and generate one per question, rate limiting accumulates across retakes and causes surprise
session_id now, before rendering the first question. You’ll need it for every /check call and it must be the same across all questions in one attempt. Create it once at attempt start:429s.- React
- Vanilla JS
EdpireQuestionProps.renderQuestion() reference
RenderQuestionOptions — same fields as EdpireQuestionProps: container, content, onAnswersChange?, feedback?, initialAnswers?, dir?.
QuestionInstance:
| Method | Description |
|---|---|
setContent(content) | Replace the question. Also clears feedback — ready for the next step. |
setFeedback(feedback | null) | Update feedback (e.g. after /check). null clears it. |
setInitialAnswers(answers) | Pre-fill answers (e.g. navigating back). |
unmount() | Tear down the React root. |
4. Check per question — POST /check
Grade a single question for immediate feedback. Stateless — no submission is recorded. Proxy it through your server so the API key and include_correct_answers flag stay trusted:
result.feedback straight into EdpireQuestion’s feedback prop (or q.setFeedback()).
How feedback maps onto the question
The/check response’s feedback is keyed by node ID → feedback state (correct/partial/incorrect, score, message, and — when include_correct_answers is true — the correct answer fields). EdpireQuestion consumes that object directly and renders the right per-node visual state. Set feedback back to null (or call setContent) before showing the next question to reset it.
When include_correct_answers is true, feedback also includes: correctChoiceIds (choice/drag-drop), correctPairings (matching), and displayAnswer (typed blanks).
5. Submit the full attempt — client.submit()
/check records nothing. After the last question, submit the whole attempt once to create the graded submission record (and fire the submission.graded webhook).
Collect answers as a flat StoredAnswer[] during the session:
client.submit() accepts either a flat StoredAnswer[] or the nested { exerciseAnswers: [...] } format. If you need the nested form explicitly (e.g. constructing it elsewhere), convert with buildSubmitPayload(stored).read:assessments (fetch + check) and write:submissions (the final submit).
If the learner abandons mid-flow:
/check is stateless, so nothing is recorded. If they close the tab before step 5, their attempt is lost. Consider saving answers to sessionStorage after each question so you can restore them on reload, and warn users before they navigate away during an active attempt.