# GET /v2/fixtures/{id}/play-by-play

Group: Fixtures

The source’s text commentary, one entry per action, oldest first: football (cards, shots, corners, substitutions, … by minute) and basketball (every basket, free throw, rebound, foul, turnover — with the game clock, the running score, what the basket was worth and where on the court).

Plans: Pro + Business only (other plans get 403 endpoint_not_in_plan).

Note: Written by the source’s data provider, in English — not our AI commentary (that is /commentary). type is a closed enum (other for anything we do not map); every field is present on every entry, null when it does not apply: football has minute / addedMinute, basketball periodSecond (seconds played in the period), periodSecondsLeft (the game clock), at, homeScore / awayScore on scoreChange (and on a football penaltyScored, counted on from the previous goal), scoreType on basketball scoreChange, and position / zone on the court. An empty array when the source has none.

## Parameters

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `id` | path | yes | our numeric id (positive integer) |

## Response

- `data`: `PlayByPlayEntry[]`
- `meta`: count
- Objects: PlayByPlayEntry (https://sportsapi.app/markdown/en/reference.md#playbyplayentry)

## Errors

- 403 history_not_in_plan — the fixture kicked off before your plan’s history

Plus the common errors (https://sportsapi.app/markdown/en/docs.md#errors).

## Request

cURL:

```bash
curl -H "Authorization: Bearer sk_live_…" \
    "https://api.sportsapi.app/v2/fixtures/{id}/play-by-play"
```

TypeScript:

```ts
const { data, meta } = await client.fixtures.playByPlay(id);
```

Python:

```python
res = client.fixtures.play_by_play(id)
```

Go:

```go
res, err := client.Fixtures.PlayByPlay(ctx, id)
```

CLI:

```bash
$ sportsapi fixtures play-by-play <id>
```

## Example response

```json
{ "data": [
  { "type": "yellowCard", "side": "home", "period": "period1", "minute": 45, "addedMinute": 6,
    "periodSecond": null, "periodSecondsLeft": null, "at": null,
    "text": "Lewis Cook (Bournemouth) is shown the yellow card for a bad foul.",
    "player": null, "assist": null, "playerIn": null, "playerOut": null, "drawnBy": null, "stolenBy": null,
    "goalkeeper": null, "homeScore": null, "awayScore": null, "scoreType": null, "position": null, "zone": null } ],
  "meta": { "count": 1 } }

// Basketball:
{ "data": [ …,
  { "type": "scoreChange", "side": "away", "period": "period4", "minute": null, "addedMinute": null,
    "periodSecond": 700, "periodSecondsLeft": 20, "at": "2026-10-22T01:54:25.605Z",
    "text": "Jalen Johnson makes regular free throw 2 of 2",
    "player": { "id": 123, "name": "Jalen Johnson", "slug": null, "shortName": null, "image": "https://cdn.sportsapi.app/v2/players/123/photo" },
    "assist": null, "playerIn": null, "playerOut": null, "drawnBy": null, "stolenBy": null, "goalkeeper": null,
    "homeScore": 125, "awayScore": 132, "scoreType": "freeThrow", "position": null, "zone": null } ],
  "meta": { "count": 486 } }
```

---

Base URL: https://api.sportsapi.app. Send your API key as `Authorization: Bearer <key>` on every /v2 request; keys are created in the dashboard (https://sportsapi.app/dashboard).
HTML: https://sportsapi.app/docs/fixtures/play-by-play · All docs: https://sportsapi.app/markdown/en/docs.md
