Scrobbling .md
Scrobbling
Tell FlickList what is playing and how far along it is; FlickList keeps resume points current and marks items watched when playback genuinely finishes. Three endpoints cover the whole lifecycle: POST /v3/scrobble/start, POST /v3/scrobble/pause, POST /v3/scrobble/stop.
The lifecycle#
Start when playback begins. Start is an upsert: it creates or updates the resume point for this item, and it doubles as the progress heartbeat. There is no separate heartbeat verb. While playback runs, re-POST start with updated progress every 30 to 60 seconds. That is roughly 60 to 120 requests per hour, comfortably inside the rate limit.
Pause only when the person actually pauses. There is no cadence on pause. Pause never creates a resume point: if no active session matches the item, the response comes back with "id": null and nothing is written, which makes it safe to send on ambiguous player events.
Stop when playback ends for any reason: natural finish, user stop, or your app shutting down. Stop is where the outcome is decided.
curl -X POST "https://flicklist.tv/api/v3/scrobble/start" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"media_type": "movie",
"ids": { "tmdb": 27205 },
"progress": 12.4
}'await fetch('https://flicklist.tv/api/v3/scrobble/start', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
media_type: 'movie',
ids: { tmdb: 27205 },
progress: 12.4
})
});requests.post(
"https://flicklist.tv/api/v3/scrobble/start",
headers={"Authorization": f"Bearer {token}"},
json={"media_type": "movie", "ids": {"tmdb": 27205}, "progress": 12.4},
)For an episode, send "media_type": "show" (or "tv", both are accepted) with the show's ids plus season and episode numbers.
What stop decides#
| Progress at stop | Session length | Outcome |
|---|---|---|
| 90% or more | At least 300 seconds, or 15% of the runtime, whichever is greater | Marked watched, resume point cleared |
| 90% or more | Under that floor | Recorded as a preview, resume point cleared |
| Under 90% | Any | Resume point kept as partial, playback resumes there next time |
| Under 0.5%, no progress ever recorded | Any | Discarded as a phantom event, nothing written |
The response's watch_status tells you which branch you landed in, so your app never has to guess.
Two behaviors worth knowing#
- Stale-session cleanup rides on start. Starting playback also resolves your account's other lingering in-progress sessions: siblings already at 90% or more get marked watched, the rest get their resume points persisted. A crashed player session heals itself the next time anything starts.
- Send stop even on shutdown. A stop at current progress is what converts "the app died at 96%" into a watched mark instead of a stuck resume point.
Reading progress back#
Resume points written by scrobbling are the same ones served by GET /v3/sync/playback, and watched marks land in history and the watched collections. Up Next reacts immediately; see Up Next & change detection.