POST an array of items you already know about; Simkl returns a parallel array telling you, per item, whether it’s in the user’s library, its current status, last-watched timestamp, and (optionally) per-episode breakdown.
Use this only when you don’t already cache the user’s full library locally — typical case is a media-server plugin or a deep-link landing page that needs to check “is this title in the user’s tracker yet?” for a handful of specific titles, without syncing the whole library first.
⚠️ Don’t use this endpoint if your app already pulls
GET /sync/all-items/{type}/{status}. The full-library response already contains the same per-item watch state, statuses, and last-watched timestamps that/sync/watchedreturns — your local cache has the answer. Calling both is wasted requests, counts twice against your rate-limit quota, and is one of the patterns that gets an app’sclient_idsuspended. The correct loop for tracker apps that sync the full library is the two-phase model: full pull once, then/sync/activities-gated incremental refresh — see the Sync guide.
Each input item carries one or more IDs. Simkl resolves to the canonical record before looking up watch state, so any of these work:
| ID style | Example |
|---|---|
| Simkl ID | { "ids": { "simkl": 2090 } } |
| IMDb / TMDB / TVDB / MAL / AniDB / AniList / Kitsu | { "ids": { "imdb": "tt1520211" } } |
| Title + year fallback | { "title": "Inception", "year": 2010 } |
Pair season + episode on an item to ask ‘has the user watched this specific episode?’ instead of ‘is this title in the library?’.
| Param | Effect |
|---|---|
extended=episodes | Include per-episode breakdown (seasons[].episodes[] arrays) for shows/anime. Limit: 100 items per call when this is set — sending more triggers 400 max_items. |
extended=specials | Include specials (season 0). Only effective when combined with episodes. |
extended=counters | When sent alone (without episodes), the seasons[] array is included but its episodes[] arrays are omitted — useful when you only want totals without the per-episode payload. When sent together with episodes, the per-episode arrays are still included. |
Multiple values are comma-separated: extended=episodes,specials.
The response is an array of the same length as the request, in the same order. Each entry echoes the input identifiers and adds:
| Field | When present | Notes |
|---|---|---|
result | always | true if the user has watched (or is watching) this item. false if Simkl matched the IDs but the item isn’t in the user’s library. "not_found" if Simkl couldn’t match the IDs at all — in this case only result is returned, no simkl/list/etc. |
simkl | when result ≠ "not_found" | Canonical Simkl ID. |
list | when matched | Current watchlist status (watching, completed, plantowatch, hold, dropped) or null if not in any list. |
last_watched_at | when matched | ISO-8601 timestamp of the most recent watch event, or null if never watched. |
episodes_total / episodes_aired / episodes_to_be_aired / episodes_watched | with extended=episodes or extended=counters (shows/anime only) | Aggregate counts across all seasons. |
seasons[] | with extended=episodes or extended=counters (shows/anime only) | Per-season {number, episodes_total, episodes_aired, episodes_to_be_aired, episodes_watched}. With extended=episodes alone, each season also includes an episodes[] array (per-episode {number, watched, aired, last_watched_at}). With extended=counters alone, episodes[] is omitted. |
Empty body quirk. Sending an empty array [] returns the literal null (not []). Treat both as ‘no items to check’.
| Status | error | When |
|---|---|---|
| 400 | max_items | More than 100 items in a single call when extended=episodes (or any other extended value that triggers per-episode loading) is set. |
Two-phase model (initial pull → activities-checked delta loop), date_from semantics, when to use /sync/watched vs /sync/all-items, and reference implementations.
Which IDs can I send/expect? All accepted input identifiers and the keys you’ll see echoed back in responses are listed at Standard media objects → Supported ID keys. Send every ID you have on writes — Simkl picks the first that resolves and ignores the rest. Reminder: slug is response-only (never send it on a request).
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.
Preferred form: your client_id as a URL query parameter on every request. Self-describing in logs and curl commands. See Headers and required parameters.
OAuth 2.0 or PIN-flow access_token. Required for endpoints that read or modify the user's library, scrobble session, ratings, settings, or playbacks. See Authentication.
Descriptive identifier for your app, ideally name/version. Examples: PlexMediaServer/1.43.1.10540, kodi-simkl/0.9.2, MyApp/2.4.1 (https://myapp.com).
Comma-separated combination of counters, episodes, specials. Order does not matter; empty or unknown values are ignored. Examples: counters, episodes,specials, counters,episodes,specials.
^(counters|episodes|specials)(,(counters|episodes|specials))*$Your client_id from your Simkl developer settings. Required on every request.
Short, lowercase identifier for your app (e.g. plex-scrobbler, kodi-bridge). Helps Simkl identify which apps are using the API.
Your app's current version (e.g. 1.0, 2.4.1). Helps Simkl debug issues you report.
Simkl internal ID. Most reliable.
53536
URL-safe slug returned in responses.
"attack-on-titan"
IMDb ID.
"tt0181852"
TMDb ID.
"296"
TVDB ID or slug.
153021
MyAnimeList ID.
"4246"
AniDB ID. Specifying just this is enough for anime lookups.
"10846"
AniList ID.
"21"
Kitsu ID.
"12"
aniSearch ID.
"2227"
Anime-Planet slug.
"one-piece"
LiveChart ID.
"321"
Letterboxd slug.
"the-truman-show"
Netflix movie ID.
"70210890"
Hulu episode ID.
Crunchyroll episode ID.
Trakt slug.
"john-wick-chapter-4-2023"
Item type. Helps the lookup find the right title when the same external ID could match multiple types. Optional but recommended.
show, movie, anime "show"
For episode-level lookup: which season. Pair with episode. Per-episode results are returned alongside the title-level result field.
x >= 01
For episode-level lookup: which episode within the season. Pair with season. Result reflects whether the user has watched that specific episode.
x >= 13
Array of per-item watch results in input order.
true if the user has watched (or is watching) the item, false if Simkl matched the IDs but the item isn't in the user's library, or the literal string "not_found" if Simkl couldn't resolve the IDs to any catalog entry.
true
Canonical Simkl ID. Omitted when result: "not_found".
2090
Current watchlist status. Type 4 null — null when the item resolved to a Simkl record but isn't in any of the user's lists. See Null and missing values.
watching, completed, plantowatch, hold, dropped, null "completed"
ISO-8601 timestamp of the most recent watch event for this item. Type 4 null — null if the item has never been watched. See Null and missing values.
"2026-05-15T00:35:15Z"
Present only with extended=episodes or extended=counters (shows/anime).
177
Present only with extended=episodes or extended=counters.
177
Present only with extended=episodes or extended=counters.
0
Present only with extended=episodes or extended=counters.
177
Per-season breakdown. Present only with extended=episodes or extended=counters (shows/anime). With extended=counters alone, the inner episodes[] array is omitted.
Hide child attributes
1
6
6
0
6
Per-episode array. Present with extended=episodes, omitted with extended=counters alone.
Hide child attributes
1
true
true
Per-episode last-watched timestamp. Type 4 null — null if the user has marked the title completed but Simkl has no specific per-episode timestamp. See Null and missing values.
null
Was this page helpful?