

## Drive chart for a game [#drive-chart-for-a-game]

```python title="nfl_drives.py"
import os, requests
KEY = os.environ["STATSHAWK_KEY"]
BASE = "https://api.statshawk.ai/v1"

games = requests.get(
    f"{BASE}/competitions/nfl/editions/2026/games",
    headers={"X-API-Key": KEY},
    params={"stage": "preseason", "date": "2026-08-13"},
    timeout=10,
).json()["data"]["items"]

pbp = requests.get(
    f"{BASE}/contests/{games[0]['id']}/play-by-play",
    headers={"X-API-Key": KEY},
    timeout=15,
).json()["data"]

for d in pbp["drives"]:
    plays = d.get("plays") or []
    print(
        f"D{d['drive_number']:>2} {d['team']['name']:<22} "
        f"{d.get('offensive_plays', len(plays)):>2} plays "
        f"{d.get('yards', 0):>3} yds → {d.get('display_result') or d.get('result')}"
    )
```

<Callout type="info">
  Football play-by-play returns `drives` — one flat array of drives in game order, each
  with its ordered plays. While a game is in progress the in-flight drive is included as
  the last element — its `end` boundary is present but unpopulated until the drive
  finishes (don't branch on the field being absent). Plays carry the down,
  distance, yards to the end zone, running score, and a `play_type` from ESPN's typed
  vocabulary (`Field Goal Good`, `Blocked Punt`, `Interception Return Touchdown`, …), so
  scoring and special-teams events need no text parsing. The `standard` and `full` detail
  tiers add the win-probability series. Baseball contests return the Statcast shape from
  the same endpoint — the response is shaped by the contest's sport.
</Callout>

<PlaygroundLink href="/docs/api">
  Open the contest play-by-play endpoint in the playground →
</PlaygroundLink>
