Composite Calls
Fetch a whole screen in one request. A team page, a player card, a match preview or a list of 30 fighters used to take 4 to 30 calls; each of these is one. Available on CS2, UFC and tennis, on every plan.
Four shapes
| Shape | Example | Returns | Counts as |
|---|---|---|---|
| include= | GET /cs2/teams/furia?include=roster,form,maps | The entity, plus each section under included | 1 request |
| Batch ids= | GET /cs2/teams?ids=furia,vitality,spirit | Up to 50 entities in data | 1 request per entity returned |
| Preview | GET /cs2/matches/{id}/preview | Everything a match screen shows | 1 request |
| Resolve | GET /cs2/resolve?q=s1mple | The best id for a name, or candidates | 1 request |
Paths are relative to https://api.citoapi.com/api/v1. Your key goes in the x-api-key header as usual.
Add sections with include=
Add include= with a comma-separated list of sections to any entity below. The response is the entity exactly as it is today, plus an included object with one key per section. It counts as one request, whatever the number of sections.
curl "https://api.citoapi.com/api/v1/cs2/teams/furia?include=roster,form,maps" \
-H "x-api-key: $CITO_API_KEY"{
"success": true,
"data": { "id": "cs2-team-8297", "name": "FURIA", ... },
"meta": {
"composite": { "kind": "include", "included": ["roster", "form", "maps"], "billedRequests": 1 }
},
"included": {
"roster": [ ... ],
"form": { ... },
"maps": [ ... ]
}
}| Game | Entity | Sections |
|---|---|---|
| CS2 | /cs2/teams/{id} | roster, form, maps, map-pool, map-stats, stats, upcoming, results, matches, trends, transfers, roster-history |
| CS2 | /cs2/players/{id} | stats, form, maps, matches, career, teams, trends, seasons, clutches, transfers, tournaments |
| CS2 | /cs2/matches/{id} | maps, player-stats, lineup-stats, head-to-head, odds, streams, demos, games |
| CS2 | /cs2/events/{id}also /cs2/tournaments/{id} | matches, standings, teams, results, stats, bracket |
| UFC | /ufc/fighters/{slug}also /ufc/athletes/{slug} | stats, history, fights |
| UFC | /ufc/events/{slug}also /ufc/fight-cards/{slug} | bouts, odds, stats, results |
| UFC | /ufc/bouts/{id}also /ufc/fights/{id} | stats, rounds, odds |
| Tennis | /tennis/players/{id} | stats, form, matches, rankings |
| Tennis | /tennis/matches/{id} | stats, timeline, status |
| Tennis | /tennis/tournaments/{id} | draw, bracket, schedule, edition |
Each section is the same data as calling that sub-path on its own (include=form on a team is /cs2/teams/furia/form). Up to 12 sections per call. Values an endpoint already understands, such as include=demo on a CS2 match, keep working as before.
Fetch up to 50 at once with ids=
Pass ids= to the list path of the same entities: ids, slugs and names all work, comma-separated, up to 50. Combine it with include= to get every entity with its sections.
curl "https://api.citoapi.com/api/v1/ufc/fighters?ids=jon-jones,tom-aspinall,alex-pereira&include=stats" \
-H "x-api-key: $CITO_API_KEY"{
"success": true,
"data": [ { "slug": "jon-jones", ..., "included": { "stats": { ... } } }, ... ],
"meta": {
"composite": {
"kind": "batch",
"requested": 3,
"returned": 2,
"errors": [ { "id": "tom-aspinal", "status": 404, "code": "NOT_FOUND", "message": "..." } ],
"billedRequests": 2
}
}
}A batch counts one request per entity it returns: ids that are not found cost nothing. A batch never spends past what is left of your month; ids it could not fetch for that reason are listed in meta.composite.errors with MONTHLY_LIMIT_REACHED.
Match and bout previews
Everything a match screen shows, in one request that counts as one.
| Path | data contains |
|---|---|
/cs2/matches/{id}/preview | match, headToHead, lineups, odds, team1 { id, name, form, mapStats }, team2 { ... } |
/ufc/bouts/{id}/preview | bout, odds, boutStats, red { fighterSlug, profile, stats, history }, blue { ... } |
/tennis/matches/{id}/preview | match, matchStats, odds, headToHead, player1 { id, form, stats }, player2 { ... } |
Turn a name into an id with resolve
GET /{game}/resolve?q= returns the one id every other endpoint takes. Add type= (team, player, event, fighter) to narrow it. When a name is ambiguous, best is null, needsDisambiguation is true and candidates lists the options instead of guessing.
{
"success": true,
"data": {
"query": "s1mple",
"best": { "type": "player", "id": "cs2-player-7998", "name": "s1mple", "path": "/api/v1/cs2/players/cs2-player-7998" },
"needsDisambiguation": false,
"candidates": [ ... ]
}
}You often do not need it: names and slugs work directly in paths, such as /cs2/teams/furia or /cs2/players/niko.
How your plan applies
Best Practices
Every section follows your plan
null, with its error and upgrade link in meta.composite.errors; the rest of the response is unaffected. History windows and live delays apply to sections the same way.One per-minute hit per call
Limits
RapidAPI keys
include= is ignored there, so the entity comes back on its own.Paging any list
Every list takes limit plus either page (1-indexed) or offset (rows to skip). offset wins when you send both. On tennis lists an offset must be a multiple of the limit; the error tells you which page to ask for instead.
GET /cs2/players/donk/maps?limit=50&page=2 # rows 51-100
GET /cs2/players/donk/maps?limit=50&offset=50 # the same rowsExamples
const res = await fetch(
"https://api.citoapi.com/api/v1/cs2/teams?ids=furia,vitality,spirit&include=roster,form",
{ headers: { "x-api-key": process.env.CITO_API_KEY! } },
);
const { data, meta } = await res.json();
for (const team of data) console.log(team.name, team.included.form);
for (const miss of meta.composite.errors ?? []) console.warn("not found:", miss.id);import os, requests
r = requests.get(
"https://api.citoapi.com/api/v1/ufc/bouts/13002/preview",
headers={"x-api-key": os.environ["CITO_API_KEY"]},
)
p = r.json()["data"]
print(p["red"]["profile"]["name"], "vs", p["blue"]["profile"]["name"])Get a key
Composite calls work on every plan, including Free.