DOCS · NO KEY REQUIRED TO READ

Read the docs. Then ship.

Every endpoint has a worked example. Every example runs. Pick a guide below or jump straight to the API reference.

Start the walkthrough Open API reference Get an API key
GET /v1/tournaments GET /v1/matches GET /v1/matches/:id GET /v1/teams/:slug

Guides

01 · QUICKSTART

Make your first call

Sign up, mint a key, curl /v1/matches?status=live. 30 seconds end-to-end.

Open guide
02 · REFERENCE

Interactive API reference

Every endpoint. Every response. Every error envelope. ReDoc-rendered, always in sync with the live spec.

Open guide
03 · GAMES

League of Legends

LoL endpoints, schema, Riot partnership notes, live state cadence.

Open guide
04 · GAMES

Counter-Strike 2

CS2 fixtures, tournaments and brackets. No demo parsing in v1 (ADR-0010).

Open guide
05 · BILLING

Tiers & quotas

How daily quotas + RPS bursts work, what the headers expose, and how to upgrade.

Open guide
06 · DX

Sandbox

esp_test_ keys, fixture data, zero quota burn. Evaluate before paying.

Open guide
07 · DX

Webhooks

Pro-tier outbound events. HMAC signature verification recipe for Python + TypeScript.

Open guide

Authentication

Mint a key at /dashboard. Pass it as a bearer token on every request:

Authorization: Bearer $STADAR_API_KEY

Two key shapes:

Both shapes use the same header. Server-side prefix detection routes the request. See /docs/sandbox for the full sandbox model.

GitHub OAuth signups get a session cookie automatically; the first call to POST /v1/account/keys mints your first live key.

Pagination

Cursor-based. Always. We never expose offset or page numbers because they break silently when entities mutate underneath you.

GET /v1/matches?limit=100&cursor=...

# Response
{
  "data": [...],
  "meta": {
    "next_cursor": "eyJpZCI6MTIz...",   // null when exhausted
    "limit": 100,
    "sources": [...]
  }
}

Walk by passing meta.next_cursor back as ?cursor= on the next call. Treat the cursor as opaque — we may change its encoding.

Errors

Every error response uses one envelope:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Daily quota exhausted. Upgrade at https://stadar.net/pricing.",
    "request_id": "req_01HMXY7N...",
    "details": { "quota_reset_at": "2026-05-17T00:00:00Z" }
  }
}

Common codes:

Always log request_id if you’re going to ask support about a 5xx.

Rate limits

Two budgets per key: a daily quota and a per-second burst (RPS). Both enforced in Redis with sliding windows. Headers on every response expose the live state:

When you hit a limit you get 429 Too Many Requests plus the standard Retry-After header in seconds. The SDKs do not auto-retry on 429 — that’s intentional. You see the limit; you decide what to do.

Capabilities

Some endpoints (match stats, brackets, bulk export) gate per tier. The middleware checks your tier on every request and returns 402 Payment Required if your tier doesn’t permit it, with a Polar checkout link in the body:

{
  "error": {
    "code": "tier_required",
    "message": "match_stats requires Hobbyist+",
    "details": {
      "required_capability": "match_stats",
      "your_tier": "free",
      "upgrade_url": "https://stadar.net/checkout?capability=match_stats"
    }
  }
}

Introspect your effective capabilities at GET /v1/account/me/capabilities. The SDKs expose this as client.account.capabilities(). Helpful when “why am I getting a 402?” is unclear.

Capabilities defined in v1:

Webhooks (Pro+)

Subscribe to outbound events at /v1/account/webhooks. We POST to your URL with an HMAC-SHA256 signature in X-Stadar-Signature. Verify before trusting the body.

Event types in v1:

See /docs/webhooks for the full signature-verification recipe in both Python and TypeScript. Failures retry on an exponential schedule (1s · 5s · 30s · 5m · 30m · 6h) then archive to a dead-letter table visible in the admin panel.

Sandbox

Mint a sandbox key at POST /v1/account/keys?mode=sandbox. Same shape as a live key but prefixed esp_test_. Hits the fixture schema (~50 matches across all 6 games, mix of scheduled/live/completed). Doesn’t burn production quota; gets meta.sandbox: true on every response. Lets you wire your integration end-to-end without paying.

See /docs/sandbox for the full model — what’s covered, what’s not, how often we refresh.

Attribution (CC-BY-SA)

Every successful response includes a meta.sources array listing the upstream data sources whose terms require attribution. Liquipedia is licensed CC-BY-SA 3.0; we satisfy attribution for you on the wire. Do not strip meta.sources from your own responses if you re-expose Stadar data. See ADR-0004 in the monorepo for the licensing posture.