Round stats
Two rows per round, the signed economy tier, and what each counter measures.
GET /v1/{game}/matches/{id}/rounds returns two rows per round — one per team. Exactly one has
won: true.
Join to a map with (match_id, map_number); rounds are numbered from 1 within a map and overtime
keeps counting up, so round 25+ on a standard map is overtime rather than a restart.
economy_level is a signed tier, not a sentinel
economy_level can be negative, and a negative value is meaningful. It is a signed
classification of the buy — eco and force-buy rounds sit below zero. It is not a missing-data
sentinel, and filtering out negatives silently discards every eco round, which is usually the
exact population an economy analysis is about.
Read it alongside equipment_value, enemy_equipment_value and money_spent — the raw dollar
figures, with the opponent's value denormalised onto the same row so you can judge the buy matchup
without a join.
Sides
team_side is lowercase ct or t. Sides swap at the half, so a team's side changes partway
through a map — never assume a team's side from the map alone.
pistol_round flags round 1 and the second-half opener.
Counters
All integers, never null:
| Field | Meaning |
|---|---|
kills / deaths / assists | Team totals for the round. deaths is 0–5. |
damage, headshots | Damage dealt; how many kills were headshots. |
first_kills / first_deaths | Opening duel. Across a round's two rows these sum to 0 or 1. |
trade_kills / trade_deaths | Trade discipline — a kill that avenged a teammate who just died, and a death that was subsequently traded. |
clutches / clutch_attempts | Won, and reached. Divide for a conversion rate — guard the zero denominator. |
bomb_plants / bomb_defuses | 0 or 1. Plants are always 0 on the CT side, defuses always 0 on the T side. |
flash_assists, utility_value | Kills enabled by blinding; dollar value of grenades used. |
kast | A count of 0–5 players who contributed — not a percentage. |
Rebuilding a scoreline
rounds = get(f"/v1/cs2/matches/{match_id}/rounds")["data"]
from collections import Counter
score = Counter(r["team_id"] for r in rounds if r["won"] and r["map_number"] == 1)That should reconcile with map 1's score_a/score_b from
map results. If it doesn't, you're probably summing across maps.