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

# Sportrix Data Live Snapshot Object — Schema Reference

> The live snapshot object is returned by GET /live, GET /result, and WebSocket frames. The shape depends on the sport — soccer carries a clock, phase, stats, and events; cricket carries an innings score, batsmen, bowler, current over, and a full per-innings scorecard.

The live snapshot is the data shape that carries real-time match state across both REST and WebSocket surfaces. Whether you poll on demand or receive pushed updates, the structure is consistent within a sport.

<Note>
  **The snapshot schema depends on the sport.** Always branch on the `sport` field. This page documents the **soccer** snapshot first, then the **cricket** snapshot (which has a completely different shape — no `clock`, `phase`, `stats`, or `events`; instead an innings score, batting/bowling cards, a current-over ticker, and a per-innings `scorecard`). Other sports will follow over time; treat unknown fields as optional.
</Note>

## Used by

* `GET /matches/{id}/live` — returns the snapshot directly
* `GET /matches/{id}/result` — returns the snapshot as `half_time` and `full_time` objects
* WebSocket `snapshot` and `update` frames — the snapshot is the `data` field

## The soccer live snapshot object

Returned with `"sport": "soccer"`.

### Top-level fields

<ResponseField name="v" type="integer" required>
  Schema version. Currently `1`.
</ResponseField>

<ResponseField name="match_id" type="integer">
  Your match id. Present on WebSocket frames for multiplexing; omitted on REST responses.
</ResponseField>

<ResponseField name="provider" type="object">
  Upstream reference ids. Clients can usually ignore this object.

  <Expandable title="Provider fields">
    <ResponseField name="stat_id" type="string">
      Upstream statistics topic id. Always present.
    </ResponseField>

    <ResponseField name="live_id" type="string">
      Upstream live id (optional).
    </ResponseField>

    <ResponseField name="fixture_id" type="string">
      Upstream fixture id (optional).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="sport" type="string" required>
  `"soccer"`.
</ResponseField>

<ResponseField name="competition" type="string" required>
  League or competition name, e.g. `"USA MLS Next Pro League"`.
</ResponseField>

<ResponseField name="home" type="string" required>
  Home team name.
</ResponseField>

<ResponseField name="away" type="string" required>
  Away team name.
</ResponseField>

<ResponseField name="status" type="string" required>
  Current match state: `live`, `ht` (half-time), `ft` (full-time), or `not_started`.
</ResponseField>

