> ## Documentation Index
> Fetch the complete documentation index at: https://docs.therundown.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Multiplexed WebSocket — subscribe to markets, scores, plays, 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); a `plays` or `live` subscribe from a
  non-entitled key is rejected with error code `forbidden`.
- `live` — score/status deltas including `live_game_state`, plus play-by-play
  deltas, on one subscription. **Requires an Ultra plan or higher**;
  `live_game_state` and `game_state` are accepted aliases.

**Subscribe** (client → server):
```json
{
  "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). Unsubscribe with
`{"action":"unsubscribe","id":"p1"}`.

**Delta messages** (server → client) are wrapped in an envelope tagged with your
subscription `id`:
```json
{
  "type": "delta",
  "id": "p1",
  "sequence": 42,
  "sub_sequence": 7,
  "delta_last_id": "...",
  "data": { "meta": { "type": "play" }, "data": { ... } }
}
```

**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.

**Errors**: `{"type":"error","id":"...","code":"...","message":"..."}` with codes
`forbidden` (plays/live without Ultra+), `invalid_channel`, `missing_id`,
`duplicate_id`, and `subscription_limit` (plan's concurrent subscription cap
reached).

Concurrent connection and subscription limits vary by tier. See the
[WebSocket reference](/api-reference/v2/websocket) for full protocol details.




## OpenAPI

````yaml get /api/v2/ws
openapi: 3.1.0
info:
  title: TheRundown Sports API
  version: 2.0.0
  description: >
    Real-time and historical sports betting data, odds, lines, and statistics
    across major North American and international sports leagues.


    ## Authentication

    All endpoints (except `/sports` and `/affiliates`) require authentication.
    Pass your API key using one of:

    - **Query parameter**: `?key=YOUR_API_KEY`

    - **Header**: `X-Therundown-Key: YOUR_API_KEY`

    ## Off-the-Board Sentinel Value

    The value **0.0001** indicates a line is "off the board" — the sportsbook
    has temporarily removed pricing (e.g., pending injury news). This is NOT an
    error. Display as "Off Board" or "N/A" in your UI.


    ## Rate Limiting

    Requests are rate-limited per API key tier. Check response headers for
    current limits.


    ## Data Updates

    - Live odds update in real-time during games

    - Use delta endpoints for efficient polling of changes

    - WebSocket connections available for streaming updates


    ## V1 vs V2

    V2 endpoints use market-based data structures (market_id, participants, line
    prices). V1 endpoints use legacy line-based structures (moneyline, spread,
    total objects). V2 is recommended for new integrations.
  contact:
    name: TheRundown API Support
    url: https://therundown.io
    email: support@therundown.io
  termsOfService: https://therundown.io/terms
servers:
  - url: https://therundown.io
    description: Production
security:
  - ApiKeyQuery: []
  - ApiKeyHeader: []
tags:
  - name: V2 Sports
    description: Sport listings, dates, and teams (V2)
  - name: V2 Events
    description: Events with market-based odds (V2)
  - name: V2 Markets
    description: Market definitions, odds, deltas, and history (V2)
  - name: V2 Teams
    description: Team data, players, and stats (V2)
  - name: V2 Players
    description: Player data (V2)
  - name: V2 Stats
    description: Team and player statistics (V2)
  - name: V2 WebSocket
    description: Real-time streaming via WebSocket (V2)
  - name: V2 Reference
    description: Reference data — affiliates, sportsbooks, season types (V2)
  - name: V1 Events
    description: Events with line-based odds (V1 legacy)
  - name: V1 Lines
    description: Moneyline, spread, total, best-line endpoints (V1 legacy)
  - name: V1 Sports
    description: Sport listings, dates, events, schedules (V1 legacy)
  - name: V1 Delta
    description: Delta/change feeds (V1 legacy)
  - name: V1 Reference
    description: Reference data (V1 legacy)
  - name: V1 WebSocket
    description: Real-time streaming via WebSocket (V1 legacy)
paths:
  /api/v2/ws:
    get:
      tags:
        - V2 WebSocket
      summary: >-
        Multiplexed WebSocket — subscribe to markets, scores, plays, and live
        channels
      description: >
        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); a `plays` or `live` subscribe from a
          non-entitled key is rejected with error code `forbidden`.
        - `live` — score/status deltas including `live_game_state`, plus
        play-by-play
          deltas, on one subscription. **Requires an Ultra plan or higher**;
          `live_game_state` and `game_state` are accepted aliases.

        **Subscribe** (client → server):

        ```json

        {
          "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). Unsubscribe with

        `{"action":"unsubscribe","id":"p1"}`.


        **Delta messages** (server → client) are wrapped in an envelope tagged
        with your

        subscription `id`:

        ```json

        {
          "type": "delta",
          "id": "p1",
          "sequence": 42,
          "sub_sequence": 7,
          "delta_last_id": "...",
          "data": { "meta": { "type": "play" }, "data": { ... } }
        }

        ```


        **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.


        **Errors**: `{"type":"error","id":"...","code":"...","message":"..."}`
        with codes

        `forbidden` (plays/live without Ultra+), `invalid_channel`,
        `missing_id`,

        `duplicate_id`, and `subscription_limit` (plan's concurrent subscription
        cap

        reached).


        Concurrent connection and subscription limits vary by tier. See the

        [WebSocket reference](/api-reference/v2/websocket) for full protocol
        details.
      operationId: v2WebSocketMultiplexed
      responses:
        '101':
          description: WebSocket upgrade successful
components:
  securitySchemes:
    ApiKeyQuery:
      type: apiKey
      in: query
      name: key
      description: API key as query parameter
    ApiKeyHeader:
      type: apiKey
      in: header
      name: X-Therundown-Key
      description: API key as request header

````