video-accessibility/docs/project/api_spec.md
Vadym Samoilenko a3b300b76a docs: add canonical documentation + audit cleanup
- AGENTS.md: canonical project entry point (Quick Nav, pipeline, constraints)
- docs/: complete docs tree — architecture, API spec, DB schema, infra,
  runbook, requirements, tech stack, principles, reference ADRs, guides,
  tasks backlog, testing strategy
- tests/README.md: test commands, structure, known gaps
- README.md / CLAUDE.md / DEPLOYMENT.md: updated with canonical doc links
- .archive/: backup of pre-documentation-pipeline originals
- backend/uv.lock: uv dependency lockfile
- Delete committed __pycache__ .pyc files (should have been gitignored)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:22:51 +01:00

198 lines
7.5 KiB
Markdown

# API Specification — Accessible Video Processing Platform
<!-- SCOPE: api-spec | owner: ln-113 | generated: 2026-04-29 -->
**Base URL (production):** `https://ai-sandbox.oliver.solutions/video-accessibility-back`
**Base URL (local):** `http://localhost:8003`
**OpenAPI docs:** `{base_url}/docs` (Swagger UI)
All endpoints require `Authorization: Bearer <access_token>` except `/auth/login`, `/auth/refresh`, `/auth/microsoft/*`, and `/health`.
---
## Authentication
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| POST | `/api/v1/auth/login` | None | Email/password login; returns access token + sets refresh cookie |
| POST | `/api/v1/auth/refresh` | Cookie | Exchange refresh cookie for new access token |
| POST | `/api/v1/auth/logout` | Bearer | Revoke refresh token, clear cookie |
| POST | `/api/v1/auth/microsoft/callback` | None | Microsoft SSO callback; validates OIDC token |
| GET | `/api/v1/auth/microsoft/login` | None | Redirect to Microsoft login |
| POST | `/api/v1/auth/change-password` | Bearer | Change own password |
**Login response fields:**
| Field | Type | Notes |
|-------|------|-------|
| access_token | string | JWT, 15-minute TTL |
| token_type | string | Always "bearer" |
| user | object | User profile (id, email, role, org_id) |
---
## Jobs
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/jobs` | ALL | List jobs (role-filtered: client sees own, reviewer/admin see all) |
| POST | `/api/v1/jobs` | CLIENT, ADMIN | Create job with MP4 upload |
| GET | `/api/v1/jobs/{id}` | ALL | Job detail with current status + outputs |
| DELETE | `/api/v1/jobs/{id}` | ADMIN | Delete job and GCS files |
| GET | `/api/v1/jobs/{id}/downloads` | ALL | Signed download URLs for deliverables (24h expiry) |
| POST | `/api/v1/jobs/{id}/actions/approve` | REVIEWER, ADMIN | Approve job at current QC stage |
| POST | `/api/v1/jobs/{id}/actions/reject` | REVIEWER, ADMIN | Reject job with reason |
| POST | `/api/v1/jobs/{id}/actions/feedback` | REVIEWER, ADMIN | Send QC feedback without rejection |
| POST | `/api/v1/jobs/{id}/actions/retry` | ADMIN | Retry failed task (TTS_FAILED, RENDER_FAILED) |
**Job object key fields:**
| Field | Type | Notes |
|-------|------|-------|
| _id | string | MongoDB ObjectId |
| status | string | JobStatus enum — see architecture.md |
| org_id | string | Organisation that owns the job |
| source_language | string | BCP-47 language code |
| requested_outputs | array | Output language codes requested |
| outputs | object | Per-language GCS paths |
| language_qc | object | Per-language QC state |
| created_at | datetime | ISO 8601 |
| updated_at | datetime | ISO 8601 |
| error | string | Last error message if failed |
---
## VTT Management
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/jobs/{id}/vtt/{lang}` | REVIEWER, ADMIN | Get VTT content for language |
| PATCH | `/api/v1/jobs/{id}/vtt/{lang}` | REVIEWER, LINGUIST, ADMIN | Update VTT content (auto-snapshots before save) |
| POST | `/api/v1/vtt/adjust-timing` | REVIEWER, ADMIN | Bulk shift all cue timings |
---
## VTT Version Control
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/jobs/{id}/vtt-versions/{lang}` | REVIEWER, ADMIN | List version history |
| GET | `/api/v1/jobs/{id}/vtt-versions/{lang}/{version_id}` | REVIEWER, ADMIN | Get specific version content |
| POST | `/api/v1/jobs/{id}/vtt-versions/{lang}/{version_id}/restore` | REVIEWER, ADMIN | Restore a previous version (creates new snapshot) |
| GET | `/api/v1/jobs/{id}/vtt-versions/{lang}/diff` | REVIEWER, ADMIN | Diff two versions (`?from=v1_id&to=v2_id`) |
---
## Language QC
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/jobs/{id}/language-qc` | REVIEWER, PM, ADMIN | Get per-language QC status for all languages |
| POST | `/api/v1/jobs/{id}/language-qc/{lang}/assign` | PM, ADMIN | Assign linguist to language |
| POST | `/api/v1/jobs/{id}/language-qc/{lang}/approve` | LINGUIST (assigned), PM, ADMIN | Approve language |
| POST | `/api/v1/jobs/{id}/language-qc/{lang}/reject` | LINGUIST (assigned), PM, ADMIN | Reject language with reason |
| POST | `/api/v1/jobs/{id}/language-qc/{lang}/feedback` | LINGUIST (assigned), PM, ADMIN | Send feedback without rejection |
---
## Glossaries
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/glossaries` | ALL | List glossaries for current org |
| POST | `/api/v1/glossaries` | ADMIN | Create glossary |
| GET | `/api/v1/glossaries/{id}` | ALL | Get glossary with terms |
| PUT | `/api/v1/glossaries/{id}` | ADMIN | Update glossary metadata |
| DELETE | `/api/v1/glossaries/{id}` | ADMIN | Delete glossary |
| POST | `/api/v1/glossaries/{id}/terms` | ADMIN | Add term |
| DELETE | `/api/v1/glossaries/{id}/terms/{term_id}` | ADMIN | Delete term |
---
## Files
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| POST | `/api/v1/files/upload-url` | CLIENT, ADMIN | Get signed GCS upload URL |
| GET | `/api/v1/files/{job_id}/{path}` | ALL | Get signed download URL |
---
## Users and Organisations
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/users/me` | ALL | Current user profile |
| GET | `/api/v1/organizations` | ADMIN | List organisations |
| POST | `/api/v1/organizations` | ADMIN | Create organisation |
| GET | `/api/v1/organizations/{id}/members` | PM, ADMIN | List org members |
| POST | `/api/v1/organizations/{id}/invite` | PM, ADMIN | Invite member |
| DELETE | `/api/v1/organizations/{id}/members/{user_id}` | PM, ADMIN | Remove member |
---
## Admin
| Method | Path | Roles | Description |
|--------|------|-------|-------------|
| GET | `/api/v1/admin/users` | ADMIN | List all users |
| PATCH | `/api/v1/admin/users/{id}` | ADMIN | Update user role or status |
| GET | `/api/v1/admin/audit-log` | ADMIN, PM | Query audit log |
---
## WebSocket
| Path | Auth | Description |
|------|------|-------------|
| `WS /api/v1/ws/jobs/{id}` | Query param `token=<access_token>` | Real-time job status updates |
| `WS /api/v1/ws/org/{org_id}` | Query param `token=<access_token>` | Org-scoped event stream |
**Message format:**
| Field | Type | Notes |
|-------|------|-------|
| type | string | `job_status_update`, `notification`, `ping` |
| job_id | string | Job ObjectId |
| status | string | New JobStatus value |
| updated_at | datetime | ISO 8601 |
---
## Health
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/health` | None | Returns `{"status":"healthy","version":"1.0.0"}` |
| GET | `/metrics` | None (internal) | Prometheus metrics |
---
## Error Response Format
All errors return:
| Field | Type | Notes |
|-------|------|-------|
| detail | string | Human-readable error message (never internal exception text) |
Common status codes:
| Code | Meaning |
|------|---------|
| 400 | Bad request / validation error |
| 401 | Unauthenticated or invalid token |
| 403 | Forbidden — insufficient role |
| 404 | Resource not found |
| 422 | Pydantic validation error |
| 429 | Rate limit exceeded |
| 500 | Internal server error (details logged, not returned) |
---
## Maintenance
**Update triggers:** New endpoint added, request/response schema changed, auth flow change.
**Verification:** All endpoints listed here exist in `backend/app/api/v1/routes_*.py`. OpenAPI schema at `/docs` matches this table.
<!-- END SCOPE: api-spec -->