A rewatch is a separate viewing session for an item the user already completed. Each session has its own start date, episode progress (for shows / anime), and status (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.
active, completed, or closed). Up to 50 sessions per item. Simkl returns the full session list so you can replicate the simkl.com “Rewatches” panel.
?allow_rewatch=yes get a silent no-op. If your UI exposes a “Rewatch” button to a free-tier user, disable it with a short note like “Rewatch tracking requires Simkl Pro or VIP” and link to simkl.com/vip.Endpoints used
POST /sync/history
?allow_rewatch=yes makes the write land in a rewatch session instead of the canonical row.GET /sync/all-items
?allow_rewatch=yes adds one extra row per saved session alongside the canonical entry.Quick start
A movie rewatch:rewatch_id and rewatch_status inside added.statuses[].response. Cache the rewatch_id and pin it on every subsequent write for that session.
When does a write become a rewatch?
The server always tries the regular write first. If the regular write would actually mark new data, that takes precedence — no rewatch is created. A write lands in a rewatch session when any of these holds:- The item is already Completed and the regular add is a no-op (movies: user already finished it; shows: payload has no episodes and the show is Completed).
- You included episodes and every one is already on the user’s history — i.e. the regular write would change nothing.
- You passed
is_rewatch: trueon the item.
is_rewatch: true does not bypass the regular-first logic. If the write tries to add a date that already exists in canonical history, it’s still rejected. The flag’s main use is to create an empty rewatch session on a Completed item your UI explicitly marked as “starting a rewatch” — without writing any episodes yet.
The episode or movie must already exist on the user’s history (completed / watching / hold / dropped) — Plan-to-Watch entries can’t be rewatched, there’s nothing to rewatch.
Per-item rewatch fields
All fields below are optional. They only take effect when?allow_rewatch=yes is on the URL.
| Field | Type | Purpose |
|---|---|---|
is_rewatch | bool | Trigger rewatch logic explicitly. See When does a write become a rewatch? for what overrides what. |
rewatch_id | int | Resume a specific session. Use the value from a previous response. Without it, the server picks the item’s active session if one exists, else creates a new session. |
rewatch_status | string | Set session state directly: active, completed, or closed. Use to explicitly close, reactivate (the simkl.com “Reactivate” gesture), or force-complete. |
watched_at | string (ISO-8601) | Standard per-item timestamp. Also serves as the session’s start date. |
last_watched_at | string (ISO-8601) | Primarily a response field from GET /sync/all-items (the session’s most recent watch event). Rarely set on writes. |
Session states
| State | Meaning | How it’s set |
|---|---|---|
active | In progress. Only one per item at a time. | Default for new TV / anime sessions; or rewatch_status: "active" to reactivate a closed / completed session. |
completed | Done — every aired episode rewatched. | Auto when watched_episodes_count >= aired_episode_count. Default for new movie sessions (no episodes to track). Or rewatch_status: "completed". |
closed | The user closed the session. Resumable at any time. | rewatch_status: "closed". Also set automatically on the previously-active session when another session is made active for the same item. Can be set on any session — including one with zero episodes watched (the simkl.com UI then shows it as completed, with no “partial” label). |
active, then becomes either completed (all aired episodes watched) or closed (user ended the session before reaching the end). Manual transitions via rewatch_status can move a session between any states — that’s how simkl.com’s “Reactivate this rewatch” gesture works.
The 2-day gap
Any two watch events on the same item (movie or individual episode) must be at least 2 days apart, or the second write collapses into the first session. It’s a rewatch, not a rewind 😄. The gap is per-item, not per-show. Watching S1E1 on Monday and S1E2 on Tuesday is fine — those are different items. The rule only fires when the same episode is written twice within 48h.- Sleep-and-resume — user starts an episode at night, finishes the next morning. One viewing, not two.
- Wrong timezones — clients labeling local time as UTC (or vice versa) drift 1–12 hours per write.
- DST transitions — naive date libraries miscalculate by an hour twice a year.
- Multi-device duplicates — phone + TV both report the same play.
- Retry storms — flaky connections retry a write that already landed.
- Importer re-runs — re-running an import re-sends the same
watched_at. - Scrobble pause/resume noise — bathroom break → re-fire of
/start+/stop. - Buggy progress reporting — players hitting 80%+ multiple times on seeks.
Reading sessions back
?allow_rewatch=yes on GET /sync/all-items adds one extra entry per saved rewatch session alongside the canonical entry for each item. Always pair with date_from — never call without it outside the initial Phase-1 sync.
Canonical vs rewatch rows
| Field | Canonical (is_rewatch: false) | Rewatch (is_rewatch: true) |
|---|---|---|
is_rewatch | false (emitted when ?allow_rewatch=yes is set; otherwise absent) | true |
rewatch_id | absent | session id |
rewatch_status | absent | active / completed / closed |
last_watched_at | The canonical (original) last watch date for the item — does not reflect rewatch sessions. | This session’s most-recent watch event. |
watched_episodes_count | Episodes marked watched on the canonical row (e.g. 62/62 for a finished show). Not a lifetime total across rewatches. | Per-session count — 0 as a sentinel without extended=full. |
last_watched_at and watched_episodes_count on the canonical entry never incorporate rewatch progress, no matter how many sessions exist for the item.
Worked example — Game of Thrones with one rewatch session
A representative shape fromGET /sync/all-items?allow_rewatch=yes&extended=full&episode_watched_at=yes — Game of Thrones (Simkl ID 17465) finished long ago, currently being rewatched in progress (4 of 73 episodes into S1). The item appears twice in shows[]: once as the canonical row, once as the in-progress rewatch row.
- Same
simklID on both rows —17465appears twice. Group byids.simklwhen iterating; treatis_rewatch: truerows as side-cars on the canonical entry. - Canonical
watched_episodes_countis73/73(the user finished the show originally); the rewatch row’s4/73is per-session and does NOT advance the canonical count. last_watched_atis independent on each row — canonical reflects the original final watch (2026-05-15); the rewatch row reflects its own most-recent episode (2026-05-16T20:00:00Z).rewatch_status: "active"because 4/73 <total_episodes_count. It would auto-flip to"completed"whenwatched_episodes_count >= total_episodes_count - not_aired_episodes_count, or you can force it via arewatch_statuswrite at any time. A session manually overridden to"completed"with fewer episodes watched is legal but represents an explicit user gesture, not natural progression.seasons[].episodes[]only appears on the rewatch row under this flag combo (extended=full+episode_watched_at=yes). Withoutextended=full, the rewatch row would arrive summary-only:watched_episodes_count: 0sentinel, noseasons[]block.- Movies are simpler — no
seasons[], justmovie: { ... }, and the rewatch row’srewatch_statusalways starts atcompleted(movies have nothing to track episode-wise). - Anime rewatch rows have the same shape as show rows plus an
anime_typefield ("tv","movie", etc.) on the rewatch row itself.
Flag combinations for episode lists
Flags (on top of allow_rewatch=yes) | What rewatch entries carry |
|---|---|
| (none) | Summary only. watched_episodes_count returns 0 as a sentinel even when the session actually has episodes. |
extended=full | Summary fields populated with real per-session counts, plus seasons[].episodes[] listing episode number. |
extended=full_anime_seasons | Same plus anime tvdb mapping per episode. |
extended=full + episode_watched_at=yes | Same plus per-episode watched_at (from each episode’s completed_on). |
episode_watched_at=yes is a modifier — it adds timestamps to episodes already loaded. Without extended=full, episodes aren’t loaded and the flag has no effect on rewatch entries.
UI patterns (mirror simkl.com)
Stats badge — '×3 times (1 partial), last 12 days ago'
Stats badge — '×3 times (1 partial), last 12 days ago'
?allow_rewatch=yes response for the current item and count by rewatch_status. closed is the “partial” count; completed is the clean-finish count.'Currently rewatching #N' progress bar (TV / anime)
'Currently rewatching #N' progress bar (TV / anime)
active session and show watched_episodes_count / total_episodes_count. Number the badge by chronological index among all sessions for the item — the number isn’t stored on the server, you compute it client-side.Movies don’t really have an active phase — every movie rewatch session flips to completed immediately.'Mark next episode rewatched' button
'Mark next episode rewatched' button
'Reactivate' / 'Start new' / 'Close' buttons
'Reactivate' / 'Start new' / 'Close' buttons
Rewatch history list — '×3 sessions' panel
Rewatch history list — '×3 sessions' panel
last_watched_at ascending. Label sessions “Rewatch #1”, “Rewatch #2”, etc. on the client.Limits and rules
- Maximum 50 rewatches per item (movie, show, or anime — combined cap).
- One
activesession per item. Making another session active auto-closes the previous active one. - 2-day minimum gap between watch events on the same movie or episode. See The 2-day gap.
- Simkl Pro / VIP only. Free-tier writes are silent no-ops.
Edge cases
Free-tier user calls `?allow_rewatch=yes`
Free-tier user calls `?allow_rewatch=yes`
200 OK with added: { movies: 0, shows: 0, episodes: 0 }. No error. Detect by checking the user’s subscription tier client-side, or by inspecting the added counts in the response.50-cap reached
50-cap reached
Active session collision
Active session collision
watched_episodes_count is preserved). The old session is still readable and still counts toward the 50-cap.`watched_at` collides with canonical history
`watched_at` collides with canonical history
is_rewatch: true — is rejected if the watched_at date matches an existing canonical episode/movie row. Use a different watched_at value, or omit the conflicting episode.Same episode written twice within 48h
Same episode written twice within 48h
watched_episodes_count doesn’t increment; last_watched_at updates to the latest value. Intentional — see The 2-day gap.Conflict-split on same episode, different dates
Conflict-split on same episode, different dates
watched_at more than 48h away, the server closes the current active session (preserving its watched_episodes_count) and opens a fresh active session with the conflicting episode at the new timestamp. Common with offline-capable apps catching up after a long sync gap.Sessions started via simkl.com are pre-populated
Sessions started via simkl.com are pre-populated
/sync/all-items after a session was created on simkl.com to see what’s actually there.`1970-01-01T00:00:01Z` on a rewatch episode
`1970-01-01T00:00:01Z` on a rewatch episode
Reference
Sync guide
date_from semantics, deletion reconciliation, edge cases.