Skip to main content

Documentation Index

Fetch the complete documentation index at: https://api.simkl.org/llms.txt

Use this file to discover all available pages before exploring further.

Every endpoint that talks about a movie, show, anime, or episode uses the same JSON shapes. Learn them once and you can read or write any endpoint.

The ids object

The ids object is the heart of every media object. It’s how Simkl identifies what you mean across all the catalogs you can integrate with. Pass as many IDs as you have — Simkl resolves to the canonical record and returns the rest.
{
  "ids": {
    "simkl": 53536,
    "imdb":  "tt0181852",
    "tmdb":  296
  }
}

Supported ID keys

Read either ids.simkl or ids.simkl_id — same integer, two key names. Depending on the endpoint, Simkl’s canonical catalog ID comes back as ids.simkl or ids.simkl_id. Robust reader code accepts both:
const id = item.ids.simkl ?? item.ids.simkl_id;
The integer is globally unique and permanent — use it as your primary key for caching and cross-referencing.slug is NOT unique — multiple titles can share one (e.g. three different Superman movies live at /movies/2059585/superman, /movies/260740/superman, /movies/951252/superman). The slug is a URL hint only; never identify a record by slug alone.External IDs in ids (imdb, tmdb, tvdb, mal, anidb, …) are echo-only. To resolve one to a Simkl record, use /redirect — it returns the canonical Simkl URL with the simkl ID baked in.tmdb is the one external ID that isn’t globally unique — TMDB keeps separate sequences for movie and tv, so the same numeric tmdb value can refer to either. When resolving a TMDB ID via /redirect, always pass type=movie or type=tv alongside tmdb. When reading TMDB IDs back from responses, treat the container key (movies / shows / anime) as part of the ID’s identity.
KeyTypeExample
simklinteger53536 — Simkl’s canonical ID. Globally unique and permanent.
imdbstringtt0181852
tmdbinteger296Not unique across types; always pair with type=movie or type=tv when resolving via /redirect. TMDB has no anime type; anime is filed under tv on TMDB.
tvdbint / string153021 or the-walking-dead
malinteger4246
anidbinteger10846
anilistinteger21
kitsuinteger12
anisearchinteger2227
animeplanetstringone-piece
livechartinteger321
letterboxdstringthe-truman-show
netflixinteger70210890
traktslugstringjohn-wick-chapter-4-2023
crunchyrollinteger656647 (episode-level)
huluinteger681868 (episode-level)
Send every identifier you have — title, year, and the full ids object.Simkl walks the ids object in priority order (simkl first when present, then external IDs like imdb, tmdb, tvdb, mal, anidb, …). If no ID resolves, it falls back to a title + year match, then to title-only as a last resort. Sending everything you know — title, year, plus every external ID your client has cached — maximizes the chance the right item gets credited. Extra fields are free; missing fields can cause a 404 id_err or, worse, a silent mismatch.You don’t need to search before writing. Endpoints like /scrobble/*, /sync/history, /sync/add-to-list, and /sync/ratings resolve IDs server-side — pass whatever you have directly, no /search/* round-trip required. Calling /search/id first to “resolve” a Simkl ID is wasted work that doubles your API quota for no gain.See Supported ID keys for the full list.

Movie

{
  "title": "Terminator 3: Rise of the Machines",
  "year":  2003,
  "ids": {
    "simkl": 53536,
    "imdb":  "tt0181852",
    "tmdb":  296
  }
}
When simkl is known, the minimum is just:
{ "ids": { "simkl": 53536 } }

Show

A show object can include nested seasons and episodes for partial sync:
{
  "title": "The Walking Dead",
  "year":  2010,
  "ids": {
    "simkl": 2090,
    "tvdb":  153021,
    "imdb":  "tt1520211"
  },
  "seasons": [
    {
      "number": 1,
      "episodes": [
        { "number": 1 },
        { "number": 2 }
      ]
    }
  ]
}

Anime

Same JSON shape as Show, plus anime_type and an optional flat episodes list. Simkl uses AniDB as its primary metadata source — episodes follow the anime-native model by default (each cour is its own title, episodes restart at 1). Simkl also accepts Western TVDB/TMDB-style season + number coordinates and cross-maps both to the same canonical episode.

Handling anime — full guide

Two integration paths (TMDB/TVDB-primary with use_tvdb_anime_seasons, or anime-native with AniDB/MAL/AniList/Kitsu IDs), the cross-mapping rules, write/read recipes, and edge cases like Attack on Titan and Solo Leveling.
Anime can go under either shows[] / show or anime[] / anime. Simkl resolves items by their ids first, then routes to the correct catalog — the key you pick is for clarity, not routing. Match the field to your data type when known; fall back to shows / shows[] when you only have TMDB / TVDB IDs.
Endpoint familyAccepted top-level keys
/scrobble/start, /pause, /stop, /checkinmovie, show, anime, episode (singular objects, one per request)
/sync/history, /sync/history/remove, /sync/add-to-list, /sync/ratings, /sync/ratings/removemovies[], shows[], anime[], episodes[] (plural arrays, batched)
/sync/watchedtop-level array of items, no wrapping key
Anime-only IDs work anywhereanidb, mal, anilist, kitsu, anisearch, animeplanet, livechart inside ids resolve correctly whether the wrapper is shows[] or anime[]. For example, either of these adds Attack on Titan:
POST /sync/history — either form works
{ "anime": [ { "ids": { "anidb": 9541 } } ] }

{ "shows": [ { "ids": { "anidb": 9541 } } ] }
Caveat: not_found always buckets under shows. If a write fails to resolve, the response’s not_found.shows array carries the failed entry regardless of whether you sent it under shows[] or anime[]. There is no not_found.anime bucket.
{
  "title": "Attack on Titan",
  "year":  2013,
  "anime_type": "tv",
  "ids": {
    "simkl": 39687,
    "mal":   16498,
    "tvdb":  267440,
    "imdb":  "tt2560140",
    "anidb": 9541
  },
  "episodes": [
    { "number": 1 },
    { "number": 2 }
  ]
}

anime_type

Anime items include an anime_type field with one of these values:
  • tv
  • special
  • ova
  • movie
  • music video
  • ona

Episode

Inside a seasons[].episodes[] array (or a flat episodes array), an episode is identified by season + number, or directly by ids. Optionally include watched_at to record when it was watched.
Prefer season + number over episode IDs whenever you can. The numeric S1E4 coordinate is stable forever — it never changes once an episode airs. External episode IDs (TVDB / AniDB) get re-issued when the source catalog merges duplicates, re-numbers a season, or replaces a record, and a stale episode ID returns 404. The season + number pair is the cheapest, most robust identifier for scrobble / sync writes — only fall back to episode.ids when your integration genuinely doesn’t know which season/number it’s dealing with (e.g. Plex-style scrapers that resolve a file to a single episode ID without season context).
{
  "watched_at": "2014-09-01T09:10:11Z",
  "season": 1,
  "number": 4
}
If you only have an episode ID (no season/number), pass it via ids. For episode-ID lookups in scrobble / sync writes, Simkl accepts only tvdb and anidb at the episode level. If both are sent, tvdb is tried first. Episode-level imdb and tmdb IDs do not exist on Simkl — those external services only assign IDs at the show/movie level.
{
  "watched_at": "2014-09-01T09:10:11Z",
  "ids": {
    "tvdb":  4274616,
    "anidb": 142278
  }
}
Catalog responses (e.g. /tv/episodes/{id}) may echo additional episode-level keys like simkl (Simkl’s internal episode ID), hulu, or crunchyroll. Those are informational — they’re returned for cross-reference but are not accepted for episode-ID lookup. Always send season + number (preferred) or tvdb / anidb when identifying an episode in a request.

Tips for sending media objects

title, year, and any IDs you have. Simkl uses all of it to disambiguate. If two movies share a title and year, IDs save the day.
If you send simkl: 53536 and imdb: "tt9999999" and they disagree, Simkl uses the simkl ID. Send only one source of truth when you can.
Simkl uses the anime-native model (each cour is its own title, episodes restart at 1) — same as AniDB / MAL / AniList / Kitsu / AniSearch / Anime-Planet / LiveChart / ANN. Western TV catalogs (TVDB / TMDB / IMDB) use the franchise-with-seasons model instead. The Scrobble and Sync endpoints accept both schemes and Simkl maps automatically — the response includes both season/number (anime-native) and tvdb_season/tvdb_number (Western style) for reference. See Anime episode numbering for the full mapping rules.