The sports betting
data API
Live odds from 35+ sportsbooks and DFS apps in one flat schema, with the players, teams, box scores, and price history to build models on.
Quickstart
Three steps from zero to live data.
X-Api-Key header. The API is plain REST and JSON, so it works from any language.curl "https://api.sportwizzard.com/api/v1/events?league=mlb" \
-H "X-Api-Key: sw_live_your_api_key_here"data. To page, pass nextCursor back as ?cursor=. When it's null, you're on the last page.{
"success": true,
"data": [ /* … */ ],
"nextCursor": "opaque-cursor-string-or-null",
"meta": { "count": 50, "updated": "2026-07-09T16:41:27Z" }
}Cache with ETags
Live-odds responses include an ETag header. Send it back as If-None-Match to get a free 304 when nothing changed. To stay in sync, poll /api/v1/odds/updated?since={timestamp} for the rows that changed.
What you can fetch
Eight resource groups cover the platform. Edges and arbitrage are computed from the same odds you can pull yourself.
Events
Games and matches. Filter by league, team, or time. Fetch one event for scores, venue, weather, lineups, and probable pitchers.
/v1/events/v1/events/{id}/v1/events/{id}/stats/v1/events/{id}/odds/v1/events/activeOdds
One flat feed across every book. Scope it by league, sportsbook, market, event, player, or team — or by scope=season for season-long futures. The delta feed returns only the rows that changed.
/v1/odds/v1/odds?scope=season/v1/odds/updated/v1/players/{id}/odds/v1/teams/{id}/oddsStats
Box scores for players and teams, keyed to canonical IDs.
/v1/players/{id}/stats/v1/teams/{id}/stats/v1/stats/playersSnapshot
The whole live board in one gzip request. Add include_history=true to include each selection’s price history.
/v1/snapshot/v1/snapshot?include_history=trueReference
Free catalog data: leagues, seasons, sportsbooks, teams, players, and market types. Leagues rotate with the calendar, so call /leagues first.
/v1/leagues/v1/seasons/v1/sportsbooks/v1/teams/v1/players/v1/markets/v1/statusHistorical
Odds as they stood at a past moment, plus settled arbitrage. 5 credits per event.
/v1/historical/odds/v1/historical/arbitrageEdges & arbitrage
Computed signals: soft DFS lines against no-vig book prices, and cross-book arbitrage. Verify a signal before you act on it.
/v1/edges/v1/arbitrageAccount
Your plan, rate limit, and usage for the month.
/v1/account/usageHow odds are shaped
Three ideas explain the whole API.
Events are the spine
Everything keys off an event: one game or match. Odds, box scores, and context all carry an eventId. List events, take an id, then pull that event's board with /v1/events/{id}/odds.
Odds are one flat table
Each row is one price at one book. A row repeats everything you need to interpret it, so you can filter, join, or load rows into a dataframe without walking a tree. The id is a stable composite key ({eventId}:{book}:{subtype}:{selectionId}) that survives price moves. Upsert on it.
{
"id": "31cd6744-…-c4a7d1fce547:ballybet:SPREAD:019f495d-8558-7324-…",
"sportsbook": "ballybet",
"league": "mlb",
"eventId": "31cd6744-9444-4fbd-b25c-c4a7d1fce547",
"market": "SPREAD",
"marketSubtype": "SPREAD",
"period": "FULL",
"selection": "KC Royals",
"side": "AWAY",
"teamSide": "AWAY",
"teamName": "KC Royals",
"line": -1.5,
"priceAmerican": 200,
"priceDecimal": 3.00,
"suspended": false,
"eventStartTime": "2026-07-10T23:05",
"updated": "2026-07-10T14:53:35Z"
}Field glossary
| Field | Meaning |
|---|---|
market | The market family: MONEYLINE, SPREAD, TOTAL, TEAM_TOTAL, PLAYER_TOTAL, PLAYER_MILESTONE, MONEYLINE_3_WAY, and more. |
marketSubtype | The specific stat or variant, such as TOTAL_RUNS or PLAYER_TOTAL_SHOTS. Equals market for simple markets. |
period | The window the wager settles over. FULL is the whole game. Sport-specific partials appear, such as baseball 1INN and 1INN_5INN. On a future it is the window within the season: REG_SEASON or FULL (through the playoffs). |
marketScope | Which anchor the market hangs off: SEASON or TOURNAMENT. Absent on game markets — a row with no marketScope is an ordinary single-game line. See futures. |
segment | Which slice of the competition a future is scoped to: AFC_EAST, NFC, AL, SEC. Present only on segment-scoped markets. Without it, all 32 division-winner selections read as one race. |
selection / side | The human label of the pick, and its normalized side: HOME, AWAY, DRAW, OVER, or UNDER. Filter on side. |
teamSide / teamName | Which side of the event the selection belongs to. For a player prop, the player's team. |
line | The handicap or total the price is quoted against. Absent on pure moneylines. |
priceAmerican / priceDecimal | The same price in both notations. DFS pick'em rows carry dfsMultiplier instead. |
playerId / playerName | Present only on player props: the canonical player the line is about. |
suspended | true while the book has the line locked. |
eventStartTime / updated | The scheduled start, and when this line last refreshed (UTC). The delta feed compares since= against updated. On a future, eventStartTime is the season anchor's settlement date — identical for every book on that anchor, and never a kickoff. See futures. |
Choose a read pattern
/v1/odds/v1/odds/updated?since=/v1/snapshot/v1/snapshot?include_history=true/v1/historical/oddsA typical pipeline: snapshot to bootstrap, then /odds/updated to stay in sync, /odds for targeted reads, include_history=true for line movement, and /historical/odds to replay the past.
Price history in the snapshot
Add ?include_history=true to /v1/snapshot and each selection's priceHistory is populated with its movement entries: fs/ls are first-seen and last-seen epoch seconds, pa/pd the American and decimal price, dm the DFS multiplier, and su: true marks a suspended span. Entries append on every price change, up to 50 per selection. The schema is identical either way: without the flag, priceHistory is null, so the same client code reads both. 1 credit without, 5 with. The two variants carry different ETags.
# board only (1 credit) # board + line movement (5 credits), same schema
curl --compressed "https://api.sportwizzard.com/api/v1/snapshot" \
-H "X-Api-Key: sw_live_…" # …/api/v1/snapshot?include_history=trueScope /v1/odds
Unscoped, /v1/odds spans every league and book. Always scope it, or use /v1/events/{id}/odds, /v1/players/{id}/odds, or /v1/teams/{id}/odds.
| Parameter | What it does |
|---|---|
| scope | Which kind of market: event (a single game), season (season-long futures), or tournament (tournament outrights). Matching is exact — scope=season excludes TOURNAMENT. Omit it and you get all three, as before. Only /v1/odds takes this; any other value returns 400 naming the valid ones. |
| league, sportsbook, market | Any-of filters. Up to 20 comma-separated values each, such as sportsbook=draftkings,fanduel. |
| event_id, player_id, team_id | Entity scoping. Combine freely with the filters above. |
| odds_format | american, decimal, probability, or all. The default returns both price fields. |
| is_main=true | Keep only each market’s primary line per book. Not available on the delta feed. |
| cursor, limit | Opaque cursor pagination. limit sizes the page, up to 1000. |
Futures and season-long markets
A future prices a whole season, not a game. 18 of the books we cover post them, and they arrive on the same flat rows as everything else.
Three fields, three questions
A game line only has to say which team, in which game. A future has to answer three independent questions, so it uses three independent fields. Read them together and any row is unambiguous.
| Field | Question it answers | Values |
|---|---|---|
marketScope | Which anchor does this market hang off? | SEASON (a synthetic season event, not a game) or TOURNAMENT. Absent entirely on game markets, which are unchanged. |
period | Which window inside that anchor does it settle over? | REG_SEASON (division winner, win totals) or FULL (through the playoffs — Super Bowl, World Series). Same field games use for 1H or 1INN. |
segment | Which slice of the competition is it scoped to? | AFC_EAST, NFC, AL, NL, SEC, BIG_12… Present only when the market is segment-scoped. |
The axes are orthogonal: a conference winner is SEASON + FULL + AFC, a division winner is SEASON + REG_SEASON + AFC_EAST, and a season passing-yards total is SEASON + REG_SEASON with no segment at all. Season player props reuse the same PLAYER_TOTAL_* subtypes as game props, so marketScope is the only thing separating a 3,750.5-yard season line from a game line. Check it before you model on it.
Ask for them: ?scope=
/v1/odds takes a scope filter. Matching is exact: scope=season does not include tournament outrights, and vice versa. Omit it and you get every scope, which is the unchanged default. This parameter is on /v1/odds only — the delta feed and the player/team odds endpoints do not accept it today.
# season-long futures only
curl "https://api.sportwizzard.com/api/v1/odds?scope=season&league=nfl&limit=200" \
-H "X-Api-Key: sw_live_…"
# scope=event → game markets scope=tournament → tournament outrights
# omitted → all three (default, unchanged)
# a typo fails loudly instead of looking like "no futures exist"
curl "https://api.sportwizzard.com/api/v1/odds?scope=futures"
# 400 {"detail":"Invalid scope 'futures'. Use scope=event (game markets),
# scope=season (season-long futures), scope=tournament (tournament
# outrights), or omit the parameter for all scopes.",
# "validValues":["event","season","tournament"]}Why segment is load-bearing
Every NFL future for a season hangs off one synthetic season event, so all 32 DIVISION_WINNER selections share a single eventId. Group by eventId + marketSubtype alone and they read as one 32-team race whose implied probabilities sum to about 8. Group by segment as well and you get the eight real four-team markets. Note that segment is a response field, not a query filter — pull the subtype and split on it client-side.
{
"id": "b2e737f7-…-852ce6b8d255:draftkings:DIVISION_WINNER:01a01c2f-a38f-76ec-…",
"sportsbook": "draftkings",
"league": "nfl",
"eventId": "b2e737f7-dfb6-4535-bdc4-852ce6b8d255",
"market": "CATEGORICAL",
"marketSubtype": "DIVISION_WINNER",
"period": "REG_SEASON",
"selection": "BUF Bills",
"priceAmerican": -136,
"priceDecimal": 1.7400,
"side": "YES",
"teamSide": "NONE",
"teamName": "BUF Bills",
"suspended": false,
"eventStartTime": "2027-02-16T23:59",
"updated": "2026-08-20T16:44:17Z",
"marketScope": "SEASON",
"segment": "AFC_EAST"
}Winner and award markets are categorical: one side: "YES" selection per competitor and teamSide: "NONE", because most books never post a NO side. Do not expect a two-sided market here.
One season event, every book on it
Futures from different books converge on the same season anchor, so a single eventId carries every book's price for the same outcome. Cross-book comparison on futures is a group-by, not a matching problem — which is the whole reason this data is worth having, since retail books and exchanges disagree most on the long-dated stuff.
curl "https://api.sportwizzard.com/api/v1/odds?scope=season&league=nfl&market=CATEGORICAL&limit=1000" \
-H "X-Api-Key: sw_live_…" \
| jq -r '.data[]
| select(.marketSubtype=="CHAMPIONSHIP_WINNER" and (.teamName|test("Bills")))
| [.sportsbook, .priceAmerican, .eventId, .eventStartTime] | @tsv' | sort
ballybet 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
betonline 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
betparx 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
betrivers-kambi 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
betway 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
draftkings 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
fanduel 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
hardrock 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
novig 953 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
pinnacle 988 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
polymarket 1011 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
prophetx 960 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
rebet 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59
thescore 1000 b2e737f7-dfb6-4535-bdc4-852ce6b8d255 2027-02-16T23:59Fourteen books, one eventId, one anchor date, captured live. The retail books sit on a round +1000 while the exchanges price it themselves. Note the team label differs by book (BUF Bills vs Buffalo Bills) — match on teamId or the canonical /v1/teams catalog, never on the display string.
/v1/edges and /v1/arbitrage by design, not by omission: a 32-way categorical market has no clean two-way no-vig fair value, so fabricating one would only manufacture fake signals. Futures are raw prices for you to model. And eventStartTime is not a kickoff. On a futures row it is the season anchor's own settlement date, normalized server-side: always present, and the same value for every book on that anchor. It tells you when the market resolves, not when anything starts, so do not treat it as a game time. Use updated for freshness.Real responses
Captured from the live API and trimmed. Pick a league, then flip between the event, its odds board, a settled box score, and a computed signal.
{
"success": true,
"data": [
{
"id": "3a4170cb-0064-48b6-933d-4c4a6ce27283",
"homeTeamId": "7d0a7f60-138a-11f1-aba1-de512ebea802",
"homeTeamName": "Miami Marlins",
"awayTeamId": "7d0a8055-138a-11f1-aba1-de512ebea802",
"awayTeamName": "Seattle Mariners",
"startTime": "2026-07-09T22:40Z",
"status": "scheduled",
"league": "mlb",
"hasOdds": true,
"venueId": "b948390b-3a35-4fc3-a00b-08d8b6959ade",
"seasonYear": 2026,
"context": {
"probable_pitchers": {
"home_id": "7ebc2295-138a-11f1-aba1-de512ebea802",
"away_id": "7ebc6aeb-138a-11f1-aba1-de512ebea802"
}
}
}
],
"meta": {
"count": 1,
"updated": "2026-07-09T18:24:55Z"
}
}api.sportwizzard.com · captured 2026-07-09 · trimmed| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /api/v1/events | List events. Filter by league, team, status, or time. | Reference |
| GET | /api/v1/events/active | Events that have live markets right now. | Reference |
| GET | /api/v1/events/{id} | One event with scores, venue, weather, lineups, and probable pitchers. | Reference |
| GET | /api/v1/events/{id}/stats | Full box score: team totals and per-player stats. | API key |
| GET | /api/v1/events/{id}/odds | The full odds board for one event. | API key |
| GET | /api/v1/odds | The normalized odds feed. Scope it with filters, including ?scope=season for futures. | API key |
| GET | /api/v1/odds/updated | Only the rows that changed since a timestamp. | API key |
| GET | /api/v1/players/{id}/odds | Every live line for one player. | API key |
| GET | /api/v1/teams/{id}/odds | Every live line for one team. | API key |
| GET | /api/v1/players/{id}/stats | Player box stats by season. | API key |
| GET | /api/v1/teams/{id}/stats | Team box stats by season. | API key |
| GET | /api/v1/stats/players | Bulk player box stats. Filter by event, team, or player. | API key |
| GET | /api/v1/snapshot | The whole live board as one gzip blob. Add ?include_history=true for price history (5 credits instead of 1). | Growth+ |
| GET | /api/v1/status | Total live markets and sportsbook count. | Reference |
| GET | /api/v1/leagues | Leagues with an in-progress season. Call this first. | Reference |
| GET | /api/v1/seasons | Seasons for a year, across all leagues. | Reference |
| GET | /api/v1/sportsbooks | Sportsbooks and DFS platforms, with market counts. | Reference |
| GET | /api/v1/markets | The market-type catalog. | Reference |
| GET | /api/v1/markets/active | Market types with live markets. | Reference |
| GET | /api/v1/teams | List teams. Filter by league. | Reference |
| GET | /api/v1/teams/{id} | Get one team. | Reference |
| GET | /api/v1/players | List players. Filter by league or team. | Reference |
| GET | /api/v1/players/{id} | Get one player. | Reference |
| GET | /api/v1/historical/odds | Odds as they stood at a past moment. 5 credits per event. | Pro+ |
| GET | /api/v1/historical/arbitrage | Settled arbitrage history. 5 credits per event. | Pro+ |
| GET | /api/v1/edges | DFS edge signals. | API key |
| GET | /api/v1/arbitrage | Two-way and three-way arbitrage signals. | API key |
| GET | /api/v1/account/usage | Your plan, rate limit, and monthly usage. | Reference |
Pricing and limits
1 credit = 1 event served. Bulk pulls are flat. Empty responses, 304s, and reference endpoints are always free.
| Tier | Price | Rate limit | Credits / month | Historical | Snapshot |
|---|---|---|---|---|---|
| Free | $0 | 2 / min | 5,000 | — | — |
| Pro | $25 / mo | 10 / min | 500,000 | ×5 credits | — |
| Growth | $50 / mo | 30 / min | 1,500,000 | ×5 credits | 5-min refresh |
| Enterprise | $100 / mo | 60 / min | Soft-unlimited | ×5 credits | Real-time |
Snapshot pulls are flat: 1 credit, or 5 with include_history=true. Your usage comes back in the X-Credits-Cost and X-Credits-Remaining response headers. Annual billing gets 2 months free. Full details on the pricing page.
MCP server
Wire SportWizzard into Claude, Codex, or any MCP client.
A hosted server runs at mcp.sportwizzard.com with bearer-key auth and no install. An open-source stdio server offers the same 20 tools over npm, including download_snapshot with an include_history option and a mock mode for development.
Working in a coding agent? See the agent quickstart.
claude mcp add --transport http sportwizzard \
https://mcp.sportwizzard.com/mcp \
--header "Authorization: Bearer sw_live_…"{
"mcpServers": {
"sportwizzard": {
"command": "npx",
"args": ["-y", "sportwizzard-mcp"],
"env": { "SPORTWIZZARD_API_KEY": "sw_live_…" }
}
}
}