REST API

The dashboard, the student player, and the MCP server all run on one API — there is no private surface. Machines authenticate with a bearer token; the endpoints below are the useful subset.

Question bank

GET  /api/tests/bank?topic=&difficulty=&lang=&q=&limit=&offset=
POST /api/tests/bank            one question (schema: /docs/json-import)
POST /api/tests/bank/import     {"questions":[…]} batch, per-item report
PUT  /api/tests/bank/:id/translations/:lang

Tests

POST /api/tests/manage                     create draft
POST /api/tests/manage/:id/sections        {title?, marking, duration_minutes?}
POST /api/tests/manage/:id/sections/:sid/questions   {question_ids:[…]} or {pool:{count,…}}
POST /api/tests/manage/:id/roster          {rows:[{name,email?,phone?}]}
POST /api/tests/manage/:id/publish         {slot:"free"|"pack"|"pro"}
GET  /api/tests/manage/:id/links
POST /api/tests/manage/:id/invite          preview → …/invite/confirm queues mail

Results

GET   /api/tests/results/:testId
GET   /api/tests/results/:testId/attempt/:attemptId
PATCH /api/tests/results/:testId/attempt/:attemptId/answer   {question_id, marks}
POST  /api/tests/results/:testId/publish
GET   /api/tests/results/:testId/export.csv

Errors are machine-readable ({"error":"language_gaps","gaps":[…]}), amounts are paise, times are ISO-8601 UTC, list endpoints paginate with limit/offset. The MCP tools are thin wrappers over these — anything the agent can do, plain HTTP can do.