Get Last Activities
Returns the most recent update timestamps for each of the user’s lists. Always call this first when syncing — compare against your last-saved timestamps and pull only the lists that have moved. This is the cheapest call in the API.
Top-level fields
| Field | Use |
|---|---|
all | Newest timestamp anywhere in this response — every domain block, settings, custom_lists, ratings and playback. If it hasn’t moved since your saved snapshot, nothing has. |
settings.all | Updates to account settings (name, time zone, …) at https://simkl.com/settings/. |
tv_shows, anime, movies | Per-domain timestamp groups. |
custom_lists.lists | Custom Lists timestamps, one level deeper than the other blocks — see Custom Lists have their own timestamps. |
Per-domain timestamps
| Field | Meaning | Cheapest next call |
|---|---|---|
all | Latest update in this domain. | — |
rated_at | A rating was added, changed, or removed. | Only when this moved — never on every sync, since every /sync/all-items item already carries user_rating. Then GET /sync/ratings/{type} with date_from and no rating segment — the changed ratings, removals included as user_rating: null. A rating-only change never appears in a /sync/all-items delta. Walkthrough: Ratings come in their own delta. |
playback | A paused playback was added, resumed, or cleared. | GET /sync/playback/{type} with date_from — only the changed sessions. |
plantowatch, watching, completed, hold, dropped | Items moved into/out of these lists, or episodes were marked watched/unwatched. | GET /sync/all-items/{type}/{status} with date_from and extended=full — full delta of modified items. Walkthrough: Phase 2 — Continuous sync. |
removed_from_list | Items were deleted from the library entirely. date_from won’t surface removals — you can only detect them by diffing. | GET /sync/all-items/{type}/{status} with extended=simkl_ids_only — cheapest possible payload (just the IDs) — and diff against your local cache. Walkthrough: Detecting deletions. |
Movies don’t have
watchingorhold— movies are atomic, so those statuses don’t apply.
Auto-move side effects
When a user rates an unrated item, Simkl auto-files it: movies → Completed, shows/anime → Watching. That auto-move bumps the corresponding list timestamp, so the rated item also appears in subsequent /sync/all-items?date_from= queries.
Recommended sync loop
- Before the first pull, read this endpoint and keep the whole response — your snapshot. Pull each list once with no
date_from, then save the snapshot, but only if every pull succeeded. - On each poll, read this endpoint again. If the top-level
allequals your snapshot’s, stop — nothing changed anywhere. - Otherwise compare bucket by bucket and call only the endpoints for the buckets that moved (table above), each with
date_from= your saved snapshot’s top-levelall, passed exactly as returned.date_fromreturns only what changed strictly after that value. - Once every fetch has succeeded, save this response as the new snapshot. If any failed, keep the old one — the next poll sends the same
date_fromand picks up what was missed.
Read the snapshot before the fetch it anchors, never after: a change made while you fetch would otherwise be stamped at or below the value you save, and no later date_from would return it. Full walkthrough: Phase 1 and Phase 2.
Removal cascade
When removed_from_list moves, the user actively deleted items from their library. Refetch with extended=simkl_ids_only and diff against your local cache to detect deletions — date_from won’t surface them. Also clear any local rating you stored for those items: Simkl wipes the rating when an item is removed, which is why removals can move both removed_from_list and rated_at.
Sync guide — full walkthrough
Two-phase model (initial pull → activities-checked delta loop), date_from semantics, deletion reconciliation, edge cases, and reference implementations in Node and Python.
Authorizations
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.
A user access_token, sent as Authorization: Bearer .... Required for endpoints that read or modify the user's library, scrobble session, ratings, settings, or playbacks. Every flow returns the same kind of token. See Set up authentication.
Headers
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).
Query Parameters
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.
Response
OK
Last-activity envelope returned by GET /sync/activities. Use all as the cheapest first-pass check, then drill into a per-domain block only when its all has moved. The top-level all now also moves when a custom list changes, so a loop that gates on it will wake for those as well.
Type 4 null — data not on file in that field's slot. See Null and missing values. Newest timestamp across every domain and bucket. Best first-level check — if this hasn't moved since your last sync, nothing has changed. This includes custom-list activity, so all can move when only a list changed.
Top-level settings change marker. Bumped when the user changes any setting at https://simkl.com/settings/ (display name, time zone, privacy, etc.).
Per-domain timestamps for TV shows and anime. Both types share the full five-status set (watching, plantowatch, hold, dropped, completed). Each timestamp is an ISO-8601 datetime, or null if the user has never had activity in that bucket — a Type 1 null ("never happened yet", see Null-value conventions).
Per-domain timestamps for TV shows and anime. Both types share the full five-status set (watching, plantowatch, hold, dropped, completed). Each timestamp is an ISO-8601 datetime, or null if the user has never had activity in that bucket — a Type 1 null ("never happened yet", see Null-value conventions).
Per-domain timestamps for movies. Movies are single-session content, so this block does not include watching or hold — those keys are omitted entirely (not null). See Watchlist statuses for the per-type matrix.
Custom Lists activity. The timestamps sit under lists rather than directly on this object, leaving room for other custom-list activity to be added alongside them later — so read custom_lists.lists.all, not custom_lists.all.