The data model
How games, tournaments, matches, maps, rounds and players relate — and which endpoint returns each.
Everything in the API hangs off six entities. Knowing which one owns a fact tells you which endpoint to call.
Game (cs2)
└─ Tournament /v1/cs2/tournaments
└─ Match /v1/cs2/matches
├─ Map result /v1/cs2/matches/{id}/maps
│ └─ Round /v1/cs2/matches/{id}/rounds
├─ Veto step /v1/cs2/matches/{id}/vetoes
├─ Player stats /v1/cs2/matches/{id}/stats
└─ Depth /v1/cs2/matches/{id}/depth
Team /v1/cs2/teams
Player /v1/cs2/playersThe entities
Game is the namespace segment in every path. cs2 is the only populated title today, but the
shape is game-agnostic by construction — a second title extends the same paths rather than replacing
them. A game that isn't onboarded returns 404 unknown_game.
Tournament is an event. It has dates, a tier, a prize pool and a region; its status
(upcoming/ongoing/finished) is derived from its dates, not stored, so a tournament with no
known start date has a null status and is excluded by any status filter.
Match is one fixture between two teams. format (bo1/bo3/bo5) tells you how many maps to
expect at most. The two sides are team_a and team_b — stable slots, not home/away; CS2 has no
home side.
Map result is one map within a series, numbered from 1. Rounds are per-team rows within a map — two per round, one for each side.
Team and Player are the competitors. A player's team_id is their current team; the team
they played for in a specific match is on that match's stat line, which is not always the same.
Which id joins to which
Everything is a UUIDv7. The joins that matter:
- A match carries
team_a_id,team_b_id,tournament_id. - A map result, veto, stat line, round and depth row all carry
match_id. - A stat line and a round both carry
map_number, so they join to a map result on(match_id, map_number). - A stat line's
map_numberisnullfor the whole-match aggregate. Filter fornullto avoid double-counting a player across per-map and aggregate rows.
List rows vs detail rows
A list row is denormalised for display: a match from /v1/cs2/matches carries team_a_name,
team_b_name, team_a_short, team_b_short and tournament_name alongside the ids.
A detail row is not: /v1/cs2/matches/{id} returns bare ids. Ask for the related resources with
?include=teams,tournament rather than making three more requests. This catches people who
prototype against the list then switch to detail — see
fetching a full match.
What isn't exposed
Markets and market types are modelled internally but have no endpoint of their own — you get a
market_id on each odds line, which groups lines belonging to the same proposition. Per-book
bookmaker prices are never served in any form; see the market line.