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

# Sports Live State

> Live scores, source reliability, and websocket updates for sports games

## Overview

Predexon separates sports market discovery from live game state.

Market discovery answers: **what can I trade?**

Live state answers: **what is happening in the underlying game?**

That separation keeps identifiers clear:

| Identifier    | Meaning                                      | Example                                               |
| ------------- | -------------------------------------------- | ----------------------------------------------------- |
| `game_id`     | Broad real-world game                        | `mlb-ari-pit-2026-05-07`                              |
| `event_id`    | Canonical market/question attached to a game | `mlb-ari-pit-2026-05-07` for current `game_winner` v1 |
| `predexon_id` | Canonical tradable outcome                   | `px-xz7fw6lsywv2rnwr`                                 |

Live state is keyed by `game_id`, not `event_id`, because future spreads, totals, and props can all share the same live score while using different market/question IDs.

<Info>
  `predexon_id` is now canonical. It identifies one Predexon outcome across matched venues; it is not a venue-native token ID, ticker, condition ID, or legacy per-venue identifier.
</Info>

## Availability

| Surface                               | Status    | Purpose                                                           |
| ------------------------------------- | --------- | ----------------------------------------------------------------- |
| `GET /v2/sports/live`                 | Available | List live-state snapshots by game.                                |
| `GET /v2/sports/live/{game_id}`       | Available | Fetch one live-state snapshot.                                    |
| `wss://wss.predexon.com/v1/<API_KEY>` | WebSocket | Stream aggregate live-state changes on the `sports_live` channel. |

If live state is not yet available for a game, REST can return the game shell with `reliability.state = "no_data"` and null score fields.

## Recommended Integration

For an application that displays sports markets with live score context:

```text theme={null}
1. GET /v2/sports/games?league=mlb
   -> discover games and canonical predexon_ids

2. GET /v2/sports/live?league=mlb
   -> hydrate visible games with score/status snapshots

3. Subscribe to WSS by league or game_ids
   -> receive aggregate live-state changes

4. GET /v2/sports/outcomes/{predexon_id}
   -> resolve execution venues when the user trades
```

Do not use live state as a tradable identifier. Trading and routing continue to use outcome-level `predexon_id`.

## Canonical predexon\_id

For sports, `predexon_id` lives at the canonical outcome layer:

```text theme={null}
game_id       -> broad real-world game
event_id      -> canonical market/question
predexon_id   -> canonical tradable outcome
token_id      -> venue-native executable token, when a venue has one
market_ticker -> Kalshi venue-native ticker
condition_id  -> CTF condition ID, not an outcome ID
```

Example:

```text theme={null}
game_id:     mlb-ari-pit-2026-05-07
event_id:    mlb-ari-pit-2026-05-07
outcome:     ari
predexon_id: px-xz7fw6lsywv2rnwr
```

If Kalshi, Polymarket, and Predict.fun all list "Arizona Diamondbacks win" for that game, each matched venue listing returns the same canonical `predexon_id`.

Use `predexon_id` for routing, positions, orderbook subscriptions, and `GET /v2/sports/outcomes/{predexon_id}`. Use venue-native identifiers only when executing directly on a specific venue.

## Data Sources

Sports live state v1 sources data from Polymarket and Kalshi. Predexon normalizes those updates into one stable game-state object keyed by `game_id`.

We are integrating with additional sports data providers soon to expand coverage and improve source redundancy.

## Game Coverage

Sports live state covers Predexon's matched canonical sports games: the same game universe exposed by [`GET /v2/sports/games`](/api-reference/sports/games).

Use the discovery endpoints to get the current event list:

```text theme={null}
GET /v2/sports/games
GET /v2/sports/games?league=mlb
GET /v2/sports/live
```

The websocket all-games subscription follows that same matched sports coverage:

```json theme={null}
{
  "action": "subscribe",
  "platform": "predexon",
  "version": 1,
  "type": "sports_live",
  "filters": {
    "game_ids": ["*"]
  }
}
```

