Multiplexed WebSocket — subscribe to markets, scores, plays, stats, and live channels
Establishes a single WebSocket connection carrying multiple logical channels. Instead of query-parameter filters, send JSON subscribe messages after connecting.
Connection: wss://therundown.io/api/v2/ws?key=YOUR_API_KEY
Channels:
markets— market price updates (same payloads as/api/v2/ws/markets)scores— score and event-status updates (no live game state fields)plays— play-by-play deltas for live games. Requires an Ultra plan or higher (the live game state entitlement); aplays,stats, orlivesubscribe from a non-entitled key is rejected with error codeforbidden.stats— changed team and player box-score rows, delivered inline withmeta.type=game_stats. Requires an Ultra plan or higher. This is a delta-only channel with no snapshot, replay, or resume; bootstrap and recover from both event game-stat REST endpoints. Each changed stat row is one stats data point.live— score/status deltas includinglive_game_state, play-by-play deltas, and game-stat deltas, on one subscription. Requires an Ultra plan or higher;live_game_stateandgame_stateare accepted aliases.
Subscribe (client → server):
{
"action": "subscribe",
"id": "p1",
"channel": "plays",
"params": { "sport_ids": [3], "event_ids": ["<eventID>"] }
}
The server acknowledges with {"type":"subscribed","id":"p1","sequence":N,"message":"subscribed to plays"}.
Supported params filters: sport_ids, event_ids (plus market_ids and
affiliate_ids on the markets channel). stats has no stat, team, or player
filter. Unsubscribe with
{"action":"unsubscribe","id":"p1"}.
Delta messages (server → client) are wrapped in an envelope tagged with your
subscription id:
{
"type": "delta",
"id": "p1",
"sequence": 42,
"sub_sequence": 7,
"delta_last_id": "...",
"data": { "meta": { "type": "play" }, "data": { ... } }
}
A stats delta uses the same outer envelope. Its inner payload has
meta.type=game_stats; data.team_stats[] and data.player_stats[] contain
only changed rows, and each row’s value remains a JSON string. Upsert those
rows into the REST-bootstrapped box score rather than replacing a whole group.
If both row arrays are absent and complete=true, the frame is the terminal
completion marker; mark the cached box complete and treat repeats as idempotent.
If both arrays are absent without complete=true, the frame is an invalidation
fallback: refetch both GET /api/v2/events/{eventID}/stats and
GET /api/v2/events/{eventID}/players/stats. Row deltas and completion markers
use an RFC 3339 updated_at; the fallback uses numeric Unix seconds. Do not use
delta_last_id as a game-stat replay cursor. Each changed nested row is one
stats data point; either zero-row variant costs one stats data point.
Snapshots: add "snapshot": true to params to receive current state
(snapshot frames, then snapshot_complete) before deltas begin; an active
subscription can request a fresh snapshot at any time with
{"action":"snapshot","id":"p1"}. Snapshot requests need a bounded scope and
are metered as data points like the equivalent REST reads. Snapshots are not
supported on stats; a request returns snapshot_error with code
unsupported_snapshot. A live snapshot does not include a game-stat baseline.
Errors: {"type":"error","id":"...","code":"...","message":"..."} with codes
forbidden (plays/stats/live without Ultra+), invalid_channel, missing_id,
duplicate_id, and subscription_limit (plan’s concurrent subscription cap
reached). A slow multiplexed client may receive the connection-level error code
buffer_overflow immediately before the connection closes with reason
buffer_overflow:reconnect_and_catchup.
Queue and recovery: each non-market subscription has its own 1024-message
outbound queue; market subscriptions are sized separately. If a live frame
cannot be queued, the server closes the connection rather than continue with a
silent gap. Reconnect, re-send subscriptions, and recover current state before
applying new deltas. For stats, refetch both event game-stat REST resources.
Concurrent connection and subscription limits vary by tier. See the WebSocket reference for full protocol details.
Authorizations
API key as query parameter
Response
WebSocket upgrade successful