### POST /api/keys response example Source: https://skipdb.tv/docs Example JSON response for generating or resetting an API key. The plaintext key is returned only once. ```json // POST response (201) { "key": "skdb_live_...", "prefix": "skdb_live_ab12", "message": "Here is your API key. ..." } ``` -------------------------------- ### GET /api/titles/search curl example Source: https://skipdb.tv/docs Example curl command to search titles by name or IMDb ID. ```bash curl "https://api.skipdb.tv/api/titles/search?q=Breaking%20Bad" ``` -------------------------------- ### Fetch segments via GET /api/segments Source: https://skipdb.tv/docs Example request and response for retrieving segment data for a specific episode using IMDb ID, season, episode, and stream duration. ```bash curl "https://api.skipdb.tv/api/segments?imdb_id=tt0903747&season=1&episode=1&duration=2820" { "imdb_id": "tt0903747", "season": 1, "episode": 1, "segments": { "intro": { "start_ms": 61000, "end_ms": 91000, "match": "exact", "adjusted": false, "offset_ms": 0, "confidence": 0.93 }, "recap": null, "outro": { "start_ms": 2760000, "end_ms": 2820000, "match": "shifted", ... }, "preview": { "start_ms": 2700000, "end_ms": 2760000, "match": "out-of-range", ... } }, "intro_length_estimate_ms": 30000 } ``` -------------------------------- ### POST /api/keys/anonymous response example Source: https://skipdb.tv/docs Example JSON response for obtaining an anonymous API key. The plaintext key is returned only once and cannot be recovered. ```json // POST response (201) { "key": "skdb_live_...", "prefix": "skdb_live_cd34", "message": "Here is your anonymous API key. ..." } ``` -------------------------------- ### Submit a segment via POST /api/segments Source: https://skipdb.tv/docs Example request and response for submitting a new segment. Requires an Authorization header with a valid API key. ```bash curl -X POST https://api.skipdb.tv/api/segments \ -H "Authorization: Bearer skdb_xxx" \ -H "Content-Type: application/json" \ -d '{ "imdb_id": "tt0903747", "season": 1, "episode": 1, "segment_type": "intro", "start_ms": 61000, "end_ms": 91000, "duration_ms": 2820000 }' { "id": 42, "status": "approved", "auto_approved": true, "reasons": ["matches an existing approved segment (consensus)"], "message": "Submission accepted and published.", "license": "ODbL 1.0 + Service Provider Reciprocity ..." } ``` -------------------------------- ### DELETE /api/segments/{id} response example Source: https://skipdb.tv/docs Example JSON response for a successful segment deletion. ```json { "id": 42, "deleted": true } ``` -------------------------------- ### PATCH /api/segments/{id} response example Source: https://skipdb.tv/docs Example JSON response for a successful segment update. The segment is sent back to review and may change status. ```json { "id": 42, "status": "pending", "auto_approved": false, "reasons": [...], "message": "Submission updated and sent back to review." } ``` -------------------------------- ### POST /api/segments/{id}/vote response example Source: https://skipdb.tv/docs Example JSON response after voting on a segment, showing the updated vote tally. ```json { "segment_id": 42, "your_vote": 1, "votes": { "up": 6, "down": 1, "score": 5 } } ``` -------------------------------- ### POST /api/keys/anonymous Source: https://skipdb.tv/docs Get an API key without signing up. Creates a blank, login-less user behind the scenes and returns its key (plaintext, once) — there's no account to recover it from, so save it immediately. Rate-limited per IP (5/hour). DELETE with the same key revokes it. ```APIDOC ## POST /api/keys/anonymous ### Description Get an API key without signing up. Creates a blank, login-less user behind the scenes and returns its key (plaintext, once) — there's no account to recover it from, so save it immediately. Rate-limited per IP (5/hour). DELETE with the same key (via Authorization or X-API-Key) revokes it. ### Method POST ### Endpoint /api/keys/anonymous ### Response #### Success Response (201) - **key** (string) - The plaintext API key. - **prefix** (string) - The key prefix. - **message** (string) - Instructions. #### Response Example { "key": "skdb_live_...", "prefix": "skdb_live_cd34", "message": "Here is your anonymous API key. ..." } ### Error Handling - **429** - more than 5 keys from this IP in an hour (POST) - **401** - missing key (DELETE) - **403** - key belongs to a registered account — manage it from /account instead (DELETE) ``` -------------------------------- ### POST /api/keys Source: https://skipdb.tv/docs Generate or reset your API key. GET returns the active key's prefix (not the secret); POST returns the plaintext key once and revokes any previous key; DELETE revokes it. Not available via API key. ```APIDOC ## POST /api/keys ### Description Generate or reset your API key. GET returns the active key's prefix (not the secret); POST returns the plaintext key once and revokes any previous key; DELETE revokes it. Not available via API key — you can't bootstrap key management from a key. ### Method POST ### Endpoint /api/keys ### Response #### Success Response (201) - **key** (string) - The plaintext API key. - **prefix** (string) - The key prefix. - **message** (string) - Instructions. #### Response Example { "key": "skdb_live_...", "prefix": "skdb_live_ab12", "message": "Here is your API key. ..." } ``` -------------------------------- ### GET /api/titles/{imdbId} Source: https://skipdb.tv/docs Title metadata with the season/episode list and a per-episode coverage matrix (which segment types have data). ```APIDOC ## GET /api/titles/{imdbId} ### Description Title metadata with the season/episode list and a per-episode coverage matrix (which segment types have data). ### Method GET ### Endpoint /api/titles/{imdbId} ### Parameters #### Path Parameters - **imdbId** (string) - Required - The IMDb ID of the title. ### Response #### Success Response (200) - **name** (string) - Title name. - **year** (number | null) - Release year. - **media_type** (string) - "movie" or "series". - **poster_url** (string | null) - Poster URL. - **seasons** (array) - Season list. - **totals** (object) - Aggregate coverage counts. - **episodes** (array) - Per-episode coverage matrix. #### Response Example { "name": "Breaking Bad", "year": 2008, "media_type": "series", "poster_url": null, "seasons": [], "totals": {}, "episodes": [] } ### Error Handling - **400** - invalid IMDb id - **429** - rate limit exceeded (30/min) ``` -------------------------------- ### GET /api/titles/search Source: https://skipdb.tv/docs Search by name or IMDb id. Proxies TMDB (when configured) and always also checks titles already in the database. ```APIDOC ## GET /api/titles/search ### Description Search by name or IMDb id. Proxies TMDB (when configured) and always also checks titles already in the database. ### Method GET ### Endpoint /api/titles/search ### Parameters #### Query Parameters - **q** (string) - Required - Free-text name, or an IMDb id (e.g. tt0903747) for a direct lookup. ### Request Example curl "https://api.skipdb.tv/api/titles/search?q=Breaking%20Bad" ### Response #### Success Response (200) - **provider** (string) - Which source results came from: "tmdb" | "local" | "none". - **results** (array) - TMDB (or fallback) matches. For an IMDb-id query with no metadata match, contains a single placeholder object with a note field — you can still submit segments for it. - **local** (array) - Titles already in SkipDB's database matching by name (name search only). #### Response Example { "provider": "tmdb", "results": [], "local": [] } ### Error Handling - **429** - rate limit exceeded (30/min) ``` -------------------------------- ### GET /api/dump Source: https://skipdb.tv/docs The full open data dump of every approved segment — no user data. Licensed ODbL 1.0 + reciprocity. Cached for an hour; may 302-redirect to a static mirror. ```APIDOC ## GET /api/dump ### Description The full open data dump of every approved segment — no user data. Licensed ODbL 1.0 + reciprocity. This is the guarantee that the data stays free. Cached for an hour; may 302-redirect to a static mirror. ### Method GET ### Endpoint /api/dump ### Response #### Success Response (200) - **segments** (array) - Each row: id, imdb_id, media_type, season, episode, segment_type, start_ms, end_ms, duration_ms, submitted_by (opaque user id, no PII), votes_up, votes_down, score, created_at, updated_at. - **count** (number) - Length of segments. - **generated_at** (string) - ISO 8601 timestamp. #### Response Example { "segments": [], "count": 0, "generated_at": "2025-01-01T00:00:00Z" } ### Error Handling - **429** - rate limit exceeded (6/min) ``` -------------------------------- ### GET /api/segments Source: https://skipdb.tv/docs Fetch the best segment of each type for a movie or episode, adjusted for the requester's stream duration when given. Supports optional filtering by segment type and duration adjustment. ```APIDOC ## GET /api/segments ### Description Fetch the best segment of each type for a movie or episode, adjusted for the requester's stream duration when given. ### Method GET ### Endpoint /api/segments ### Parameters #### Query Parameters - **imdb_id** (string) - Required - IMDb id, e.g. tt0903747. - **season** (integer) - Optional - Omit both season and episode for a movie. - **episode** (integer) - Optional - See season. - **type** (string) - Optional - Restrict to one segment type: intro, recap, outro, preview. Omit to fetch all four. - **duration** (number, seconds) - Optional - Stream length. Strongly recommended — enables duration matching/shifting and improves CDN cache hit rates versus passing ms. - **adjust** (string) - Optional - Default conservative. How to shift timestamps when the stream duration is close but not identical: conservative only shifts earlier (never risks a late skip button), greedy shifts in either direction, none never shifts (still reports out-of-range). ### Response #### Success Response (200) - **segments** (object) - Always has all four keys (intro, recap, outro, preview). If type was passed, the other three keys are always null. - **segments[type]** (object | null) - null means no approved data yet for that type. Otherwise: start_ms, end_ms, match (exact | shifted | agnostic | out-of-range), adjusted (bool), offset_ms (number), and confidence (0–1). - **intro_length_estimate_ms** (number | null) - Median intro length for the season, when 80% of episodes agree within 15s. #### Response Example { "imdb_id": "tt0903747", "season": 1, "episode": 1, "segments": { "intro": { "start_ms": 61000, "end_ms": 91000, "match": "exact", "adjusted": false, "offset_ms": 0, "confidence": 0.93 }, "recap": null, "outro": { "start_ms": 2760000, "end_ms": 2820000, "match": "shifted", ... }, "preview": { "start_ms": 2700000, "end_ms": 2760000, "match": "out-of-range", ... } }, "intro_length_estimate_ms": 30000 } ### Error Handling - **400** - missing/invalid imdb_id, type, adjust, season, episode, or duration - **429** - rate limit exceeded ### Request Example curl "https://api.skipdb.tv/api/segments?imdb_id=tt0903747&season=1&episode=1&duration=2820" ``` -------------------------------- ### POST /api/segments Source: https://skipdb.tv/docs Submit a segment. Submitting implies agreement to publish under ODbL 1.0 + reciprocity. Resubmitting the same episode/type/duration within 24h edits your existing submission instead of creating a duplicate. ```APIDOC ## POST /api/segments ### Description Submit a segment. Submitting implies agreement to publish under ODbL 1.0 + reciprocity (see terms). Resubmitting the same episode/type/duration within 24h edits your existing submission instead of creating a duplicate. ### Method POST ### Endpoint /api/segments ### Parameters #### Request Body - **imdb_id** (string) - Required - IMDb id. - **segment_type** (string) - Required - intro | recap | outro | preview. Fixed once submitted — edit the times via PATCH, not the type. - **season** (integer) - Optional - Omit both for a movie. - **episode** (integer) - Optional - See season. - **start_ms** (number) - Required - Milliseconds. - **end_ms** (number) - Optional - Required for every type except outro, where it defaults to duration_ms if omitted (so at least one of end_ms / duration_ms must be given for an outro). - **duration_ms** (number) - Optional - Stream length in ms. Recommended — improves matching for other requesters. duration_sec accepts the same thing in seconds or a clock string (e.g. "47:00"). ### Request Example curl -X POST https://api.skipdb.tv/api/segments \ -H "Authorization: Bearer skdb_xxx" \ -H "Content-Type: application/json" \ -d '{ "imdb_id": "tt0903747", "season": 1, "episode": 1, "segment_type": "intro", "start_ms": 61000, "end_ms": 91000, "duration_ms": 2820000 }' ### Response #### Success Response (200) - **id** (number) - Submission ID. - **status** (string) - Status of the submission (e.g., approved). - **auto_approved** (boolean) - Whether the submission was auto-approved. - **reasons** (array of strings) - Reasons for the approval. - **message** (string) - Human-readable message. - **license** (string) - License information. #### Response Example { "id": 42, "status": "approved", "auto_approved": true, "reasons": ["matches an existing approved segment (consensus)"], "message": "Submission accepted and published.", "license": "ODbL 1.0 + Service Provider Reciprocity ..." } ### Error Handling - **401** - no session/API key - **422** - schema validation failed (issues[]) or bounds invalid (too short/long, end ≤ start, beyond duration) - **409** - identical approved segment already exists (vote_url returned), or overlaps your own other submission (conflicting_segment_id) - **429** - rate limit exceeded ``` -------------------------------- ### POST /api/segments/{id}/vote Source: https://skipdb.tv/docs Vote a segment up or down. Requires a real, ownable identity — an anonymous key can't vote — and you can't vote on your own submission. ```APIDOC ## POST /api/segments/{id}/vote ### Description Vote a segment up or down. Requires a real, ownable identity — an anonymous key can't vote — and you can't vote on your own submission. ### Method POST ### Endpoint /api/segments/{id}/vote ### Parameters #### Path Parameters - **id** (integer) - Required - The ID of the segment to vote on. #### Request Body - **value** (integer) - Required - 1 = good, -1 = bad, 0 = clear your existing vote. ### Request Example { "value": 1 } ### Response #### Success Response (200) - **segment_id** (integer) - The segment ID. - **your_vote** (integer) - Your vote value. - **votes** (object) - Vote counts: up, down, score. #### Response Example { "segment_id": 42, "your_vote": 1, "votes": { "up": 6, "down": 1, "score": 5 } } ### Error Handling - **400** - invalid segment id or JSON body - **401** - auth required - **403** - own segment, or segment disabled - **404** - segment not found - **422** - value must be 1, -1, or 0 - **429** - rate limit exceeded (60/min) ``` -------------------------------- ### PATCH /api/segments/{id} Source: https://skipdb.tv/docs Edit a submission's times. Re-runs review, so a previously auto-approved segment can drop back to pending if the new values no longer qualify. Owner or moderator/admin access required. ```APIDOC ## PATCH /api/segments/{id} ### Description Edit a submission's times. Re-runs review, so a previously auto-approved segment can drop back to pending if the new values no longer qualify. ### Method PATCH ### Endpoint /api/segments/{id} ### Parameters #### Path Parameters - **id** (integer) - Required - The ID of the segment to edit. #### Request Body All optional — omitted fields keep their current value. - **start_ms** (number) - Optional - Milliseconds. - **end_ms** (number) - Optional - Milliseconds. - **duration_ms** (number) - Optional - duration_sec also accepted. - **clear_duration** (boolean) - Optional - Drop the stored duration_ms. - **segment_type** (string) - Optional - Immutable — passing a different value than the segment already has returns a 422. Delete and resubmit instead. ### Request Example { "start_ms": 1000, "end_ms": 5000 } ### Response #### Success Response (200) - **id** (integer) - The segment ID. - **status** (string) - Status of the segment (approved, pending, rejected, already_approved). - **auto_approved** (boolean) - Whether the segment was auto-approved. - **reasons** (array) - Review reasons. - **message** (string) - Confirmation message. #### Response Example { "id": 42, "status": "pending", "auto_approved": false, "reasons": [...], "message": "Submission updated and sent back to review." } ### Error Handling - **401** - no session/API key - **403** - not your submission and not staff - **404** - segment not found - **422** - bounds invalid or segment_type change attempted - **409** - overlaps your own other submission ``` -------------------------------- ### DELETE /api/segments/{id} Source: https://skipdb.tv/docs Delete a submission. Owner or moderator/admin access required. ```APIDOC ## DELETE /api/segments/{id} ### Description Delete a submission. ### Method DELETE ### Endpoint /api/segments/{id} ### Parameters #### Path Parameters - **id** (integer) - Required - The ID of the segment to delete. ### Response #### Success Response (200) - **id** (integer) - The segment ID. - **deleted** (boolean) - Confirmation of deletion. #### Response Example { "id": 42, "deleted": true } ### Error Handling - **401** - no session/API key - **403** - not your submission and not staff - **404** - segment not found ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.