The API¶
345 operations across 279 paths, in 31 tag groups.
-
Reference — every endpoint, rendered from the OpenAPI document with Scalar.
-
The API as a contract — addressing, versioning, the error envelope, tokens, rate limits, and the two rules a client should not try to work around.
The tag groups¶
access · admin · ai-mode · articles · attempts · auth ·
categories · collections · contact · documents · drafts ·
exam results · exams · favorites · feedback · flashcards · folders ·
glossary · health · media · public · question-categories ·
questions · quizzes · search · share · study-plans · study-tools ·
tags · teach · tts
Addressing¶
Everything is under /api/v1. /api/… reaches the same route and always
will — it is the address the web application in this repository was written
against, and an address that has shipped is a promise.
It is a rewrite, not a second mount, so the two cannot drift and the OpenAPI document describes each endpoint once rather than twice.
Two addresses sit outside the scheme deliberately:
| Path | Why |
|---|---|
/api/health |
Monitoring points at it and nobody edits that for a year. It also answers at /api/v1/health. |
/uploads/… |
An image's URL gets written into markdown and shared. Those must not move. |
The live documents¶
The running application serves its own:
GET /api/openapi.json— the schema/api/docs— Swagger UI/api/redoc— ReDoc
The copy in this site is a committed snapshot, so the documentation renders without a backend behind it. Regenerate it whenever a route changes:
docker exec -w /app -e PYTHONPATH=/app quiz-backend-1 \
python -c "import json;from app.main import app;print(json.dumps(app.openapi()))" \
> docs/openapi.json
Authentication¶
Every endpoint but /api/health, /api/v1/public/…, the share routes and the
SSO handshake needs a bearer token.
Get one through the SSO exchange. There is no
password grant — POST /auth/login answers 410.