How the esports API works.
The esports data feed developers build on: one bearer token, a versioned snake_case schema, rate limits you can read off every response, and a WebSocket that pushes updates so you stop polling — with six years of Counter-Strike history behind it.
The CS2 odds line
One clean reference line per match — not a shopping list of prices.
At least two books behind every line, refreshed on our ingest cadence, and appended — never overwritten — so history holds.
"price": 1.72,
"book_count": 4
A predictive line built on the same six years of match history — currently in validation. It ships when it clears our accuracy bar, not before. Until then, it appears nowhere in the API.
"status": "validating"
# not yet served — no early access
Auth, versioning, history & errors
Send Authorization: Bearer <key>. That’s the whole integration story — no SDK, no OAuth dance, no signing. A ?apiKey=query fallback exists for callers that can’t set a header; the header always wins if both are present.
Everything lives under /v1, game-namespaced as /v1/cs2/.... Fields are snake_case, mapping 1:1 onto the underlying columns. A second game adds a namespace; it doesn’t reshape your parser.
22,000+ completed matches back to 2020 — 16,000+ of them CS2-era. Odds history is append-only: a line you read last season is still there this one.
Errors return a plain JSON body — {"error": "..."} — alongside the status code today. A richer coded envelope with a request_idis on the roadmap — that’s a target we’re building toward, not something shipped yet.
Rate limits & monthly quota
A per-key token bucket smooths bursts; a hard monthly quota of 10,000 requests bounds the bill. Every metered response carries remaining tokens, remaining quota, and the exact reset instant — no guessing, no surprise invoices.
Exceed either cap and you get a 429 with a Retry-After header in seconds.
$ curl -i -H "Authorization: Bearer $EO_KEY" \ "api.esportsodds.gg/v1/cs2/matches" HTTP/2 200 X-RateLimit-Limit: 20 X-RateLimit-Remaining: 19 X-Quota-Limit: 10000 X-Quota-Remaining: 9873 X-Quota-Reset: 2026-08-01T00:00:00Z
# 1. mint a short-lived ticket $ curl -X POST "api.esportsodds.gg/v1/cs2/ws-token" # 2. connect and subscribe → {"subscribe": ["match:019f4ba2"]} # 3. updates arrive when our feed changes ← {"type": "odds_update", "price": 1.68, ...}
WebSocket push updates
Mint a short-lived ticket, open the socket, subscribe to the matches you care about. When a score or line changes in our feed, it’s pushed to you instead of you burning quota on polls.
Freshness is bounded by our own ingest cadence — tens of seconds — not a live server connection. This is not real-time or in-play data; it’s the fastest honest version of a polled feed.
CS2 data coverage
Coverage is not uniform, and we’d rather you know that before you build. The gaps cluster in lower-tier events nobody recorded that granularly. We do not synthesize the missing rounds — a gap stays a gap.
Ship your first odds feed today
One plan — $99/mo for 10,000 requests. Production-ready in minutes.