Examples
Worked, copy-pasteable walkthroughs that assemble real datasets from the API — one set per sport.
NFL
A box score is one game plus the per-player stat lines for both teams. Find a game in the current season, fetch its player stats, and group them by team.
List endpoints accept whitelisted filter parameters. This example resolves the current season from the API (so it survives the annual rollover) and uses it to filter games.
Every stat-api client reads its key from the STAT_API_KEY environment variable, so a first program is just: construct the client, call a list endpoint, and look at the rows.
Every table exposes an auto-paging iterator that follows the next_from_id keyset cursor until it runs out — so you can consume a whole table without writing the paging loop.
A game log is one player's per-game stat lines with the game context joined back in. Resolve the season, index its games by id, borrow a player from one game's box score, then page that player's stats and join each row to its game.
Grab a team to borrow its id, then list players filtered by team_id — the players endpoint accepts team_id as a filter for both NFL rosters.
season_player_stats holds one row per player per season. Resolve the current season, page through all of it with the auto-pager, then sort client-side to build any leaderboard.
season_team_stats has one row per team per season — wins, losses, games played. Resolve the current season, page the whole table, and sort by wins to build the standings.
NBA
A box score is one game plus the per-player stat lines for both teams. Find a game in the current season, fetch its player stats, and group them by team.
The SDK maps status codes to typed errors — AuthenticationError (401), ValidationError (400), NotFoundError (404), QuotaExceededError (429). A 429 is a monthly budget, so it is never retried; branch on the type and handle each.
List endpoints accept whitelisted filter parameters. This example resolves the current season from the API (so it survives the annual rollover) and uses it to filter games.
Every table with a single-column primary key exposes a get(id) that returns exactly one row. Here we list one team to get a real id, then fetch it.
Every stat-api client reads its key from the STAT_API_KEY environment variable, so a first program is just: construct the client, call a list endpoint, and look at the rows.
Kalshi events point at the underlying game through a polymorphic (league_code, competition_id) pair — competition_id is the game's id. Resolve a game with the DSL, then use the code escape hatch to find its Kalshi event and list that event's markets.
Every table exposes an auto-paging iterator that follows the next_from_id keyset cursor until it runs out — so you can consume a whole table without writing the paging loop.
Pagination is keyset, not offset. Each list response returns next_from_id — the cursor for the following page — and null on the last page. This is the loop the auto-paging iterator runs for you, written out by hand.
A game log is one player's per-game stat lines with the game context joined back in. Resolve the season, index its games by id, borrow a player from one game's box score, then page that player's stats and join each row to its game.
Every response is metered and stamped with X-Quota-Limit / X-Quota-Used / X-Quota-Remaining. The SDK parses them into a Quota on every list page, so you can watch your monthly budget without a second request.
A rolling average smooths a per-game stat over a trailing window. Fetch a player's game log with the ops, sort it oldest-first, then compute a 5-game trailing average of points — the windowed math the DSL leaves to the escape hatch.
season_player_stats holds one row per player per season. Resolve the current season, page through all of it with the auto-pager, then sort client-side to build any leaderboard.
season_team_stats has one row per team per season — wins, losses, games played. Resolve the current season, page the whole table, and sort by wins to build the standings.
MLB
A box score is one game plus the per-player stat lines for both teams. Find a game in the current season, fetch its player stats, and group them by team.
List endpoints accept whitelisted filter parameters. This example resolves the current season from the API (so it survives the annual rollover) and uses it to filter games.
Every stat-api client reads its key from the STAT_API_KEY environment variable, so a first program is just: construct the client, call a list endpoint, and look at the rows.
Every table exposes an auto-paging iterator that follows the next_from_id keyset cursor until it runs out — so you can consume a whole table without writing the paging loop.
Grab a team to borrow its id, then list players filtered by team_id — the players endpoint accepts team_id as a filter for both MLB rosters.
season_player_stats holds one row per player per season. Resolve the current season, page through all of it with the auto-pager, then sort client-side to build any leaderboard.
season_team_stats has one row per team per season — wins, losses, games played. Resolve the current season, page the whole table, and sort by wins to build the standings.
NHL
A box score is one game plus the per-player stat lines for both teams. Find a game in the current season, fetch its player stats, and group them by team.
List endpoints accept whitelisted filter parameters. This example resolves the current season from the API (so it survives the annual rollover) and uses it to filter games.
Every stat-api client reads its key from the STAT_API_KEY environment variable, so a first program is just: construct the client, call a list endpoint, and look at the rows.
Every table exposes an auto-paging iterator that follows the next_from_id keyset cursor until it runs out — so you can consume a whole table without writing the paging loop.
season_player_stats holds one row per player per season. Resolve the current season, page through all of it with the auto-pager, then sort client-side to build any leaderboard.
PGA
The leaderboards table has one row per player per tournament: rank, total score, earnings, and strokes-gained splits. Pick a golfer and read their finishes.
A scorecard is a round broken into holes. Pick a golfer, index them by id for name lookups, then pull the holes and render score-to-par per hole.
DFS
A few endpoints require a filter SET, not just any single filter. dfs.slates accepts only operator_id and date TOGETHER. Call it bare and the server returns a 400 ValidationError naming the accepted sets; supply both and it succeeds.
A slate lists every playable player with a salary; projections estimate their points. Page a slate's players by slate_id, rank by salary, then join the top player's projection to compute a value ratio. Use the required-filter-sets recipe to obtain a slate id (91396 is a placeholder here).
General
Betting and prediction-market rows reference an underlying event through a polymorphic (league_code, competition_id) pair. competition_id points at a team sport's games.id (or golf.tournaments.id). Here's how to connect a Kalshi market to the NBA game it settles on.
Every endpoint is a GET under https://api.stat-api.com/api/v1/{league}/{table}. Authentication is a single API key sent as a Bearer token. You can explore with the shared trial key right away, then swap in your own key for unrestricted access.
Per-endpoint recipes
Every endpoint in the API reference ships runnable curl / JavaScript / TypeScript / Python snippets you can execute against the trial key in the browser. Jump straight to a league: