OpenSeek Docs

This is the short reference for the hosted registry at https://openseek.duckdns.org. One lookup returns a WebVTT cue track; each cue names a 320×180 tile inside a JPEG sheet. Start at OpenSeek, manage keys on the dashboard, and read the client lifecycle on the SDK page.

1. Quickstart

One title takes three requests. The lookup is keyed; the VTT and the sheets are open.

  1. Look the title up. Send the metadata id and the runtime the player reports, with the key in an X-API-Key header:

    curl -H 'X-API-Key: <your key>' \
      'https://openseek.duckdns.org/v1/sprites?imdb_id=tt0111161&duration_ms=8280000'

    The response carries the cue track URL, which version was matched, and how far coverage reaches:

    {
      "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
    }
  2. Fetch the VTT. No key is needed for this request:

    curl 'https://openseek.duckdns.org/s/tt0111161-v1/thumbnails.vtt'
  3. Crop the tile. Each cue payload has the form sheet-320x180-0.jpg#xywh=320,0,320,180: a sheet name, then the tile box inside it. Resolve the sheet name against the directory the vtt_url came from, fetch the sheet, and crop the box described by x,y,w,h. The tile is 320×180, the only size served.

2. Authentication

EndpointGateNote
GET /v1/spriteskeyedThe lookup. 401 without a valid X-API-Key header.
GET /v1/keys/validateopenKey self-check: present the key, get 200 {valid, name} or 401 {valid: false}. Never counts quota.
GET /s/…openVTT and sheets. Sheets carry long cache headers; they are immutable once written.
GET /v1/status, GET /v1/catalog, GET /v1/titles, GET /v1/requestsopenCatalogue metadata only. The requests read stays open but is permanently empty.
POST /v1/contribute, POST /v1/register, contribution verify / promote / get, jobs lease / ack / failkeyedWrites and worker routes. The jobs routes are the operator's own and are not part of the public API.

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 and only its sha256 plus a six-character prefix is stored. See and revoke your keys on the dashboard. Self-hosting needs no account: mint keys on your own host; see self-hosting.

Two 401 shapes, and only these: {"error": "api key required (X-API-Key)"} when the header is missing, {"error": "invalid api key"} when it is unknown or revoked. A revoked account's keys answer the same way.

3. Lookup

A successful lookup answers:

{
  "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
}

version is the indexed version chosen; source_duration_ms is that copy's runtime and scale is the requested duration divided by it, so a player reporting a slightly different runtime still lands on the right cue. status and covered_until_ms say how far previews reach (see next section). vtt_url is absolute and may point at object storage rather than the registry: resolve sheet names against its directory, never rebuild them from the origin.

4. VTT and coverage

The cue track is WebVTT: a WEBVTT header, then one cue per frame:

WEBVTT

00:00:00.000 --> 00:00:10.000
sheet-320x180-0.jpg#xywh=0,0,320,180

00:00:10.000 --> 00:00:20.000
sheet-320x180-0.jpg#xywh=320,0,320,180

A full bundle is positional — cue i covers second i × interval_s — but a bundle captured part-way through a title starts where it started, so never index cues by position. For a scrub position, take the last cue whose start is less than or equal to the position, after checking coverage first: when status is pending, previews exist only up to covered_until_ms, and a floor lookup past that point returns a stale tail tile instead of nothing. Past the one-hour mark timestamps start with 01:, so parse both two- and three-component times.

Two empty states, and they look different:

  1. Not indexed. The lookup itself answers 404 {"error": "not indexed"}. There is no VTT to fetch; show no preview.
  2. Past coverage. The lookup succeeds with status: pending but the position is past covered_until_ms. There are cues, just none for this position; show no preview.

5. Limits

6. Errors

StatusBodyWhen
400{"error": "duration_ms required"}Lookup without a runtime.
400{"error": "tmdb_id|imdb_id|show_* required"}Lookup without any metadata id.
400{"error": "bad json"} / {"error": "media_type+title+duration_ms required"}Register with an unreadable or incomplete body.
400{"error": "title-block JSON field required"} and kindred multipart errorsContribute without the title block, the VTT, or any sheet.
401{"error": "api key required (X-API-Key)"}Keyed route, header missing.
401{"error": "invalid api key"}Keyed route, key unknown or revoked.
401{"valid": false}Validate with a missing or unknown key.
404{"error": "not indexed"}No title, or no version within ±240 s.
404{"error": "version not found"}Pinned version does not exist on the title.
404{"error": "public intake is closed - POST previews you captured with POST /v1/contribute"}POST /v1/jobs or POST /v1/requests. Deliberate and unauthed, so it never reads as a key problem.
409{"error": "version_no taken"}Register pins a version slot already held.
413{"error": "body too large (50MB cap)"}Contribute body over 50 MB.
429{"error": "quota exceeded"}Not returned today: quota is counted, never enforced. Reserved for the enforcing flag.

Sign-in has three of its own: 404 {"error": "auth disabled"} while it is unconfigured, 429 after ten starts per address per ten minutes, and 503 when the store is unavailable. The full client lifecycle is on the SDK page; every endpoint with its gate is on the API page.

OpenSeek · Dashboard · SDK · API · Self-hosting · openseek-sdk · NuvioMobile · openseek-site. MIT licensed.