# 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](/docs/tokens); 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.
