Spaces:
Sleeping
Sleeping
File size: 2,675 Bytes
2c8b437 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # Backend HTTP API
**Source of truth: the OpenAPI schema**, served live at `/docs` and
`/openapi.json`, and committed as `frontend/openapi.snapshot.json`
(CI regenerates it and fails on drift β see
`scripts/generate-frontend-api-types.sh`). This page is a map, not a
second contract; when in doubt, the schema wins.
## Authentication model
`POST /api/jobs` returns a **capability token** once (`job_token`);
only its SHA-256 hash is stored. Every job endpoint requires it via the
`X-Job-Token` header. Missing/wrong token β **404** (job existence
never leaks). The token is **never accepted in a URL**.
Header-less surfaces use short-lived signed credentials (`?sig=`),
scoped to one job and one purpose:
- **events** β `POST /api/jobs` also returns `events_url`
(an events-scoped `?sig=` valid for the run's timeout budget), for
`EventSource`.
- **images** β `GET β¦/layout` appends a 15-minute images-scoped
`?sig=` to each `image_url`, for `<img>`.
## Routes
| Route | Purpose |
|---|---|
| `POST /api/providers/models` | List models for a provider + API key |
| `POST /api/jobs` | Multipart upload (`files`, `provider`, `api_key`, `model`, optional `geometric_pairing`) β `{job_id, job_token, events_url}` |
| `GET /api/jobs/{id}` | Authoritative status snapshot (`JobStatusResponse`) |
| `POST /api/jobs/{id}/cancel` | Cooperative cancellation β idempotent, 202, body = current status |
| `GET /api/jobs/{id}/events` | SSE stream (auth via `?sig=` or header) |
| `GET /api/jobs/{id}/download` | Corrected XML (single file) or ZIP |
| `GET /api/jobs/{id}/trace` | The run's versioned `CorrectionReport` (per-line traces) |
| `GET /api/jobs/{id}/diff` | OCR vs corrected, per page/line |
| `GET /api/jobs/{id}/layout` | Blocks/lines with ALTO coordinates + signed `image_url`s |
| `GET /api/jobs/{id}/images/{name}` | Source scan image (auth via `?sig=` or header) |
| `GET /health`, `/health/live`, `/health/ready` | Probes β `ready` includes storage, frontend (when promised) and load gauges |
Job state machine: `queued β started β running β completed |
completed_with_fallbacks | failed`, plus `cancel_requested β cancelled`.
Terminal jobs are evicted after a TTL (default 1 h); artefacts live
under `{JOB_STORAGE_DIR}/{job_id}/` (`input/`, `output/`, `images/`).
## SSE events
Event names are defined by `corrigenda.core.schemas.PipelineEventType`
(the enum is the wire contract) and mirrored by
`frontend/src/hooks/useJobStream.ts::EVENTS`;
`backend/tests/test_sse_event_contract.py` fails CI on any drift.
Terminal events (`completed`, `failed`, `cancelled`) have guaranteed
delivery and are synthesised for late subscribers.
|