The reference registry runs at https://openseek.duckdns.org. It answers JSON over HTTP and serves the preview assets themselves from /s/. Endpoints are listed below as open or keyed; a keyed one answers 401 without a valid key.
GET /v1/sprites?imdb_id=tt0111161&duration_ms=8280000
Host: openseek.duckdns.org
X-API-Key: <your key>
imdb_id or tmdb_id — the metadata id of the title. Either one identifies it; supply one, not both.duration_ms — the runtime the player reports, in milliseconds. The registry uses it to choose between indexed versions.X-API-Key — the header carrying the key on every keyed route.Episodes are looked up with show_imdb_id or show_tmdb_id plus season and episode. A lookup has no size parameter: the registry serves one tile size, 320×180.
GET /v1/status — service state: ok, titles, versions, service.GET /v1/catalog — browsable index of everything indexed. Every version carries vtt_url, cue_count, interval_s, width, height, status and covered_until_ms. Catalogue metadata only.GET /v1/titles?imdb_id=… — all versions of one title.GET /v1/keys/validate — key self-check. Not quota-gated: it never counts usage. Returns 200 {valid, name} for a known key and 401 {valid: false} for an unknown or missing one.GET /s/… — static VTT and sheet files. Long cache headers on sheets, which are immutable once written.GET /v1/requests — the backlog read. It stays open, but nothing can write to it any more, so it answers empty unless an operator filled it in themselves.GET /v1/sprites?… — the lookup. Returns vtt_url, version, status, covered_until_ms, source_duration_ms and scale. An unknown title is a 404.POST /v1/contribute — contributor upload, multipart/form-data with a meta part carrying the title block as JSON, a vtt part carrying thumbnails.vtt, and the sheets as sheet-*.jpg parts.POST /v1/register — upsert a title and insert a version directly. For population time.POST /v1/contributions/<id>/verify — internal-consistency check on a quarantined upload.POST /v1/contributions/<id>/promote — move a verified contribution into the catalogue.GET /v1/contributions/<id> — the state of one contribution.Public intake is closed. POST /v1/contribute is the only public write, because the registry will not download a video URL supplied by a stranger: an open enqueue route would let anyone hand this host a URL to fetch, content it has no right to. There is a client that captures previews from the video a viewer is already playing, so there is nothing left to ask for.
POST /v1/jobs and POST /v1/requests therefore answer 404, with a body naming the replacement:
{"error": "public intake is closed - POST previews you captured with POST /v1/contribute"}
That is a deliberate 404, not a missing route and not a key problem: it comes back the same way with no key, so it never reads as "get a key and try again". POST /v1/jobs/lease, POST /v1/jobs/<id>/ack and POST /v1/jobs/<id>/fail still exist and still need a key, but they are the operator's own worker routes: something inside the deployment leases work it queued itself. They are not part of the public API and are not documented for clients.
A key does not bypass verification. Promotion refuses a contribution that has not been verified, and verification is a check on the upload itself: the WebVTT must parse, every cue must reference a sheet that was uploaded, sampled tiles must decode as non-blank JPEGs, the tile boxes must lie inside the sheet image, and the cue count and interval must be plausible.
Signing in with a Google account issues a key for the hosted registry, up to four active keys per account. The key is shown once, on a page that does not cache. Sign in with Google to get an API key.
Self-hosting needs no account at all: you run the registry, so you mint your own keys on your own host. See self-hosting.
On a registry host, an operator mints a key with:
python3 mint_key.py <name>
The key is printed once and only a hash of it is stored — a sha256 digest plus a six-character prefix for identification — so it cannot be shown again. Mint a replacement and revoke the old one by that prefix:
DELETE FROM keys WHERE key_prefix='<old prefix>';
curl -H 'X-API-Key: <your key>' \
'https://openseek.duckdns.org/v1/sprites?imdb_id=tt0111161&duration_ms=8280000'
{
"media_type": "movie",
"title": "The Shawshank Redemption",
"imdb_id": "tt0111161",
"vtt_url": "https://openseek.duckdns.org/s/tt0111161-v1/thumbnails.vtt",
"version": 1,
"source_duration_ms": 8280000,
"scale": 1.0,
"status": "complete",
"covered_until_ms": 8280000
}
vtt_url may point at object storage rather than at the registry. Fetch it, resolve the sheet names it references against the directory it came from, and do not rebuild those URLs from the origin. The lifecycle is described step by step on the SDK page.