Integration guide: building a mock-exam flow
This walks through a complete, production-shaped integration: let a student pick an exam, sit a timed past paper, and see a scored result — backed by verified MirrorMingo content.
We use the TypeScript SDK; the shape is identical in every language.
Architecture
Browser / app ──► Your backend ──► MirrorMingo Exam API
(holds the API key)
Keep the API key on your server. The browser talks to your backend; your backend talks to MirrorMingo. This keeps the key secret and lets you add your own auth, caching and analytics.
1. Let the student choose an exam
// GET /api/exams (your backend)
app.get("/api/exams", async (req, res) => {
const exams = await mm.exams.list({ country: req.query.country as string });
res.json(exams);
});
Exam metadata (names, sections, scoring) changes rarely — cache it for a day.
2. List verified past papers
app.get("/api/exams/:examKey/papers", async (req, res) => {
const catalog = await mm.mockExams.listPapers(req.params.examKey);
res.json(catalog);
});
Each paper has a stable paper_id grouped under a year. Render a year picker.
3. Start a timed attempt
app.post("/api/exams/:examKey/start", async (req, res) => {
const attempt = await mm.mockExams.open(req.params.examKey, {
paperId: req.body.paperId,
questionLimit: 20,
});
// Persist attempt.attempt_id against the signed-in student so a refresh
// resumes the same attempt. Start your countdown from the exam's duration.
res.json(attempt);
});
For long papers, page with mm.mockExams.questions(examKey, { paperId, questionOffset }).
has_visual: true marks questions that reference a figure — render a note for those.
4. Submit and score
app.post("/api/exams/:examKey/submit", async (req, res) => {
const result = await mm.mockExams.submit(req.params.examKey, {
attemptId: req.body.attemptId,
answers: req.body.answers, // { "1": "C", "2": "A", ... }
status: req.body.timedOut ? "expired" : "submitted",
});
res.json(result.feedback);
});
feedback carries the score and per-question correctness/explanations.
5. (Optional) React to scoring with webhooks
Instead of blocking the UI on scoring, subscribe to mock_attempt.scored and
update the student's dashboard when the event arrives — see
Webhooks.
Production checklist
- API key stored in a secret manager, never shipped to the client
- Exam/paper metadata cached (≥1 day)
-
attempt_idpersisted per student so attempts survive a refresh - Server-side countdown; submit with
status: "expired"on timeout - Handle
429with backoff (the SDK does this automatically) - Sandbox used in CI; production key only in prod