Skip to content

Timestamps API

The core of OpenSkip - endpoints for querying intro/outro timestamps.

Query Timestamps

GET /api/v1/timestamps

Query timestamps with various filters. This is the main endpoint for media player integrations.

Query Parameters

Parameter Type Description
tvdb_id integer Filter by show's TVDB ID
season integer Filter by season number
episode integer Filter by episode number
episode_id integer Filter by episode database ID
duration_ms integer Filter by file duration in milliseconds
tolerance integer Duration matching tolerance in ms (default: 5000)

Best for Plex, Sonarr, and most media managers:

curl "https://api.openskip.io/api/v1/timestamps?tvdb_id=81189&season=1&episode=1"

Match specific file versions by duration:

curl "https://api.openskip.io/api/v1/timestamps?tvdb_id=81189&season=1&episode=1&duration_ms=3550000"

If you already have the episode ID:

curl "https://api.openskip.io/api/v1/timestamps?episode_id=42"

Response

{
  "items": [
    {
      "id": 1,
      "episode_id": 1,
      "duration_ms": 3550000,
      "intro_start": 0.0,
      "intro_end": 45.500,
      "outro_start": 3420.0,
      "outro_end": 3480.0,
      "recap_start": null,
      "recap_end": null,
      "preview_start": null,
      "preview_end": null,
      "source": "community",
      "confidence": 100,
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 1
}

Get Timestamp

GET /api/v1/timestamps/{timestamp_id}

Get a specific timestamp record by ID.

Example

curl "https://api.openskip.io/api/v1/timestamps/1"

Timestamp Object

Field Type Description
id integer Database ID
episode_id integer Parent episode ID
duration_ms integer File duration in milliseconds
intro_start decimal Intro start time in seconds
intro_end decimal Intro end time in seconds
outro_start decimal Outro/credits start time
outro_end decimal Outro/credits end time
recap_start decimal "Previously on..." start time
recap_end decimal Recap end time
preview_start decimal "Next episode" preview start
preview_end decimal Preview end time
source string Data source (community, official, automated)
confidence integer Confidence score (0-100)
created_at datetime Record creation time
updated_at datetime Last update time

Timestamp Fields Explained

Intro

The opening credits/theme sequence. Typically at the start of the episode.

|--intro--|-------------- episode content --------------|
0      45.5                                           3600

Outro

End credits sequence. Usually at the very end.

|-------------- episode content --------------|--outro--|
0                                           3420      3480

Recap

"Previously on..." segment that summarizes earlier episodes.

|--recap--|--intro--|-------- episode content ---------|
0        60      105.5                                3600

Preview

"Next time on..." or "Scenes from next episode" segment.

|-------- episode content --------|--outro--|--preview--|
0                               3360      3420       3480

Duration Matching

Different releases of the same episode may have different durations (different cuts, framerates, etc.). Use duration_ms to find timestamps for your specific file:

# Your file is 3550000ms (59:10)
curl "https://api.openskip.io/api/v1/timestamps?tvdb_id=81189&season=1&episode=1&duration_ms=3550000"

The tolerance parameter (default 5000ms / 5 seconds) allows for minor duration differences:

# Match files within 10 seconds of your duration
curl "...&duration_ms=3550000&tolerance=10000"

Handling Multiple Results

When multiple timestamps exist for an episode (different versions), pick the best match:

  1. Duration match: Prefer timestamps matching your file's duration
  2. Highest confidence: Higher confidence = more verified
  3. Most recent: Newer entries may be more accurate
# Example: Pick best timestamp
timestamps = response["items"]
best = max(timestamps, key=lambda t: (
    t["duration_ms"] == your_duration,  # Exact match first
    t["confidence"],                     # Then confidence
    t["updated_at"]                      # Then recency
))

Integration Tips

Cache Responses

Timestamp data rarely changes. Cache responses for at least 24 hours to reduce API calls.

Handle Missing Data

Not all episodes have timestamps yet. Gracefully handle empty responses:

if response["total"] == 0:
    # No timestamps available, skip functionality
    pass

Null Fields

Fields like recap_start may be null if that segment doesn't exist. Always check before using:

if timestamp["intro_start"] is not None:
    skip_to(timestamp["intro_end"])