2026-09-04 17:34:03 -05:00
# Aurora Core — API
Base path: `/api/v1` . Interactive OpenAPI docs are available at `/docs` in
any environment where `AURORA_API_DOCS_ENABLED=true` (default; set to
`false` to hide docs in production — section 32).
All responses are JSON, built from Pydantic response schemas
(`app/schemas/` ), never from serialized ORM objects (section 18). Errors use
a consistent envelope:
```json
{ "error" : { "code" : "movie_not_found" , "message" : "No such movie: aur_movie_..." } }
```
## Health
| Method | Path | Notes |
|---|---|---|
| GET | `/health` and `/api/v1/health` | Liveness only. |
| GET | `/ready` and `/api/v1/ready` | Checks PostgreSQL (always) and Redis (if `REDIS_REQUIRED=true` ). |
## Search
| Method | Path | Notes |
|---|---|---|
| GET | `/api/v1/search?q=...&limit=10` | Searches movies, series, people, collections, companies. `limit` (1-50) caps results **per type** . |
```json
GET /api/v 1 /search?q=the% 20 matrix
{
"query" : "the matrix" ,
"movies" : [ { "id" : "aur_movie_..." , "type" : "movie" , "title" : "The Matrix" , "release_date" : "1999-03-30" , "poster_path" : "https://..." } ],
"series" : [],
"people" : [],
"collections" : [ { "id" : "aur_collection_..." , "name" : "The Matrix Collection" } ],
"companies" : [],
"total_results" : 2
}
```
## Movies
| Method | Path |
|---|---|
| GET | `/api/v1/movies/{aurora_id}` |
| GET | `/api/v1/movies/{aurora_id}/credits` |
| GET | `/api/v1/movies/{aurora_id}/images` |
| GET | `/api/v1/movies/{aurora_id}/videos` |
`GET /api/v1/movies/{aurora_id}` (cached, see `docs/architecture.md#caching` ):
```json
{
"id" : "aur_movie_01m1q7p1c..." ,
"type" : "movie" ,
"title" : "The Matrix" ,
"original_title" : "The Matrix" ,
"overview" : "..." ,
"tagline" : "Welcome to the Real World" ,
"status" : "released" ,
"original_language" : "en" ,
"release_date" : "1999-03-30" ,
"runtime" : 136 ,
"budget" : 63000000 ,
"revenue" : 463517383 ,
"popularity" : 45.5 ,
"vote_average" : 8.2 ,
"vote_count" : 24000 ,
"adult" : false ,
"genres" : [{ "id" : "aur_genre_..." , "name" : "Action" }],
"keywords" : [{ "id" : "aur_keyword_..." , "name" : "dystopia" }],
"cast" : [{ "id" : "aur_credit_..." , "person" : { "id" : "aur_person_..." , "name" : "Keanu Reeves" , "profile_path" : null }, "character" : "Neo" , "billing_order" : 0 }],
"crew" : [{ "id" : "aur_credit_..." , "person" : { "id" : "aur_person_..." , "name" : "Lana Wachowski" }, "department" : "Directing" , "job" : "Director" }],
"companies" : [{ "id" : "aur_company_..." , "name" : "Village Roadshow Pictures" , "company_type" : "production_company" }],
"collection" : { "id" : "aur_collection_..." , "name" : "The Matrix Collection" },
"images" : { "posters" : [ ... ], "backdrops" : [ ... ], "logos" : [ ... ] },
"videos" : [{ "id" : "aur_vid_..." , "type" : "trailer" , "site" : "YouTube" , "url" : "https://www.youtube.com/watch?v=..." , "is_official" : true }],
"external_ids" : { "tmdb" : "603" , "imdb" : "tt0133093" },
"created_at" : "..." ,
"updated_at" : "..."
}
```
## Series / Seasons / Episodes
| Method | Path |
|---|---|
| GET | `/api/v1/series/{aurora_id}` |
| GET | `/api/v1/series/{aurora_id}/seasons` |
| GET | `/api/v1/seasons/{aurora_id}` |
| GET | `/api/v1/episodes/{aurora_id}` |
Series detail includes `networks` and `companies` as separate lists (a TV
network and a production company are both `Company` rows distinguished by
`company_type` — see `docs/database.md` ), plus `creators` (series-level
"Creator" credits) alongside `cast` /`crew` .
## People
| Method | Path |
|---|---|
| GET | `/api/v1/people/{aurora_id}` |
2026-09-04 20:00:15 -05:00
| GET | `/api/v1/people/{aurora_id}/credits` (movie and series filmography; guest-star episode credits are aggregated to one row per series with `episode_count` , not one row per episode) |
2026-09-04 17:34:03 -05:00
## Collections / Companies
| Method | Path |
|---|---|
| GET | `/api/v1/collections/{aurora_id}` |
| GET | `/api/v1/companies/{aurora_id}` |
## Administrative (section 17: "separately protected")
Require header `X-API-Key: <one of AURORA_ADMIN_API_KEYS>` . Never exposed to
public clients — mount behind a separate Traefik router/ACL in production if
you want network-level isolation too.
| Method | Path | Body | Notes |
|---|---|---|---|
| POST | `/api/v1/admin/ingest/movie` | `{"tmdb_id": "603"}` | Enqueues an arq job; returns `{"job_id": "...", "status": "enqueued"}` immediately (section 15: ingestion never runs inline in a request). |
| POST | `/api/v1/admin/ingest/person` | `{"tmdb_id": "6384"}` | Same, for a person profile. |
2026-09-04 19:43:56 -05:00
| POST | `/api/v1/admin/ingest/series` | `{"tmdb_id": "1396"}` | Ingests the series and season *stubs* (number, title, air date, poster) — no episodes yet. |
| POST | `/api/v1/admin/ingest/season` | `{"tmdb_id": "1396", "season_number": 1}` | Ingests one season's full episode list. Requires the series to already be ingested (`ingest/series` first) — fails with a clear error otherwise. |
2026-09-04 17:34:03 -05:00
| GET | `/api/v1/admin/ingest/jobs/{job_id}` | — | Poll job status: `pending` → `running` → `succeeded` /`failed` /`retrying` . |
## Errors
| Status | When |
|---|---|
| 404 | Entity not found, or the ID is well-formed but the wrong entity type (`aur_person_...` passed to `/movies/{id}` ) |
| 422 | Request validation failure (e.g. missing/invalid query params) |
| 429 | Rate limit exceeded (`Retry-After` header set) |
| 401 | Missing/invalid `X-API-Key` on an admin endpoint |
| 503 | Admin API called with `AURORA_ADMIN_API_KEYS` unset, or the job queue is unavailable |
## Known limitations
- No pagination on list-shaped responses yet beyond search's `limit`
(movie/series lists like recommendations return everything). Cursor-based
pagination using the Aurora ID's inherent creation-order sort (see
`docs/database.md#aurora-ids-vs-primary-keys` ) is the natural next step.
2026-09-04 20:00:15 -05:00
- `/people/{id}/credits` covers movies and series (episode guest-star
credits rolled up per series). It does not yet expose a per-episode
breakdown for those guest appearances (just the aggregate
`episode_count` ) — the individual episode `Credit` rows exist in the
database if that's ever needed.