Skip to main content
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.
Note the quoting: simkl is an integer, every other ID is a string. That’s exactly how responses come back, and requests accept this form too β€” see Supported ID keys below.

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:
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.
In responses, every ID is a string except simkl / simkl_id. ids.simkl (and ids.simkl_id) come back as JSON integers; every other ID β€” including numeric-looking ones like tmdb, tvdb, mal, anidb, anilist, and kitsu β€” comes back as a quoted string:
Type your decoder accordingly β€” a struct that declares tmdb as Int will fail to decode. On requests, both forms are accepted ("tmdb": 693134 and "tmdb": "693134" both resolve), so you only need to care about this when reading.
The table below gives the response type for each key. Accepted on requests but not returned in responses. These resolve a title when you send them to /redirect or /search/id, but Simkl doesn’t echo them back in ids: crunchyroll, netflix, hulu, anisearch, animeplanet, livechart, anfo, ann, tvcom, zap2it, mdl, boxd.
The CDN data files use different key names than the API. Everything above describes api.simkl.com. The pre-built JSON files on data.simkl.in β€” trending, DVD releases, and calendar β€” are produced by a separate pipeline that still emits the older movie/series-qualified names:simkl_id, slug, imdb, tmdb, tvdb, tvdbslug, mdlslug, mal, anidb, anilist, and kitsu are spelled the same in both. If you read from both surfaces, normalize the three keys above before merging β€” otherwise the same title looks like it has different IDs depending on where you fetched it.
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

When simkl is known, the minimum is just:

Show

A show object can include nested seasons and episodes for partial sync:

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.Anime-only IDs work anywhere β€” anidb, 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
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.

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).
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.
tvdb and anidb are request-only at the episode level. Catalog responses (e.g. /tv/episodes/{id}, /anime/episodes/{id}) return a single key in each episode’s ids β€” simkl_id, an integer, Simkl’s own episode ID:
They do not echo tvdb, anidb, hulu, or crunchyroll back. 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.