---
title: "Cricket ball-by-ball deliveries"
method: GET
path: "/v1/cricket/matches/{id}/deliveries"
tags: ["cricket"]
---

# Cricket ball-by-ball deliveries

`GET /v1/cricket/matches/{id}/deliveries`

## Request

- Base URL: `https://api.bigballsdata.com`
- URL: `https://api.bigballsdata.com/v1/cricket/matches/{id}/deliveries`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Stored ball-by-ball for one cricket match. Requires Pro or higher. This is a new capability; the innings scorecard and existing cricket match, series, player and tutorial surfaces remain available on Free. Wides and no-balls are delivery records and remain present as rows. Same-day double-headers can share a canonical match id; when that happens, retry with one of the opaque stream numbers returned in meta.available_streams. Internal source references are never exposed.

## Path parameters

- `id` string, uuid, required: A stored BigBalls id. This is the identifier every match, team, player and league endpoint returns, and the one every `{id}` path segment accepts. Take it from the `id` field of the corresponding list endpoint and use it as-is.

## Query parameters

- `stream` integer
- `cursor` string
- `limit` integer

## Response `200`

A collision-safe page of stored deliveries.

- object: The standard response wrapper. Only `data` is guaranteed. `error` is absent (not null) on 16 of 40 live 200 responses measured 2026-09-18, so test for the KEY before reading it; this block declared it required until then. On a non-2xx, `error` is present and `data` is absent.
  - `data` object, required
    - `match_id` string, uuid, required
    - `deliveries` object[], required
      - `innings_number` integer, required
      - `super_over` boolean, required
      - `over_number` integer, required
      - `ball_seq` integer, required
      - `batting_team` object, nullable
        - `id` string, uuid, required
        - `name` string, nullable, required
      - `batter` object, required
        - `id` string, uuid, required
        - `name` string, nullable, required
      - `bowler` object, required
        - `id` string, uuid, required
        - `name` string, nullable, required
      - `non_striker` object, nullable
        - `id` string, uuid, required
        - `name` string, nullable, required
      - `runs` object, required
        - `batter` integer, required
        - `extras` integer, required
        - `total` integer, required
      - `extras` object, required
        - `wides` integer, required
        - `no_balls` integer, required
        - `byes` integer, required
        - `leg_byes` integer, required
        - `penalty` integer, required
      - `wicket` object, nullable, required
        - `kind` string, required
        - `player_out` object, nullable, required
          - `id` string, uuid, required
          - `name` string, nullable, required
        - `fielder_ids` string[], required
  - `meta` object: Response metadata. NOTHING here is guaranteed: measured over 38 live envelopes on 2026-09-18, `cached` and `request_id` appeared in 29, `source` in 28, `cache_age_ms` in 9 and `confidence` in 6. This block previously declared all five REQUIRED, which no response has ever satisfied. Treat every field as optional and branch on its absence. Routes add their own keys here (`count`, `limit`, `offset`, `note`, `total`, and per-endpoint ones), so do not assume a closed set.
    - `date_window` object: Present when ?date= was applied. The exact window the filter used, so an omission at a day boundary is visible. start_utc is inclusive, end_utc exclusive. timezone is UTC, or the zone named by ?tz=, in which case the window is that local day. Boxing card dates are published event dates, so timezone and bounds are null there.
      - `date` string
      - `timezone` string, nullable
      - `start_utc` string, date-time, nullable
      - `end_utc` string, date-time, nullable
      - `note` string
    - `source` 'official-league' | 'aggregator-paid' | 'aggregator-free' | 'community-scraper' | 'forecast' | 'mixed' | 'cache' | 'none' | 'unknown-source' | 'stored' | 'catalogue' | 'gateway' | 'coverage-snapshot': Opaque source-tier label. Customers never see the vendor identity. `forecast` marks a weather forecast (GET /v1/matches/{id}/weather).
    - `confidence` number, float
    - `cached` boolean
    - `cache_age_ms` integer
    - `request_id` string
    - `fields_missing` string[]
    - `note` string: Short factual disclosure about something this response deliberately withheld, present only when there is something to disclose. On live scores it appears when `match_id` could not be resolved to a stored match and was therefore omitted: it gives the counts and points at `/v1/stored/matches`, whose ids you can call back into. Absent when every served id resolves. Distinct from `message`, which explains `coverage: false` or a stale response. This one is attached to a response that DID serve data and names the part of it that is deliberately missing.
    - `available` boolean, required
    - `count` integer, required
    - `limit` integer, required
    - `stream` integer, nullable, required
    - `available_streams` integer[], required
    - `next_cursor` string, nullable, required
  - `error` ApiError
    - `code` string, required
    - `message` string, required
    - `details` unknown

## Other responses

- `400`: Invalid match id, stream, cursor or limit.
- `403`: Pro plan or higher is required.
- `404`: Match or selected delivery stream not found.
- `409`: The canonical match id represents multiple streams; retry with meta.available_streams.
- `429`: Rate limited (`429`). Two causes share `error.code: rate_limited` and are told apart by `error.message` and headers: - **Quota exhaustion** (per-minute or per-day cap). The envelope is enriched: `suggested_fix` names the next tier and its cap, and `meta.current_usage` + `meta.upgrade_path` carry live usage and the upgrade target. `X-RateLimit-Limit/-Remaining/-Reset` are present. - **4xx circuit breaker** (sustained high 4xx rate: malformed requests, or ignoring Retry-After and hammering past quota; key in cooldown). Carries `X-RateLimit-4xx-Cooldown`; no `upgrade_path`. Additive: existing parsers keying on `error.code`, `error.message`, `docs_url`, `support`, `meta.request_id` are unaffected. `X-RateLimit-Limit/-Remaining/-Reset` are returned on every authenticated response (2xx/4xx/5xx), not only on 429s, so clients can self-throttle.
- `503`: Service temporarily unavailable (`503`). Returned when a backing query exceeds the endpoint's `statement_timeout` (Postgres cancels it) instead of holding the connection for seconds. Transient under heavy load; retry after a short delay. Standard error envelope with `error.code = upstream_unavailable`.

---

[API](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api.md) · [All operations](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api/revisions/31fb54ac414e?raw)
