Teams

The opponents a team meets most often

The opponents a team has met most often, most meetings first. A rival is an opponent met at least `min_meetings` times (default 2) in decided, played matches inside the window (default the last 36 months). Each row gives the head-to-head split, the date of the last meeting, the most recent ten meetings oldest to newest as won/lost booleans, and `avg_rating_gap`: the opponent's rating minus the team's going into each meeting, averaged over only the `rated_meetings` where both teams had a rating then. It is `null` when no meeting had both, never zero. A negative gap means the team was the higher-rated side on average. For the meetings themselves, with scores, maps and both ratings, call `/teams/{id}/results?opponent=`. `limit` default 5, maximum 20. Enveloped `{"data": [TeamRival, ...], "meta": {...}}`.

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) in decided, played matches inside the window (default the last 36 months).

Each row gives the head-to-head split, the date of the last meeting, the most recent ten meetings oldest to newest as won/lost booleans, and avg_rating_gap: the opponent's rating minus the team's going into each meeting, averaged over only the rated_meetings where both teams had a rating then. It is null when no meeting had both, never zero. A negative gap means the team was the higher-rated side on average. For the meetings themselves, with scores, maps and both ratings, call /teams/{id}/results?opponent=. limit default 5, maximum 20. Enveloped {"data": [TeamRival, ...], "meta": {...}}.

Authorization

AuthorizationBearer <token>

Primary auth (live). Authorization: Bearer <api-key> — the header takes precedence over the query fallback. The raw key is hashed (SHA-256, hex) and looked up in api.keys.key_hash; the raw value is never stored.

In: header

Path Parameters

game*string

Game slug. cs2 is the only populated title today; an un-onboarded game 404s cleanly.

id*string

Resource identifier — either a UUID or the resource's human-readable slug, scoped to {game}. /v1/cs2/teams/natus-vincere and /v1/cs2/teams/019f23d1-fb5c-7987-b522-47c3a5e72111 address the same row, so you can go straight from a slug you already have without first looking up its id.

Slugs work on teams, players and tournaments. Matches have no slug, so a match id must be a UUID. Either way, an identifier that resolves to nothing returns 404 not_found.

A team or a player also answers to a slug it was renamed away from, as long as no current team or player holds that slug — so a link made before a rename keeps working. The row returned carries its current slug.

Query Parameters

limit?integer

How many rivals to return. Default 5, maximum 20. Not paginated.

Range1 <= value <= 20
Default5
min_meetings?integer

The fewest meetings an opponent needs to count as a rival: a whole number from 1 to 50. Default 2. Anything else is a 400 naming the parameter.

Range1 <= value <= 50
Default2
window?string

The trailing span of matches the figures cover: a whole number of months with an m suffix, such as 6m, up to 120m, or all for the whole history. Default 36m. Anything else is a 400 naming the parameter.

Default"36m"

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/cs2/teams/019f2858-e253-7f3d-bdff-bc7738bd1036/rivals"
{  "data": [    {      "opponent": {        "id": "019f23d1-fb5c-738b-8ca9-2e78eaeb5b42",        "name": "MOUZ",        "slug": "mouz-cs2"      },      "meetings": 19,      "wins": 14,      "opponent_wins": 5,      "last_meeting_at": "2026-09-05T16:45:00Z",      "avg_rating_gap": -96.61298197407216,      "rated_meetings": 19,      "results_oldest_first": [        false,        true,        true,        true,        true,        false,        true,        false,        true,        true      ]    },    {      "opponent": {        "id": "019f23d1-fb5b-7963-9295-da73d11ba912",        "name": "FaZe",        "slug": "faze"      },      "meetings": 16,      "wins": 12,      "opponent_wins": 4,      "last_meeting_at": "2026-08-20T13:25:00Z",      "avg_rating_gap": -108.76017881012469,      "rated_meetings": 16,      "results_oldest_first": [        true,        true,        true,        false,        true,        true,        true,        false,        true,        true      ]    },    {      "opponent": {        "id": "019f23d1-fb5c-782d-be6f-5314d5adc883",        "name": "The MongolZ",        "slug": "the-mongolz"      },      "meetings": 15,      "wins": 13,      "opponent_wins": 2,      "last_meeting_at": "2026-03-21T21:10:00Z",      "avg_rating_gap": -155.23871385509048,      "rated_meetings": 15,      "results_oldest_first": [        true,        true,        true,        true,        false,        false,        true,        true,        true,        true      ]    }  ],  "meta": {    "count": 3,    "next_cursor": null  }}
{  "error": {    "code": "not_found",    "message": "not found",    "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578"  }}
{  "error": {    "code": "not_found",    "message": "not found",    "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578"  }}
{  "error": {    "code": "not_found",    "message": "not found",    "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578"  }}

{  "error": {    "code": "rate_limited",    "message": "rate limit exceeded",    "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578"  }}

A team's recent results GET

A team's completed, decided matches, newest first — the rows of a results table. Each carries the opponent, the tournament and stage, the series score, every played map's score from the team's side, and both teams' ratings going into the match. `rating_before` and `opponent_rating_before` are the latest Glicko-2 state 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 are awarded rather than played, so they are not listed, and neither is a match with no recorded winner; a forfeited or abandoned map is left out of `maps`. `opponent` (a team id or slug) narrows the list to one rivalry. `limit` default 20, maximum 100. Enveloped `{"data": [TeamResult, ...], "meta": {...}}` (not cursor-paginated).

A team's roster timeline (the five it actually fielded) GET

The five players a team actually fielded in each recent completed match, newest first, with the derived roster-change facts. `limit` default 20, max 100. Enveloped `{"data": [TeamRosterEntry, ...], "meta": {...}}` (not cursor-paginated). Read `continuity` BEFORE interpreting `changed_count`: `stable` (same five as last match), `changed` (1–4 players swapped — the only value for which `has_debutant` is asserted), `reset` (all five swapped, i.e. an organisation rename or full rebuild, NOT five stand-ins), `resumed` (previous match beyond a 60-day gap — a transfer window, not a stand-in), and `new` (no prior match, so `players_in`/`players_out` are empty because there is no baseline to diff against). A match where a team used more than five players across maps is omitted rather than guessed at.