<ResponseField name="clock" type="object" required>
  Match clock. See [Clock](#clock) below.
</ResponseField>

<ResponseField name="score" type="object" required>
  Current score as `{"home": int, "away": int}`.
</ResponseField>

<ResponseField name="phase" type="object" required>
  Decoded current game state. See [Phase](#phase) below.
</ResponseField>

<ResponseField name="stats" type="object" required>
  Map of stat key → `{"home": int, "away": int}`. See [Statistics](/api/events-stats#statistics).
</ResponseField>

<ResponseField name="events" type="array | null">
  Timeline incidents. `null` if no events have occurred yet. See [Events](/api/events-stats#events).
</ResponseField>

<ResponseField name="ball" type="object">
  Last event-anchored ball position on the pitch. See [Ball Position](/api/events-stats#ball-position).
</ResponseField>

<ResponseField name="updated_at" type="datetime" required>
  When this snapshot was produced, in ISO 8601 UTC.
</ResponseField>

### Clock

<Expandable title="Clock fields">
  <ResponseField name="minute" type="integer">
    Current match minute.
  </ResponseField>

  <ResponseField name="second" type="integer">
    Current second within the minute.
  </ResponseField>

  <ResponseField name="period" type="string">
    Current period: `1H`, `2H`, `HT`, or `FT`.
  </ResponseField>

  <ResponseField name="running" type="boolean">
    `true` while the clock is ticking; `false` during breaks (half-time, full-time).
  </ResponseField>

  <ResponseField name="added" type="integer">
    Stoppage or added minutes, when applicable.
  </ResponseField>

  <ResponseField name="as_of" type="datetime">
    UTC ISO 8601 wall time that `minute:second` corresponds to — the moment of the last provider frame that updated the clock. Used to project the clock forward between frames. Omitted when there is no anchor (e.g. before kickoff).
  </ResponseField>
</Expandable>

#### Displaying a live timer

`minute:second` is the clock as of `as_of`, not as of right now. How you turn it into a ticking timer depends on which surface you read from:

* **REST (`GET /matches/{id}/live`)** — the server projects the clock forward to request time before responding. When `running` is `true`, `minute:second` is already current and `as_of` is set to the response time. Display `minute:second` as-is.
* **WebSocket `snapshot` and `update` frames** — frames carry the clock as of the last provider update, so consumers must advance it themselves between frames. While `running` is `true`:

  ```text theme={null}
  displayed_seconds = (minute * 60 + second) + (now − as_of)
  ```

  When `running` is `false` (half-time, full-time, stoppages), do **not** project — display `minute:second` as-is. A new frame will reset the anchor when play resumes.

The clock only ticks within the current period; period transitions (e.g. `1H` → `HT` → `2H`) always arrive in a real frame, so the projected value can run uncapped through stoppage time and snaps back if the provider pauses silently.

### Phase

The phase object describes what is happening on the pitch right now.

<Expandable title="Phase fields">
  <ResponseField name="team" type="string">
    Which team the phase involves: `"home"`, `"away"`, or an empty string.
  </ResponseField>

  <ResponseField name="code" type="string">
    Decoded state code.
  </ResponseField>

  <ResponseField name="label" type="string">
    Human-readable label, e.g. `"Dangerous attack"`, `"Corner"`, `"Goal"`, `"Safe possession"`.
  </ResponseField>

  <ResponseField name="vc" type="string">
    Raw provider game-state code. Clients can usually ignore this.
  </ResponseField>
</Expandable>

### Full soccer example

```json theme={null}
{
  "v": 1,
  "match_id": 41282,
  "provider": {"stat_id": "151350409062M1_1"},
  "sport": "soccer",
  "competition": "USA MLS Next Pro League",
  "home": "Vancouver Whitecaps II",
  "away": "The Town",
  "status": "live",
  "clock": {"minute": 75, "second": 56, "period": "2H", "running": true, "added": 0, "as_of": "2026-06-18T02:56:50Z"},
  "score": {"home": 3, "away": 2},
  "phase": {"vc": "21002", "team": "away", "code": "1002", "label": "Dangerous attack"},
  "stats": {
    "shots_on_target": {"home": 4, "away": 2},
    "possession": {"home": 56, "away": 44},
    "corners": {"home": 5, "away": 3}
  },
  "events": [
    {"minute": "60", "type": "goal", "team": "home", "label": "Goal", "score": "1-0"}
  ],
  "ball": {"x": 0.91, "y": 0.5, "event": "goal", "minute": "60"},
  "updated_at": "2026-06-18T02:56:50Z"
}
```

## The cricket live snapshot object

Returned with `"sport": "cricket"` from the same surfaces as the soccer snapshot — `GET /matches/{id}/live` and the WebSocket `data` field. The shape is different: an innings score, the batting and bowling cards, a current-over ticker, the last decoded incident, and a full per-innings `scorecard`. There is no `clock`, `phase`, `stats`, `events`, or `ball`.

### Reading a cricket snapshot

The payload has **two layers** — a quick-glance live state and the full card:

* **Live, at a glance** (top level): `score` (the current innings total), `over` (the over in progress), `batsmen` (the two at the crease), `bowler` (current spell), and `last_event`. This is everything you need for a compact live scoreboard — e.g. *"West Indies 138/3 (40.1) — Jangoo 20\*, Da Silva 12\* — Dinusha 9-0-25-1"*.
* **Full detail** (`scorecard`): every innings of the match in order, each with its complete batting and bowling cards, fall of wickets, and an over-by-over breakdown (`overs`: runs in that over plus cumulative score — the data behind a worm or run-rate graph). Use this for a full scorecard view.

The top-level `score`/`batsmen`/`bowler`/`over` describe the **same innings** that is flagged `"live": true` in `scorecard`. They come from two separate provider feeds, so they can differ by a ball or two for a moment; the next frame reconciles them. `scorecard` is omitted until the match is live mid-session — limited-overs games have up to two innings, a Test up to four.

<Note>
  **Multi-day Tests.** Between days a Test is at *stumps*: the live snapshot **freezes** at the last ball — no new frames until play resumes the next day — and the catalog match object's `status` becomes `CLOSE_OF_PLAY` (see [Match status values](/api/match-object#status-values)), so the match stays visible in `/matches` and `/matches/live` rather than disappearing overnight. The snapshot's own `status` (below) is the in-play state and is distinct from that catalog lifecycle status.
</Note>

### Top-level fields

<ResponseField name="match_id" type="integer">
  Your match id. Present on WebSocket frames.
</ResponseField>

<ResponseField name="sport" type="string" required>
  `"cricket"`.
</ResponseField>

<ResponseField name="competition" type="string" required>
  Competition or match name, e.g. `"West Indies vs Sri Lanka - 1st Test"`.
</ResponseField>

<ResponseField name="home" type="string" required>
  Home team name.
</ResponseField>

<ResponseField name="away" type="string" required>
  Away team name.
</ResponseField>

<ResponseField name="status" type="string" required>
  Current match state: `not_started`, `live`, `innings_break`, `stopped` (rain, bad light, tea, …), or `ended`.
</ResponseField>

<ResponseField name="match_type" type="string" required>
  Format: `test`, `t20`, `one_day` (50-over), `the_hundred`, or `limited_overs` (overs not yet known).
</ResponseField>

<ResponseField name="innings" type="integer" required>
  Current innings number.
</ResponseField>

<ResponseField name="batting" type="string" required>
  Side at the crease: `"home"` or `"away"`.
</ResponseField>

<ResponseField name="score" type="object" required>
  The batting side's innings score. See [Cricket score](#cricket-score) below.
</ResponseField>

<ResponseField name="set_score" type="string">
  Raw score string from the provider; for a multi-innings match it may carry prior innings too.
</ResponseField>

<ResponseField name="over" type="object" required>
  Current-over ticker. See [Over](#over) below.
</ResponseField>

<ResponseField name="batsmen" type="array" required>
  The two batters at the crease. See [Batsman](#batsman) below.
</ResponseField>

<ResponseField name="bowler" type="object" required>
  Current bowler's spell figures. See [Bowler](#bowler) below.
</ResponseField>

<ResponseField name="last_event" type="object">
  The decoded last incident. See [Last event](#last-event) below.
</ResponseField>

<ResponseField name="scorecard" type="array">
  Full per-innings card (all innings, in order). See [Scorecard](#scorecard) below. Omitted until the match is live mid-session.
</ResponseField>

<ResponseField name="t" type="datetime" required>
  When this snapshot was produced, in ISO 8601 UTC.
</ResponseField>

### Cricket score

The batting side's current innings total.

<Expandable title="Score fields">
  <ResponseField name="runs" type="integer">
    Runs scored.
  </ResponseField>

  <ResponseField name="wickets" type="integer">
    Wickets fallen.
  </ResponseField>

  <ResponseField name="overs" type="string">
    Overs faced, e.g. `"62.1"`.
  </ResponseField>

  <ResponseField name="raw" type="string">
    Raw score string, e.g. `"262/6"`.
  </ResponseField>
</Expandable>

### Over

Ticker for the over in progress.

<Expandable title="Over fields">
  <ResponseField name="over" type="integer">
    Over in progress (1-based).
  </ResponseField>

  <ResponseField name="ball" type="integer">
    Ball within the over.
  </ResponseField>

  <ResponseField name="this_over" type="array">
    The deliveries bowled in this over so far (runs as strings, `"W"` for a wicket, etc.).
  </ResponseField>
</Expandable>

### Batsman

Each entry in `batsmen` describes one of the two batters at the crease.

<Expandable title="Batsman fields">
  <ResponseField name="name" type="string">
    Batter name.
  </ResponseField>

  <ResponseField name="runs" type="integer">
    Runs scored in this innings.
  </ResponseField>

  <ResponseField name="balls" type="integer">
    Balls faced in this innings.
  </ResponseField>

  <ResponseField name="on_strike" type="boolean">
    `true` for the batter on strike. Omitted on the non-striker.
  </ResponseField>
</Expandable>

### Bowler

The current bowler's spell figures.

<Expandable title="Bowler fields">
  <ResponseField name="name" type="string">
    Bowler name.
  </ResponseField>

  <ResponseField name="overs" type="string">
    Overs bowled this spell.
  </ResponseField>

  <ResponseField name="maidens" type="integer">
    Maiden overs.
  </ResponseField>

  <ResponseField name="runs" type="integer">
    Runs conceded.
  </ResponseField>

  <ResponseField name="wickets" type="integer">
    Wickets taken.
  </ResponseField>
</Expandable>

### Scorecard

`scorecard` is an array of innings — every innings of the match, in order. The live innings is flagged with `"live": true`; finished innings carry their final figures; innings yet to bat are present but omit `score`.

<Expandable title="Innings fields">
  <ResponseField name="team" type="string">
    Batting team, e.g. `"West Indies"`.
  </ResponseField>

  <ResponseField name="phase" type="string">
    `1st` or `2nd` (this team's innings number).
  </ResponseField>

  <ResponseField name="score" type="string">
    Innings score, e.g. `"138/3"`. Omitted for an innings yet to bat.
  </ResponseField>

  <ResponseField name="live" type="boolean">
    `true` for the innings in progress. Omitted otherwise.
  </ResponseField>

  <ResponseField name="batting" type="array">
    Batting card — one row per batter. Each row has `name`, `dismissal` (`"c X b Y"`, `"not out"`, …), `runs`, `balls`, `fours`, `sixes`, and `strike_rate`.
  </ResponseField>

  <ResponseField name="bowling" type="array">
    Bowling card — one row per bowler. Each row has `name`, `overs`, `maidens`, `runs`, `wickets`, and `economy`.
  </ResponseField>

  <ResponseField name="fall_of_wickets" type="array">
    Wickets in the order they fell: `{ "wicket": int, "score": int, "batsman": string }`.
  </ResponseField>

  <ResponseField name="overs" type="array">
    Per-over breakdown: `{ "over": int, "runs": int, "score": string }` — `runs` is the runs in that over, `score` the cumulative innings score after it. Drives a worm or run-rate graph.
  </ResponseField>

  <ResponseField name="extras" type="integer">
    Total extras for the innings. Omitted if none.
  </ResponseField>

  <ResponseField name="extras_detail" type="string">
    Extras breakdown, e.g. `"b 16,lb 1,w 1,nb 2,P 0"`.
  </ResponseField>
</Expandable>

### Last event

The decoded last incident on the field.

<Expandable title="Last event fields">
  <ResponseField name="vc" type="string">
    Raw provider code.
  </ResponseField>

  <ResponseField name="team" type="string">
    `"home"`, `"away"`, or an empty string.
  </ResponseField>

  <ResponseField name="code" type="string">
    Decoded code.
  </ResponseField>

  <ResponseField name="label" type="string">
    Human-readable label, e.g. `runs`, `wicket`, `bowled`, `LBW`, `caught`, `bowling`, `century`, `end of over`.
  </ResponseField>
</Expandable>

### Full cricket example

```json theme={null}
{
  "match_id": 41822,
  "sport": "cricket",
  "competition": "West Indies vs Sri Lanka - 1st Test",
  "home": "West Indies",
  "away": "Sri Lanka",
  "status": "live",
  "match_type": "test",
  "innings": 2,
  "batting": "home",
  "score": {"runs": 138, "wickets": 3, "overs": "40.1", "raw": "138/3"},
  "set_score": "138/3",
  "over": {"over": 41, "ball": 1, "this_over": ["1"]},
  "batsmen": [
    {"name": "AA Jangoo", "runs": 20, "balls": 46, "on_strike": true},
    {"name": "J Da Silva", "runs": 12, "balls": 36}
  ],
  "bowler": {"name": "GS Dinusha", "overs": "9.0", "maidens": 0, "runs": 25, "wickets": 1},
  "last_event": {"vc": "21206", "team": "away", "code": "1206", "label": "bowling"},
  "scorecard": [
    {
      "team": "Sri Lanka", "phase": "1st", "score": "308",
      "batting": [
        {"name": "N Madushka", "dismissal": "c Da Silva b Seales", "runs": 84, "balls": 142, "fours": 9, "sixes": 1, "strike_rate": "59"}
      ],
      "bowling": [
        {"name": "JNT Seales", "overs": "22.0", "maidens": 5, "runs": 71, "wickets": 4, "economy": "3.23"}
      ],
      "fall_of_wickets": [
        {"wicket": 10, "score": 308, "batsman": "CAK Rajitha"}
      ],
      "extras": 17, "extras_detail": "b 4,lb 9,w 2,nb 2,P 0"
    },
    {
      "team": "West Indies", "phase": "1st", "score": "138/3", "live": true,
      "batting": [
        {"name": "JD Campbell", "dismissal": "c N Madushka b GS Dinusha", "runs": 39, "balls": 64, "fours": 3, "sixes": 2, "strike_rate": "61"},
        {"name": "AA Jangoo", "dismissal": "not out", "runs": 20, "balls": 46, "fours": 3, "sixes": 0, "strike_rate": "43"}
      ],
      "bowling": [
        {"name": "RMMP Rathnayaka", "overs": "11.0", "maidens": 2, "runs": 30, "wickets": 2, "economy": "2.73"}
      ],
      "fall_of_wickets": [
        {"wicket": 1, "score": 58, "batsman": "BA King"},
        {"wicket": 2, "score": 97, "batsman": "JD Campbell"}
      ],
      "overs": [
        {"over": 1, "runs": 0, "score": "0/0"},
        {"over": 2, "runs": 12, "score": "12/0"}
      ],
      "extras": 20, "extras_detail": "b 16,lb 1,w 1,nb 2,P 0"
    }
  ],
  "t": "2026-06-25T11:30:00Z"
}
```

<Note>
  The `batting` and `bowling` arrays above are trimmed to one or two rows for brevity; a real innings carries every batter and bowler.
</Note>

## Appendix: enumerations

**Snapshot `sport`:** `soccer`, `cricket`. Other sports may appear in future — branch on this field.

**Snapshot `status` — soccer:** `not_started`, `live`, `ht`, `ft`.

**Snapshot `status` — cricket:** `not_started`, `live`, `innings_break`, `stopped` (rain, bad light, tea, …), `ended`.

**Cricket `match_type`:** `test`, `t20`, `one_day` (50-over), `the_hundred`, `limited_overs` (overs not yet known).

**Clock period (soccer):** `1H`, `2H`, `HT`, `FT` (and similar period codes).

**Event type (soccer):** `goal`, `corner`, `yellow_card`, `red_card`, `penalty`, `substitution`, `event`.

**Common soccer stat keys:** `shots_on_target`, `shots_off_target`, `attacks`, `dangerous_attacks`, `possession`, `corners`, `yellow_cards`, `red_cards`.

**Cricket `last_event.label`** is drawn from the provider's incident table, e.g. `runs`, `bye`, `wide`, `no ball`, `wicket`, `bowled`, `LBW`, `caught`, `stumped`, `run out`, `bowling`, `maiden over`, `end of over`, `duck`, `century`, `review`, `innings break`, `match ended`.

**Catalog match status** (for the [match object](/api/match-object), not the live snapshot): `NOT_STARTED`, `STARTED`, `CLOSE_OF_PLAY` (multi-day cricket Test between days), `FINISHED`.
