Core concepts

Match lifecycle

What populates when, from scheduled through live to completed.

A match moves through three states, and which fields are trustworthy depends on where it is.

The states

statusMeaningScoreswinner_team_id
scheduledNot startednullnull
liveIn progressPartialnull
completedFinishedFinalSet, once the result is ingested

scheduled_at is the planned start. There is no separate actual-start field, so a match that started late still shows its scheduled time. Treat it as the fixture's slot, not as evidence of when play began.

What appears when

Fixtures are created ahead of time with teams, tournament and format. Odds start being captured as soon as a market opens — often days before. Everything else lands as the match plays out or shortly after:

  • Map results appear per map as each finishes.
  • Round stats and player stats arrive with the map they belong to.
  • Vetoes are known before play starts, since the pick/ban happens first.
  • Depth (weapons, grenades, hitgroups, duels, flashes) is the last and least universal layer.

A completed match therefore does not guarantee every sub-resource exists.

Don't guess — read data_available

Every match row carries flags for exactly which sub-resources have data:

"data_available": { "maps": true, "stats": true, "vetoes": true, "rounds": true, "depth": false }

Use them instead of speculatively fetching five endpoints and discarding empty responses. Each avoided request is one you keep in your monthly quota.

You can also filter the list to matches that have what you need:

# Only completed matches with round-level AND per-player depth data
curl -H "Authorization: Bearer $ESPORTSODDS_API_KEY" \
  "https://api.esportsodds.gg/v1/cs2/matches?status=completed&has=rounds,depth&limit=20"

has= accepts any comma-separated subset of maps,stats,vetoes,rounds,depth, AND-ed together. An unknown value is a 400 rather than a silently ignored filter.

Settled odds

Once a match settles, its odds lines gain is_winner (which outcome came in) and one line per outcome is flagged is_closing — the last price captured before scheduled_at. The closing line is the standard benchmark for evaluating a forecast, so if you are scoring predictions, that's the row you want. See odds movement.

How fast it changes

Measured over a recent 7-day window, the whole fixture corpus takes about 6 writes an hour — matches simply don't change often. Odds move roughly 110× faster. Polling both on the same timer is the single most common way to burn a monthly quota; the arithmetic is in how often to poll.

On this page