playback:write scope. A stop that resolves as watched and creates history also requires history:write.
Supported actions
Send these actions to:startpauseresumestopprogress
Minimum payload shape
Every playback request must include deterministic event and session identifiers, a client event timestamp, and enough media identity to resolve the title.Supported payload fields
Movie example
Episode example
Event ordering behavior
PunchPlay applies session-aware event handling so clients can send real playback events without manually reconstructing user state. Important behaviors:- Duplicate
event_idvalues are deduped. - A
stopmay create a completed watch or only save progress, depending on completion state. - Older events that arrive after a stop are ignored.
- A newer incomplete
stopcan update an existing passive snapshot when it uses the sameplayback_session_id, a newevent_id, and a laterevent_created_at. - Newer progress after a stopped session can reopen the session.
pauseupdates an active session without creating a watch. A standalone pause returns409 playback_state_conflict.
Passive resume sync
When importing an existing resume position from another tracker or media server, send one incompletestop. No preceding start, progress, or
pause request is required. PunchPlay stores the item as inactive resumable
progress, so it appears in Continue Watching without appearing as now playing.
progress followed by pause for a passive import. progress
represents active playback and may briefly publish a now-playing state. A
standalone pause is a transition for an existing live session and is rejected.
To refresh a passive resume position, reuse the stable
playback_session_id, generate a new event_id, and send a later
event_created_at. PunchPlay compares provider event time rather than arrival
time, so delayed older snapshots cannot overwrite newer progress.
Best practices
- Always send a stable
playback_session_id. - Generate a unique
event_idfor each logical playback update and reuse it only when retrying that same event. - Send the original client event time in
event_created_at, not the retry time. - Send
tmdb_idwhenever available. - Include
position_secondsandduration_secondsfor accurate progress. - Keep
progressin the0to1range. PunchPlay can deriveposition_secondsfromprogressonly whenduration_secondsis present.
Completion rules
Astop event is treated as watched when one of these is true:
watchedis explicitlytrueprogressor derived progress meetswatched_threshold
history:write. Request that scope during authorization for clients that are allowed to create completed watch history.
Failure handling
Platform playback errors include:request_idin the JSON bodyX-PunchPlay-Request-Idin the response headers