API Reference
StakeAPI delivers real-time Stake.com sports & esports events and odds over a simple REST API plus a Server-Sent Events stream. JSON in, JSON out - no SDK required.
Introduction
The API exposes normalized fixtures (matches) with live and pre-match odds across all major sports and esports - football, tennis, basketball, ice-hockey, baseball, MMA, CS2, Dota 2, League of Legends, Valorant and more. Virtual feeds (eFootball / eSoccer) are excluded.
Base URL
All endpoints are served over HTTPS under the /v1 prefix:
https://bwapi.lol/v1
Authentication
Authenticate every request with your API key in the X-API-Key header. Keys are issued and managed from your dashboard. An active subscription is required.
X-API-Key: your_api_key401. If your subscription has expired you'll get 402 Payment Required.Quickstart
Fetch upcoming and live events in one call:
curl "https://bwapi.lol/v1/events?status=live&limit=5" \ -H "X-API-Key: your_api_key"
Rate limits
Default limit is 1000 requests / minute per key (higher on 6- and 12-month plans). For continuous live data prefer the SSE stream over tight polling.
List sports
Returns enabled disciplines with a live-event counter.
Response
{
"sports": [
{ "key": "counter-strike", "label": "CS2", "category": "esport", "live_count": 3 },
{ "key": "soccer", "label": "Football", "category": "sport", "live_count": 12 }
]
}List events
Returns events with markets and odds. Filter by sport and status.
Query parameters
| Param | Type | Description |
|---|---|---|
| sport | string | Filter by sport key (e.g. soccer, counter-strike). Optional. |
| status | string | all (default), live, prematch or ended. |
| limit | int | Max results, default 200, up to 1000. |
Example
curl "https://bwapi.lol/v1/events?sport=tennis&status=live" \ -H "X-API-Key: your_api_key"
Response
{
"events": [
{
"id": "65c3a461-b9e5-4a68-8082-db97a6bed3bb",
"sport": "tennis",
"league": "Wimbledon Men Singles",
"home": "Alex Molcan",
"away": "Daniel Altmaier",
"start_time": "2026-06-30T16:55:00+00:00",
"status": "live",
"score": { "home": 1, "away": 0, "status": "1ST SET" },
"stream_url": "NTMyNjU2NTcyOzgwZjFjMmE0...",
"match_url": "https://stake.com/sports/tennis/atp/wimbledon-men-singles/46670858-r64p59-r64p60",
"winner": null,
"ended_at": null,
"markets": [
{
"type": "Winner",
"selections": [
{ "name": "Alex Molcan", "line": null, "price": 1.30 },
{ "name": "Daniel Altmaier", "line": null, "price": 3.30 }
]
},
{
"type": "Total Sets",
"selections": [
{ "name": "Over 2.5", "line": null, "price": 2.10 },
{ "name": "Under 2.5", "line": null, "price": 1.72 }
]
}
],
"updated_at": "2026-06-30T22:34:07+00:00"
},
{
"id": "a1f9c2e0-77bd-4e31-9a02-4c6d0f2b8e10",
"sport": "tennis",
"league": "Wimbledon Men Singles",
"home": "Carlos Alcaraz",
"away": "Jannik Sinner",
"start_time": "2026-06-30T14:00:00+00:00",
"status": "ended",
"score": { "home": 2, "away": 1, "status": "ENDED" },
"stream_url": null,
"winner": "home",
"ended_at": "2026-06-30T16:41:22+00:00",
"markets": [],
"updated_at": "2026-06-30T16:41:22+00:00"
}
]
}?status=ended to settle bets: a finished match returns status:"ended" with winner (home / away / draw) and the final score. If winner is null, there is no confirmed result (match interrupted or cancelled) - void the bets. Settled events are retained for 72h.Get event
Fetch a single event by its id. Returns 404 if not found.
curl "https://bwapi.lol/v1/events/65c3a461-b9e5-4a68-8082-db97a6bed3bb" \ -H "X-API-Key: your_api_key"
Live stream (SSE)
A Server-Sent Events stream that pushes a fresh snapshot of live events whenever odds change (checked every ~3s). Optional ?sport= filter.
Browser
const es = new EventSource( "https://bwapi.lol/v1/live/stream?sport=counter-strike" ); es.addEventListener("live", (e) => { const { events } = JSON.parse(e.data); console.log(events); });
?api_key= when consuming the stream from a browser. Server-to-server, use the X-API-Key header.Data model
Event
| Field | Type | Description |
|---|---|---|
| id | string | Stable unique event id (UUID). |
| sport | string | Sport key (e.g. soccer). |
| league | string | Tournament / league name. |
| home | string | Home competitor. |
| away | string | Away competitor. |
| start_time | string | ISO-8601 UTC kickoff time. |
| status | string | prematch, live or ended. |
| score | object|null | { home, away, status } - live or final score. |
| winner | string|null | home, away, draw or null - who won. Set once status is ended. null on an ended match = no confirmed result (interrupted / cancelled) - void the bets. |
| ended_at | string|null | When the match was settled (ISO-8601), else null. |
| stream_url | string|null | Live broadcast reference from Stake (live only), else null. Opaque stream token, not a direct .m3u8. |
| match_url | string|null | Link to the match page on Stake (where the live broadcast plays). Opens on stake.com; requires a Stake login and eligible region. |
| markets | Market[] | All markets for the match (winner, handicaps, totals, map/set winners, correct score, etc.). |
| updated_at | string | Last update timestamp (ISO-8601). |
Market & Selection
| Field | Type | Description |
|---|---|---|
| type | string | Market name, e.g. Winner. |
| selections[].name | string | Outcome label. |
| selections[].line | number|null | Handicap / total line if any. |
| selections[].price | number | Decimal odds. |
Errors
Errors use standard HTTP status codes with a JSON body { "detail": "..." }.
| Status | Meaning |
|---|---|
| 200 | OK |
| 401 | Missing or invalid API key. |
| 402 | Subscription expired - renew in the dashboard. |
| 404 | Event not found. |
| 429 | Rate limit exceeded. |
Need help? Write to support@bwapi.lol.