Current sports market coverage follows the [venue coverage matrix](/concepts/sports-markets#venue-coverage). Live-state data is available when one of the live-state sources has data for that covered game.

## Key Incidents and Event Lists

The live-state object includes a normalized event list in `significant_events[]`.

`significant_events[]` is for key incidents, not full box-score or every vendor-specific stat. When source data is available, events can include:

| Event type     | Description                                                                                                          |
| -------------- | -------------------------------------------------------------------------------------------------------------------- |
| `score_change` | A scoring event, including soccer goals, basketball made shots/free throws, or other source-supported score changes. |
| `yellow_card`  | Soccer yellow card.                                                                                                  |
| `red_card`     | Soccer red card.                                                                                                     |
| `substitution` | Soccer substitution or other source-supplied substitution event.                                                     |
| `period_start` | Start of a period, half, quarter, map, or similar segment when exposed by the source.                                |
| `period_end`   | End of a period, half, quarter, map, or similar segment when exposed by the source.                                  |
| `game_start`   | Game started.                                                                                                        |
| `game_end`     | Game ended or final status reached.                                                                                  |
| `other`        | Source-supplied incident that does not map cleanly to a standard type yet.                                           |

Example:

```json theme={null}
{
  "type": "score_change",
  "team": "home",
  "period": "2H",
  "clock": "58'",
  "player": "Ramos, Guilherme",
  "description": "Goal for the home team",
  "source": "kalshi"
}
```

Incident availability is source- and sport-dependent. Kalshi can provide detailed game-stat/play-by-play data for supported milestones. In the current Kalshi feed, soccer commonly includes goals, cards, substitutions, period events, and game-end events; basketball can include made shots/free throws and period boundaries; baseball play-by-play is available for some games but is not always returned as typed key incidents. Polymarket's sports websocket primarily provides score, period, status, clock, and game-level state. If no key incidents are available for a game, `significant_events` is returned as an empty array.

## Aggregate State

The aggregate state is the primary client object.

```json theme={null}
{
  "game_id": "mlb-ari-pit-2026-05-07",
  "league": "mlb",
  "sport": "baseball",
  "game_date": "2026-05-07",
  "title": "Arizona Diamondbacks vs Pittsburgh Pirates",
  "home_team": {
    "code": "pit",
    "name": "Pittsburgh Pirates"
  },
  "away_team": {
    "code": "ari",
    "name": "Arizona Diamondbacks"
  },
  "participants": [
    { "code": "ari", "name": "Arizona Diamondbacks" },
    { "code": "pit", "name": "Pittsburgh Pirates" }
  ],
  "status": "InProgress",
  "status_text": "In Progress",
  "live": true,
  "ended": false,
  "period": "Top 5",
  "clock": null,
  "score": {
    "home": 2,
    "away": 4,
    "display": "2-4"
  },
  "winner": null,
  "last_play": null,
  "significant_events": [],
  "reliability": {
    "state": "single_source",
    "source_count": 1,
    "sources": ["polymarket"],
    "conflict": false,
    "stale": false
  },
  "updated_at": "2026-05-07T23:42:10Z"
}
```

## Field Semantics

| Field                       | Meaning                                                                                                                                                                                                                |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `game_id`                   | Broad sports fixture ID. Same value used by `/v2/sports/games`.                                                                                                                                                        |
| `home_team` / `away_team`   | Home/away teams when source mapping is known. May be `null` before source mapping is available.                                                                                                                        |
| `participants`              | Known participants from canonical game metadata. Present even when home/away is unknown.                                                                                                                               |
| `status`                    | Normalized or source-derived game status.                                                                                                                                                                              |
| `status_text`               | Human-readable status when available.                                                                                                                                                                                  |
| `live`                      | Whether the game is currently in progress.                                                                                                                                                                             |
| `ended`                     | Whether the game has ended.                                                                                                                                                                                            |
| `period`                    | Sport-specific period: inning, quarter, half, map number, etc.                                                                                                                                                         |
| `clock`                     | Sport-specific clock when available. May be `null` for sports like baseball.                                                                                                                                           |
| `score.home` / `score.away` | Score by home/away team when home/away mapping is known.                                                                                                                                                               |
| `score.display`             | Source or aggregate display score.                                                                                                                                                                                     |
| `winner`                    | Winner when known: typically `home`, `away`, `draw`, or a source-native value.                                                                                                                                         |
| `last_play`                 | Latest notable play when available. When present, it maps to the most recent item in `significant_events`. It can be `null` when no notable incident has happened yet or the source has not supplied one at that time. |
| `significant_events`        | Normalized key incident list. Can include score changes, cards, substitutions, period events, game start/end, or source-supported `other` events. Empty when no incidents are available.                               |
| `reliability`               | Source agreement and freshness summary.                                                                                                                                                                                |
| `updated_at`                | Last aggregate update timestamp.                                                                                                                                                                                       |

## Reliability

`reliability` is not a model confidence score. It is a data-quality summary based on direct source names, source agreement, and freshness.

| State           | Meaning                                                                     |
| --------------- | --------------------------------------------------------------------------- |
| `no_data`       | The game exists, but no source has written live state.                      |
| `single_source` | One source has current state.                                               |
| `confirmed`     | Two or more sources agree on material fields.                               |
| `conflict`      | Sources disagree on material fields such as score, winner, or ended status. |
| `stale`         | Latest available source state is too old for a live game.                   |

The boolean fields make the state easy to consume:

| Field          | Meaning                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------- |
| `sources`      | Direct source names used for the aggregate, such as `polymarket` or `kalshi`.               |
| `source_count` | Number of source snapshots used. Equal to `sources.length` when source names are available. |
| `conflict`     | Whether material source disagreement exists.                                                |
| `stale`        | Whether the aggregate is stale or absent.                                                   |

For normal product surfaces, use the aggregate fields and `reliability`. For debugging or auditing, request source rows with `include_sources=true`.

## Source Snapshots

REST can include source-level rows:

```text theme={null}
GET /v2/sports/live/{game_id}?include_sources=true
```

Source snapshots are intended for audit/debug, not primary UI rendering.

```json theme={null}
{
  "source": "polymarket",
  "source_game_id": "19439",
  "source_url": null,
  "status": "InProgress",
  "status_text": "InProgress",
  "live": true,
  "ended": false,
  "period": "Top 5",
  "clock": null,
  "score": {
    "home": 2,
    "away": 4,
    "display": "2-4"
  },
  "winner": null,
  "last_play": null,
  "significant_events": [],
  "details": {
    "slug": "mlb-pit-ari-2026-05-07"
  },
  "observed_at": "2026-05-07T23:42:09Z",
  "updated_at": "2026-05-07T23:42:10Z"
}
```

## WebSocket

The websocket streams **aggregate changes**, not every raw upstream source message. This keeps client integrations simple and avoids making consumers reconcile Polymarket/Kalshi differences themselves.

Endpoint:

```text theme={null}
wss://wss.predexon.com/v1/<API_KEY>
```

Authentication uses the same data key as REST, passed in the websocket URL:

```text theme={null}
wss://wss.predexon.com/v1/YOUR_DATA_KEY
```

## Subscription Messages

Subscribe to all matched sports games Predexon currently covers:

```json theme={null}
{
  "action": "subscribe",
  "platform": "predexon",
  "version": 1,
  "type": "sports_live",
  "filters": {
    "game_ids": ["*"]
  }
}
```

Subscribe by league:

```json theme={null}
{
  "action": "subscribe",
  "platform": "predexon",
  "version": 1,
  "type": "sports_live",
  "filters": {
    "leagues": ["mlb"]
  }
}
```

Subscribe by explicit games:

```json theme={null}
{
  "action": "subscribe",
  "platform": "predexon",
  "version": 1,
  "type": "sports_live",
  "filters": {
    "game_ids": ["mlb-ari-pit-2026-05-07"]
  }
}
```

Filters:

| Field      | Type      | Meaning                                                         |
| ---------- | --------- | --------------------------------------------------------------- |
| `game_ids` | string\[] | Subscribe to specific games. Use `["*"]` for all matched games. |
| `leagues`  | string\[] | Subscribe to all games in one or more leagues.                  |
| `sports`   | string\[] | Subscribe to all games in one or more sports.                   |

Exactly one of `game_ids`, `leagues`, or `sports` is required.

Unsubscribe:

```json theme={null}
{
  "action": "unsubscribe",
  "subscription_id": "sub_01"
}
```

## Server Messages

Subscription acknowledgement:

```json theme={null}
{
  "type": "ack",
  "subscription_id": "sub_01",
  "channel": "sports_live"
}
```

Aggregate update:

```json theme={null}
{
  "type": "event",
  "subscription_id": "sub_01",
  "data": {
    "event_type": "sports_live_state",
    "sequence": 1842,
    "game_id": "mlb-ari-pit-2026-05-07",
    "league": "mlb",
    "sport": "baseball",
    "home_team": {
      "code": "pit",
      "name": "Pittsburgh Pirates"
    },
    "away_team": {
      "code": "ari",
      "name": "Arizona Diamondbacks"
    },
    "updated_at": "2026-05-07T23:42:10Z",
    "status": "InProgress",
    "live": true,
    "ended": false,
    "period": "Top 5",
    "clock": null,
    "score": {
      "home": 2,
      "away": 4,
      "display": "2-4"
    },
    "winner": null,
    "reliability": {
      "state": "single_source",
      "source_count": 1,
      "sources": ["polymarket"],
      "conflict": false,
      "stale": false
    }
  }
}
```

Error:

```json theme={null}
{
  "type": "error",
  "code": "INVALID_FILTERS",
  "message": "Sports live subscriptions require exactly one of game_ids, leagues, or sports"
}
```

## Heartbeats and Reconnects

The gateway uses websocket ping/pong frames for connection liveness. Clients should respond to ping frames according to their websocket library's normal behavior.

If the connection drops, clients should reconnect and resubscribe. The REST endpoint should be used to rehydrate current state after reconnect:

```text theme={null}
GET /v2/sports/live?league=mlb
```

The websocket version does not require clients to track replay cursors. If replay is added later, it should be additive through a field such as `since_sequence`.

## Update Policy

The websocket emits an update when the aggregate changes materially:

* Score changed
* Period changed
* Clock changed
* Key incidents changed
* `live` or `ended` changed
* Winner changed
* Reliability changed
* Source conflict appeared or resolved
* Stale state appeared or resolved

The websocket does not emit every upstream heartbeat or duplicate source message.

## Sports-Specific Notes

| Sport          | Common `period` / `clock` behavior                                         |
| -------------- | -------------------------------------------------------------------------- |
| MLB            | `period` may be inning state such as `Top 5`; `clock` is usually `null`.   |
| NBA/NFL/CFB    | `period` is quarter; `clock` is game clock when supplied.                  |
| Soccer         | `period` is half/status; `clock` may be elapsed match time.                |
| NHL            | `period` is period/overtime/shootout; `clock` is game clock when supplied. |
| Tennis/esports | `period` may be set/map number; score display can be source-specific.      |

## Non-Goals

The live-state API is not intended to expose every possible vendor-specific stat.

The stable public contract is:

* Current score
* Period/clock/status
* Winner/end state
* Significant events when available
* Source reliability
* Optional source snapshots for audit/debug

Full play-by-play, detailed box scores, and sport-specific stat feeds may be added later as separate endpoints if needed.
