Skip to main content
The playback API is the core of the PunchPlay platform. It accepts playback lifecycle events and turns them into now-playing state, in-progress items, playback sessions, and watch history. This surface requires the playback:write scope. A stop that resolves as watched and creates history also requires history:write.

Supported actions

Send these actions to:
Available actions:
  • start
  • pause
  • resume
  • stop
  • progress

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_id values are deduped.
  • A stop may create a completed watch or only save progress, depending on completion state.
  • Older events that arrive after a stop are ignored.
  • A newer incomplete stop can update an existing passive snapshot when it uses the same playback_session_id, a new event_id, and a later event_created_at.
  • Newer progress after a stopped session can reopen the session.
  • pause updates an active session without creating a watch. A standalone pause returns 409 playback_state_conflict.

Passive resume sync

When importing an existing resume position from another tracker or media server, send one incomplete stop. 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.
Do not send 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_id for 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_id whenever available.
  • Include position_seconds and duration_seconds for accurate progress.
  • Keep progress in the 0 to 1 range. PunchPlay can derive position_seconds from progress only when duration_seconds is present.

Completion rules

A stop event is treated as watched when one of these is true:
  • watched is explicitly true
  • progress or derived progress meets watched_threshold
If a stop does not qualify as watched, PunchPlay stores progress instead of creating a completed watch entry. When a stop does qualify as watched, the token must include history:write. Request that scope during authorization for clients that are allowed to create completed watch history.

Failure handling

Platform playback errors include:
  • request_id in the JSON body
  • X-PunchPlay-Request-Id in the response headers
Capture that value when reporting failed writes or invalid payloads.