Odds Snapshot
Get a snapshot of current odds from sportsbooks.
GET /api/v1/oddsChanged in v3.0.0: the odds response now carries a single timestamp field (delivery / feed-freshness, matching OpticOdds). The former odds_changed_at, last_seen_at, and wire_received_at fields have been removed — read timestamp instead. There is no longer a field for when the price last moved.
Authentication
Requires API key. Available to all tiers.
The sportsbooks returned in your results depend on your subscription tier. Free tier users receive odds from DraftKings and FanDuel only. See Book Access by Tier below.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
sportsbook | string | tier-allowed | Comma-separated sportsbook IDs (e.g., draftkings,fanduel). Tier limits enforced. |
sport | string | all | Filter by sport(s), comma-separated (e.g., basketball, football). Supports category aliases. |
league | string | all | Filter by league(s), comma-separated (e.g., nba, nfl, nhl) |
market | string | all | Filter by market type(s), comma-separated. Supports category aliases (main, spread, total, props) or exact types (point_spread, player_points). |
event | string | — | Filter by event ID(s), comma-separated |
live | boolean | — | true = live only, false = prematch only, omit = both |
sort | string | — | Sort field with optional - prefix for descending (e.g., -odds_american, odds_probability) |
fields | string | all | Comma-separated field names to include in response (e.g., id,sportsbook,odds_american) |
min_odds | number | — | Minimum American odds filter (e.g., -110) |
max_odds | number | — | Maximum American odds filter (e.g., +200) |
group_by | string | — | Group results by field (e.g., event) |
state | string | — | US state code for sportsbook deep links (e.g., nj, ny, il). When set, deep_link URLs include ?state=XX so the redirect targets the correct state-specific sportsbook domain. Only affects books with state-dependent URLs (BetMGM, Caesars, BetRivers). |
limit | integer | 50 | Max results per page (max 200) |
offset | integer | 0 | Pagination offset. Must be ≤ 500. Values above 500 return 400 offset_too_large — use cursor for deeper pagination. May produce duplicate rows when live data updates between requests. |
cursor | string | — | Opaque cursor from next_cursor in a previous response. Required for deep pagination (past offset 500) and recommended for any multi-page scan — stable against live data changes. Takes precedence over offset when both are provided. |
Use comma-separated values to filter by multiple sportsbooks: sportsbook=draftkings,fanduel,betmgm
Market Category Aliases
Instead of listing individual market types, you can use a category alias to match a group of related markets. Aliases and exact types can be mixed freely in a comma-separated list.
| Alias | Expands to |
|---|---|
main | moneyline, point_spread, total_points |
spread | point_spread, puck_line, run_line, set_handicap |
total | total_points, total_goals, total_runs, total_games, total_rounds, team_total |
props | All player_* market types (prefix match) |
# Fetch all "main" markets (moneyline + spreads + totals)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&market=main" \
-H "X-API-Key: YOUR_API_KEY"
# Mix an alias with an exact type
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&market=spread,moneyline" \
-H "X-API-Key: YOUR_API_KEY"
# All player prop markets
curl "https://api.sharpapi.io/api/v1/odds?league=nba&market=props" \
-H "X-API-Key: YOUR_API_KEY"The props alias uses a prefix match, so it automatically includes any market type starting with player_ (e.g., player_points, player_rebounds, player_assists, player_strikeouts, etc.).
Example Requests
cURL
curl -X GET "https://api.sharpapi.io/api/v1/odds?league=nba&sportsbook=draftkings&market=moneyline" \
-H "X-API-Key: YOUR_API_KEY"Pagination
Use cursor-based pagination for multi-page scans. The /odds endpoint serves live data that refreshes every ~15 seconds. With offset-based pagination, rows can shift positions between requests, causing duplicates at page boundaries. Cursor-based pagination anchors each page to the last seen item — no drift.
Each response includes both next_cursor (stable) and next_offset (legacy) in the pagination object. For sequential full-dataset scans, always use next_cursor.
# First page — no cursor needed
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&limit=200" \
-H "X-API-Key: YOUR_API_KEY"
# Subsequent pages — pass next_cursor from the previous response
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&limit=200&cursor=eyJlIjoiMzM0ODMxNTMiLCJiIjoiZHJhZnRraW5ncyIsIm0iOiJtb25leWxpbmUiLCJpIjoiZHJhZnRraW5nc18zMzQ4MzE1M19tb25leWxpbmVfUEhJIn0" \
-H "X-API-Key: YOUR_API_KEY"Cursors are opaque — do not parse or construct them. They encode the sort position of the last item on the current page and are only valid for the same filter parameters.
?offset=N continues to work for shallow pagination (up to offset 500) and is appropriate for single-page requests or direct position access. Beyond 500, the API returns 400 offset_too_large — the server would otherwise have to sort the full filtered result set on every page, which is much cheaper to avoid than to optimize per-request. Use cursor for anything deeper.
{
"error": {
"code": "offset_too_large",
"message": "offset must be <= 500; use `cursor=` from the previous response for deeper pagination",
"max_offset": 500
}
}Response
Success (200)
The example below shows the flat fields only. As of May 2026, every row also carries optional nested reference blocks (home, away, sport_ref, league_ref, market_ref, sportsbook_ref) — see Nested reference blocks below.
{
"success": true,
"data": [
{
"id": "draftkings_33483153_moneyline_PHO",
"sportsbook": "draftkings",
"event_id": "33483153",
"sport": "basketball",
"league": "nba",
"home_team": "PHI 76ers",
"away_team": "PHO Suns",
"market_type": "moneyline",
"selection": "PHO Suns",
"selection_type": "away",
"odds_american": -150,
"odds_decimal": 1.667,
"odds_probability": 0.60,
"line": null,
"is_main_line": true,
"is_alternate_line": false,
"event_start_time": "2026-01-26T19:00:00Z",
"timestamp": "2026-01-26T02:10:24.125Z",
"is_live": false
},
{
"id": "draftkings_33483153_moneyline_PHI",
"sportsbook": "draftkings",
"event_id": "33483153",
"sport": "basketball",
"league": "nba",
"home_team": "PHI 76ers",
"away_team": "PHO Suns",
"market_type": "moneyline",
"selection": "PHI 76ers",
"selection_type": "home",
"odds_american": 130,
"odds_decimal": 2.30,
"odds_probability": 0.4348,
"line": null,
"is_main_line": true,
"is_alternate_line": false,
"event_start_time": "2026-01-26T19:00:00Z",
"timestamp": "2026-01-26T02:10:24.125Z",
"is_live": false
}
],
"meta": {
"count": 2,
"total": 3095,
"books_available": ["draftkings", "fanduel", "betmgm", "caesars", "pinnacle"],
"books_returned": ["draftkings"],
"pagination": {
"limit": 50,
"offset": 0,
"has_more": true,
"next_offset": 50,
"next_cursor": "eyJlIjoiMzM0ODMxNTMiLCJiIjoiZHJhZnRraW5ncyIsIm0iOiJtb25leWxpbmUiLCJpIjoiZHJhZnRraW5nc18zMzQ4MzE1M19tb25leWxpbmVfUEhJIn0"
},
"updated_at": "2026-01-26T02:10:37.846Z",
"filters": {
"league": "nba",
"sportsbook": "draftkings",
"market": "moneyline"
}
}
}Response Headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1737853200
X-Data-Delay: 0
X-Request-Id: req_abc123def456| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute for your tier |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the rate limit resets |
X-Data-Delay | Data delay in seconds (0 for real-time, 60 for free tier) |
X-Request-Id | Unique request identifier for debugging |
Error Responses
401 Unauthorized
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key",
"docs": "https://docs.sharpapi.io/en/authentication"
}
}403 Tier Restricted
{
"error": {
"code": "tier_restricted",
"message": "Sportsbook 'pinnacle' requires Sharp tier or higher",
"docs": "https://docs.sharpapi.io/en/pricing"
}
}429 Rate Limited
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry after 45 seconds.",
"docs": "https://docs.sharpapi.io/en/authentication#rate-limits"
}
}Odds Object Schema
| Field | Type | Description |
|---|---|---|
id | string | Unique odds identifier |
sportsbook | string | Sportsbook ID (e.g., draftkings) |
event_id | string | Event identifier |
sport | string | Sport slug (e.g., basketball, football) |
league | string | League slug (e.g., nba, nfl) |
home_team | string | Home team name |
away_team | string | Away team name |
market_type | string | moneyline, spread, total, player_prop, etc. |
selection | string | The selection (team name, Over/Under, player name) |
selection_type | string | Canonical side identifier. See Selection types below for the full enum, including compound forms (e.g. home_over) emitted on multi-axis markets. |
team_side | string|undefined | Raw team-side hint from the adapter — one of home, away, draw. Useful when selection_type carries a compound value (e.g. home_over) and you want just the team axis without parsing. Absent when the adapter did not stamp it. |
odds_american | number | American odds (e.g., -110, +150) |
odds_decimal | number | Decimal odds (e.g., 1.909) |
odds_probability | number | Implied probability (e.g., 0.5238) |
line | number | null | Spread or total line value (null for moneyline) |
is_alternate_line | boolean | true when this row’s line differs from the canonical main line for its (event, market_type, selection) group. false for the consensus main line, for no-line markets (moneyline, outright), and for rows whose cohort hasn’t been published yet (cold start, brand-new event). See is_main_line for the positive-polarity sibling that disambiguates “main” from “cohort-pending”. |
is_main_line | boolean | true when this row’s line equals the canonical main line for its (event, market_type, selection) group, AND for no-line markets (moneyline, outright — always main by definition). false for alt-line rows and for rows whose cohort hasn’t been published yet. Mutually exclusive with is_alternate_line: both true never coexists; both false is the cohort-pending state. Filter for is_main_line=true when you want a positive “main lines only” view that excludes cohort-pending rows. Also accepted as a query filter on /odds/best?is_main_line=true. |
event_start_time | string | ISO 8601 event start time |
timestamp | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds’ timestamp); it is NOT when the price last changed. See understanding the timestamp field. |
is_live | boolean | Whether the event is currently live |
is_active | boolean | true (default) = market open and bettable; false = market suspended/closed with the price frozen at its last value (so you can grey it out rather than trust a stale price). Mirrors OpticOdds’ locked-odds, but as a queryable field you can also filter on. Absent is treated as true. An active→suspended transition is pushed on the odds stream as an odds:update carrying is_active: false. |
event_uuid | string|undefined | Stable canonical event UUID from the SharpAPI atlas, when the event is mapped. Where event_id carries the adapter’s primary event identifier (often the originating sportsbook’s), event_uuid is a feed-stable hash you can use for cross-feed joins. Absent for unmapped events. |
external_event_id | string|undefined | The sportsbook’s own native event ID, when distinct from event_id. Useful for round-tripping rows back to the sportsbook’s UI or API. |
deep_link | string|undefined | Resolver URL pointing to the sportsbook’s event or bet-slip page. Pass state= (e.g. state=nj) on the request to route through state-specific subdomains for books that need them (BetMGM, Caesars, BetRivers). |
market_id | string|undefined | The sportsbook’s own native market identifier. Some books don’t expose one — absent when unknown. |
selection_id | string|undefined | The sportsbook’s own native selection/outcome identifier. Some books don’t expose one — absent when unknown. |
player_name | string|undefined | Player name (player prop markets only) |
stat_category | string|undefined | Stat category, e.g. points, rebounds (player prop markets only) |
home_pitcher | string|undefined | MLB only. Home-team starting pitcher when published by the book. |
away_pitcher | string|undefined | MLB only. Away-team starting pitcher when published by the book. |
public_bet_pct | number|undefined | Public betting ticket percentage (0.0-1.0). Currently BetMGM only. |
max_bet | number|undefined | Maximum wager amount (USD) for this market type. Emitted by Pinnacle and SBObet. See Liquidity and limits. |
volume | number|undefined | Cumulative traded volume on the selection, in the exchange’s native units. Exchanges only — currently Kalshi. See Liquidity and limits. |
volume_24h | number|undefined | Rolling 24-hour traded volume, in the exchange’s native units. Exchanges only — currently Polymarket and Kalshi. |
open_interest | number|undefined | Outstanding open contracts on the selection. Exchanges only — currently Kalshi. |
exchange_token_id | string|undefined | Exchange-native token or market identifier for order-routing use cases. Emitted where the upstream exchange exposes a stable token ID, currently Polymarket (token_id) and SX Bet (marketHash). |
polymarket_resolution | string|undefined | Polymarket only. UMA optimistic-oracle resolution status when the market has terminated — one of settled_normal, voided, disputed, proposed, unknown. Absent for live (unresolved) Polymarket markets and for every non-Polymarket book. |
home | object|undefined | New (May 2026). Nested home-team reference: {id, numerical_id, name, abbreviation, logo, city, mascot, conference, division}. See Entity reference IDs. |
away | object|undefined | New (May 2026). Nested away-team reference: {id, numerical_id, name, abbreviation, logo, city, mascot, conference, division}. |
sport_ref | object|undefined | New (May 2026). Nested sport reference: {id, numerical_id, name}. |
league_ref | object|undefined | New (May 2026). Nested league reference: {id, numerical_id, label}. |
market_ref | object|undefined | New (May 2026). Nested market reference: {id, numerical_id, label}. |
sportsbook_ref | object|undefined | New (May 2026). Nested sportsbook reference: {id, numerical_id, label}. |
Selection types
selection_type carries the canonical side identifier for each selection. Most markets are two-way (e.g. moneyline, point spread, total) and emit one of the simple values below. A small set of multi-axis markets (soccer double-chance, BTTS-combined, result × O/U, MMA round betting, tennis set betting, correct-score, etc.) encode two outcomes per selection and emit compound values joined by _.
| Family | Values | Where they appear |
|---|---|---|
| Two-way (team side) | home, away | moneyline, point_spread, puck_line, run_line, team_total, set_handicap, most period markets |
| Two-way (line direction) | over, under | total_points, total_goals, total_runs, total_games, total_rounds, team_total, all player_*_o_u props |
| Two-way (yes/no) | yes, no | binary, prop-style yes/no markets, exchange “back/lay” outcomes, Polymarket prediction markets |
| Two-way (parity) | even, odd | Total-parity markets (e.g. total points odd/even) |
| Three-way | draw | Three-way moneyline (soccer 1X2), draw-no-bet’s complementary side, next_goal “no goal” |
| Compound (team × O/U) | home_over, home_under, away_over, away_under | Soccer match_result_total_goals (“Team A and Over N.5”) and analogous result-plus-total markets |
| Compound (team × BTTS) | home_yes, home_no, away_yes, away_no, draw_yes, draw_no | Soccer match_result_both_teams_to_score |
| Compound (double chance) | home_draw, away_draw, home_away | Soccer double_chance (1X / X2 / 12) and MMA double-chance |
| Compound (round / method) | home_r1, home_r2, home_decision, away_r1, etc. | MMA round_betting and method-of-victory markets |
| Catch-all | other | game_prop, next_goal “no goal”, and any selection where the canonical-side mapper cannot decompose the outcome cleanly. Always present in low volume; treat as opaque. |
Parsing compound values. Compound selection_type strings always join the team axis (home / away / draw) to the secondary axis with a single underscore. To recover just the team axis without parsing, read team_side — it is the raw side stamped by the adapter for the same row.
Long-tail markets emit additional forms. Markets such as correct_score (e.g. "2_1"), set_betting (e.g. "0_2"), winning_margin, halftime_fulltime, first_goal, and anytime_goal encode score-level or compound outcomes directly in selection_type. If you depend on a closed enum, filter to the families above and treat any unrecognised value as opaque — do not error.
New (May 2026): nested reference blocks
Every odds row now carries six optional nested reference objects that bundle each entity’s slug id, display label, and stable numerical_id directly with the row. The flat string fields (sport, league, home_team, away_team, market_type, sportsbook) remain unchanged — the new blocks are purely additive.
{
"id": "pinnacle_mlb_yankees_redsox_moneyline_NYY",
"sportsbook": "pinnacle",
"sport": "baseball",
"league": "mlb",
"home_team": "New York Yankees",
"away_team": "Boston Red Sox",
"market_type": "moneyline",
"selection": "New York Yankees",
"odds_american": -135,
"home": {
"id": "new_york_yankees",
"numerical_id": 20,
"name": "New York Yankees",
"abbreviation": "NYY",
"logo": "https://cdn.opticodds.com/team-logos/baseball/36.png",
"city": "New York",
"mascot": "Yankees",
"conference": "AL",
"division": "East Division"
},
"away": {
"id": "boston_red_sox",
"numerical_id": 5,
"name": "Boston Red Sox",
"abbreviation": "BOS",
"logo": "https://cdn.opticodds.com/team-logos/baseball/14.png",
"city": "Boston",
"mascot": "Red Sox",
"conference": "AL",
"division": "East Division"
},
"sport_ref": { "id": "baseball", "numerical_id": 3, "name": "Baseball" },
"league_ref": { "id": "mlb", "numerical_id": 354, "label": "MLB" },
"market_ref": { "id": "moneyline","numerical_id": 878, "label": "Moneyline" },
"sportsbook_ref": { "id": "pinnacle", "numerical_id": 28, "label": "Pinnacle" }
}When fields are absent. Each block is emitted only when the underlying entity is mapped in the SharpAPI atlas. Unmapped entities (long-tail leagues, niche markets, fresh sportsbook additions) omit the block, in which case the flat field on the row is the only ID you’ll see. Treat every block — and every inner field, including numerical_id and abbreviation — as optional.
See Entity reference IDs for the full semantics, the dense-from-1 / frozen / never-reused contract, and recommended use cases (storage keys, cross-feed mapping, display labels).
Sorting
Use the sort parameter to order results by any field. Prefix with - for descending order.
# Sort by best American odds (descending)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&sort=-odds_american" \
-H "X-API-Key: YOUR_API_KEY"
# Sort by odds_probability (ascending)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&sort=odds_probability" \
-H "X-API-Key: YOUR_API_KEY"
# Sort by event start time
curl "https://api.sharpapi.io/api/v1/odds?sort=event_start_time" \
-H "X-API-Key: YOUR_API_KEY"Valid sort fields: odds_american, odds_decimal, odds_probability, event_start_time, timestamp, sportsbook, league, sport.
Field Selection
Use the fields parameter to return only specific fields, reducing payload size.
# Only return id, sportsbook, and American odds
curl "https://api.sharpapi.io/api/v1/odds?league=nba&fields=id,sportsbook,odds_american" \
-H "X-API-Key: YOUR_API_KEY"The response will only include the requested fields for each odds object:
{
"data": [
{
"id": "draftkings_33483153_moneyline_PHO",
"sportsbook": "draftkings",
"odds_american": -150
}
]
}Odds Range Filtering
Use min_odds and max_odds to filter by American odds value.
# Only return plus-money odds (+100 and above)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&min_odds=100" \
-H "X-API-Key: YOUR_API_KEY"
# Only return odds between -200 and +200
curl "https://api.sharpapi.io/api/v1/odds?league=nba&min_odds=-200&max_odds=200" \
-H "X-API-Key: YOUR_API_KEY"Event-Grouped Response
Use group_by=event to group odds by event instead of a flat list. This is useful for building event-centric UIs.
curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \
-H "X-API-Key: YOUR_API_KEY"{
"data": [
{
"event_id": "33483153",
"event_name": "PHI 76ers vs PHO Suns",
"sport": "basketball",
"league": "nba",
"start_time": "2026-01-26T19:00:00Z",
"is_live": false,
"odds": [
{
"id": "draftkings_33483153_moneyline_PHO",
"sportsbook": "draftkings",
"market_type": "moneyline",
"selection": "PHO Suns",
"selection_type": "away",
"odds_american": -150,
"odds_decimal": 1.667,
"odds_probability": 0.60,
"line": null,
"timestamp": "2026-01-26T02:10:24.125Z"
}
]
}
],
"meta": {
"group_by": "event",
"books_available": 5,
"filters": { "league": "nba" },
"updated_at": "2026-01-26T02:10:37.846Z"
}
}Book Access by Tier
The sportsbooks included in your odds results depend on your subscription tier:
| Tier | Books Available | Included Sportsbooks |
|---|---|---|
| Free | 2 | DraftKings, FanDuel |
| Hobby | 5 | + BetMGM, Caesars, theScore Bet |
| Pro | 15 | + Bet365, BetRivers, and more |
| Sharp | All 32 | All available sportsbooks |
| Enterprise | All 32 | All available sportsbooks |
Pinnacle (sharp book) requires Sharp tier or higher. Requesting sportsbook=pinnacle on a Free, Hobby, or Pro tier will return a 403 tier_restricted error.
Filtering Examples
# Get live NBA odds from all your available books
curl "https://api.sharpapi.io/api/v1/odds?league=nba&live=true" \
-H "X-API-Key: YOUR_API_KEY"
# Get moneyline and spread odds for a specific event
curl "https://api.sharpapi.io/api/v1/odds?event=33483153&market=moneyline,spread" \
-H "X-API-Key: YOUR_API_KEY"
# Paginate through all NFL spread odds (use next_cursor from each response)
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&market=spread&limit=200" \
-H "X-API-Key: YOUR_API_KEY"Related Endpoints
- Odds Delta - Get only odds that changed since a given timestamp
- Best Odds - Get the best odds across all books for each selection
- Odds Comparison - Compare odds across books side by side
- Batch Odds - Fetch odds for multiple events in one request
- Markets - List available market types
- Sportsbooks - List available sportsbooks and their status