CS2 data reference

Team records — results, rivals, maps, vetoes, playstyle

The derived team endpoints, the windows they accept, and what each is actually measuring.

These endpoints summarise a team's history. All are derived from completed matches, so a team with little history returns thin results rather than an error.

Windows. The per-map, round and veto endpoints take window — a whole number of months with an m suffix (6m, up to 60m) or all — so you can describe how a team plays now rather than across every roster it has had. Without window the endpoint keeps its original behaviour, the team's whole history. The windows count back from the request time.

Era. era=cs2 keeps only Counter-Strike 2 matches (from the October 2023 release); era=all, the default, keeps everything, including CS:GO matches. A match with no recorded game version counts as CS2 from 2023-10-16 onward.

Recent form

GET /v1/{game}/teams/{id}/form — recent completed results, newest first, from the subject team's perspective. Default 10, max 50; not paginated.

Each row: match_id, opponent_id, won, score_for, score_against, scheduled_at. The scores are maps won, not rounds, and are null where the series score wasn't recorded.

Head-to-head

GET /v1/{game}/teams/{id}/h2h?opponent=<id-or-slug> — opponent is required.

curl -H "Authorization: Bearer $ESPORTSODDS_API_KEY" \
  "https://api.esportsodds.gg/v1/cs2/teams/natus-vincere/h2h?opponent=faze"

Returns team_wins, opponent_wins, total. Only matches with a settled winner are counted, so team_wins + opponent_wins == total exactly — there is no draw bucket.

total is the number to sanity-check first: a 3–1 record over 4 meetings is close to no evidence.

Recent results

GET /v1/{game}/teams/{id}/results — completed, decided matches, newest first: the rows of a results table. Default 20, max 100; not paginated. opponent=<id-or-slug> narrows it to one rivalry.

Each row carries the opponent (id, name, slug), tournament_id, tournament_name, stage, format, won, the series score (score_for, score_against, maps won) and every played map's score from the team's side in maps (map_number, map_name, score_for, score_against).

rating_before and opponent_rating_before are each side's Glicko-2 state (rating, rd) strictly before the match started, so a result never contains its own outcome. A side with no earlier rated match has null there — never a default rating. Walkovers (awarded, not played) and matches with no recorded winner are not listed, and a forfeited or abandoned map is left out of maps.

Rivals

GET /v1/{game}/teams/{id}/rivals — the opponents a team has met most often, most meetings first. A rival is an opponent met at least min_meetings times (default 2, range 1–50) in decided, played matches inside window (default 36m, up to 120m, or all). limit default 5, max 20.

Each row: the opponent, meetings, wins, opponent_wins, last_meeting_at, and results_oldest_first — the last ten meetings as won/lost booleans, oldest to newest.

avg_rating_gap is the opponent's rating minus the team's going into each meeting, averaged over the rated_meetings where both teams had a rating then. It is null when no meeting had both — never zero — and a negative gap means the team was the higher-rated side on average. For the meetings themselves, with scores and both ratings, call /teams/{id}/results?opponent=.

Per-map record

GET /v1/{game}/teams/{id}/maps — one row per map the team has a completed result on: map_name, played, wins.

Raw counts, deliberately — the win rate is wins / played, left for you to compute so the model stays a fact rather than a formatted ratio. Guard small played values: 3–0 on a map is not a 100% map.

Ordered by win rate descending, then by matches played. Only maps played out count: a forfeit, an abandoned map or an awarded walkover is not a performance.

By default the record covers the team's whole history, which makes a retired map's old record read as present form. Narrow it with window, era=cs2 and active=true (only the maps in today's Active Duty pool). include=detail adds, per map, last_played_at, active_pool, and the team's round record by side and in pistol rounds: ct_rounds, ct_round_wins, t_rounds, t_round_wins, pistol_rounds, pistol_round_wins. Those are counts of rounds, not maps, and are null for a map with no round data.

Veto record

GET /v1/{game}/teams/{id}/vetoes — how the team chooses maps. window defaults to 6m (up to 60m, or all); era as above. The response is one object:

Prop

Type

picks and bans count only the team's own choices, so an opponent's habits never read as the team's, and which side of the match the team was on does not matter. first_bans counts the matches where it was the team's first ban; deciders the matches where the map was left over. A choice attributed to a team that is not one of the match's two sides, or on a name that is not a competitive map, is dropped rather than counted.

permaban is true when the team bans the map in at least 90% of at least 20 recorded vetoes — bans / veto_matches. Vetoes are recorded for most matches but not all, so veto_matches is the number to read first. A team with no recorded vetoes still returns its matches, with maps: [].

Playstyle profile

GET /v1/{game}/teams/{id}/round-stats — a single object of percentages aggregated over the team's rounds:

Prop

Type

Every percentage is 0–100, and null when the denominator is empty — a team with no recorded eco rounds has eco_win_pct: null, not 0. window limits it to rounds of matches inside a trailing span (default all, the whole history).

To place a team's rates among its peers without one request per team, GET /v1/{game}/rankings/round-stats returns the same figures for the top board teams in a single call — see ratings and rankings.

An unknown team id returns rounds: 0 with every percentage null — not a 404. If you need to know a team exists, fetch it directly.

Units, one more time

These are the only team fields expressed as 0–100 percentages. Player KAST on a stat line is a 0–1 fraction (a 0–100 percentage on the player figures endpoints) and round KAST is a 0–5 count. When in doubt, check the field's own description in the reference.

On this page