ParlayAPI Documentation

Real-time sports odds API: 22 sources, 13+ books in a single call, 6× cheaper than the-odds-api. Drop-in compatible with TOA's URL surface where it makes sense, with extensions for player props, prediction-market exchanges, and WebSocket streaming.

Quick Start

Three lines to your first call:

pip install parlay-api

from parlay_api import ParlayAPI
client = ParlayAPI(api_key="YOUR_KEY")
odds = client.odds("baseball_mlb", regions="us")
curl "https://parlay-api.com/v1/sports/baseball_mlb/odds?regions=us" \
  -H "X-API-Key: YOUR_KEY"
const r = await fetch(
  "https://parlay-api.com/v1/sports/baseball_mlb/odds?regions=us",
  { headers: { "X-API-Key": "YOUR_KEY" } }
);
const odds = await r.json();
import requests
r = requests.get(
    "https://parlay-api.com/v1/sports/baseball_mlb/odds",
    headers={"X-API-Key": "YOUR_KEY"},
    params={"regions": "us"},
)
odds = r.json()

Sign up free for a 1,000-credit/month key. No card required.

Authentication

Pass your API key one of two ways:

  • Header: X-API-Key: YOUR_KEY (recommended)
  • Query param: ?apiKey=YOUR_KEY (TOA-compatible)

WebSocket connections use the query param: wss://parlay-api.com/ws/odds/{sport_key}?apiKey=YOUR_KEY

Never commit your key. If you accidentally publish one, rotate it from the dashboard immediately.

Credits & Pricing

Every paid endpoint deducts a fixed number of credits per call regardless of how many books, players, or markets come back. One /props call returns ALL books for that sport.

EndpointCreditsNotes
/v1/sports0Free, lists active sport keys
/v1/sports/{key}/events1Deduped via canonical_event_id
/v1/sports/{key}/odds1TOA-shape moneyline/spread/total
/v1/sports/{key}/props3All books, all markets, single call
/v1/sports/{key}/consensus3Best/worst per (player, market, line)
/v1/sports/{key}/arbitrage10Cross-book arb scanner
/v1/sports/{key}/ev5+EV picks vs Pinnacle baseline
/v1/sports/{key}/live1In-play games
/v1/sports/{key}/live/points1Live PBP snapshot (Free tier OK)
/v1/sports/{key}/live/sse7 / eventLive PBP stream (Starter+, billed per delivered event)
/v1/sports/{key}/live/book_latency5Per-book lag for arb-mining (Pro+)
/v1/sports/{key}/live/period_markets21H, Q1-Q4 spreads/totals/h2h (Free OK)
/v1/inplay/arbs10Live arb scanner (5s refresh)
/v1/event-markets/search0 betaKalshi, Polymarket, and Novig event-market discovery
/v1/historical/...52012-present closing lines
/v1/historical/stats0Public summary, cached 10min
/v1/stats0Public
/ws/odds/{key}0 + tierBusiness+ tier, no per-frame charge

Tiers

TierPriceCredits/moConcurrent SSE/WSBest for
Free$01,0001 (polling only)Trying it out, light testing
Starter$520,0003 (SSE)Small scanner, 1-2 sports
Pro$20100,00025 (SSE + WS)Serious bettor, multi-sport
Business$401,000,000100 (SSE + WS)Tools, content, reseller
Enterprise / Scalecontact5M+1000 (SSE + WS)Bespoke deals, custom SLA

Concurrent SSE/WS = max simultaneous push-stream connections per API key. Polling endpoints aren't connection-capped, only credit-capped. Hit the limit and new SSE / WS connections return 429 / WS close 4002 with a clear reason; existing connections aren't affected.

Sandbox (no auth, fake data)

Hit /v1/sandbox/sports, /v1/sandbox/sports/{sport_key}/odds, /v1/sandbox/sports/{sport_key}/live/period_markets, or /v1/sandbox/sports/{sport_key}/live/sse to see the response shape with deterministic synthetic data. No API key, no credits consumed, IP rate-limited at 60 req/min. Useful for verifying integration shape during off-hours when no real games are live.

Source health diagnostic

Live-betting bots need to know when a source goes stale so they don't trade on dead data. GET /v1/sports/{sport_key}/live/source-health?apiKey=YOUR_KEY returns per-source freshness for the requested sport (events in the last 5 min, seconds since last event, latest capture timestamp). 1 credit per call. Recommended polling cadence: 30 seconds. A source with seconds_since_last_event > 60 during a known-live game has likely failed; failover yourself or rely on our internal failover (one source going down doesn't break customer SSE — primary auto-promotes).

Postman + OpenAPI spec

Full machine-readable OpenAPI spec at /openapi.json (129 paths). Postman supports importing OpenAPI directly: Postman → Import → Link → paste the URL above → Import. Auto-generated collection with every endpoint pre-populated.

Official SDKs

Python: pip install parlay-api · source
JavaScript / Node: npm install parlay-api · source

Both SDKs ship with built-in math helpers (devig, Kelly sizing, American↔implied conversions) and async iterators for SSE / WebSocket streams.

API stability

Read the full versioning + deprecation policy. Short version: paths under /v1/ are stable. Additive changes ship without notice. Breaking changes ship under /v2/ with 12+ months of overlap. Pricing changes get 30+ days of notice. Your integration won't break overnight.

Every response includes x-requests-used, x-requests-remaining, and x-requests-last headers so you always know how much you've burned. Empty responses still bill normally (no auto-refund, see the leak fix if curious).

Python SDK

Pure-Python single-file SDK on PyPI: pip install parlay-api. Source on GitHub.

The SDK is a near drop-in replacement for the-odds-api's official Python clients with extra methods for our extensions and built-in devig math helpers.

from parlay_api import ParlayAPI

client = ParlayAPI(api_key="YOUR_KEY")

# TOA-compatible methods
sports = client.sports()
events = client.events("baseball_mlb")
odds = client.odds("baseball_mlb", regions="us", markets=["h2h", "spreads"])
historical = client.historical_odds("baseball_mlb", date="2024-10-15")

# Extensions
props = client.props("baseball_mlb", markets=["player_total_bases"])
arbs = client.arbitrage("baseball_mlb", limit=20)
consensus = client.consensus("baseball_mlb")

# Devig math (no network call)
fair_over, fair_under = ParlayAPI.devig(over_price=-110, under_price=-110)
edge_pct = ParlayAPI.edge(book_price=-105, fair_prob=fair_over)

# WebSocket URL builder
ws_url = client.websocket_url("baseball_mlb")

Sports

GET/v1/sports0 credits

List all sport keys with at least one event in the last 24 hours.

Response

[
  {
    "key": "baseball_mlb",
    "group": "Baseball",
    "title": "MLB",
    "description": "Major League Baseball",
    "active": true,
    "has_outrights": false
  },
  ...
]

See Sport Keys reference for the full list.

Events

GET/v1/sports/{sport_key}/events1 credit

List events for a sport. Deduped by canonical_event_id (an MD5 of sport + date + sorted team names) so the same matchup from books with different team naming conventions ("NY Yankees" vs "New York Yankees") collapses into one event.

Parameters

commenceTimeFromISO 8601 string
Filter to events starting after this time
commenceTimeToISO 8601 string
Filter to events ending before this time
dateFormatenum
iso (default) or unix

Response

[
  {
    "id": "8b1f3a2c0e9d4...",
    "canonical_event_id": "ee78855a3bdd1019",
    "sport_key": "baseball_mlb",
    "sport_title": "MLB",
    "commence_time": "2026-05-01T19:35:00Z",
    "home_team": "New York Yankees",
    "away_team": "Kansas City Royals"
  },
  ...
]

Odds

GET/v1/sports/{sport_key}/odds1 credit

TOA-compatible game-line odds. Returns moneyline, spread, totals (and player_* markets if you ask for them) across every book that publishes them.

Parameters

regionscomma-separated
us, us2, uk, eu, au. Default: us
marketscomma-separated
h2h (moneyline), spreads, totals, outrights. Player markets accepted too: player_total_bases, etc.
bookmakerscomma-separated
Filter to specific books: draftkings,fanduel,pinnacle. See Bookmaker Keys.
oddsFormatenum
american (default) or decimal
dateFormatenum
iso (default) or unix
eventIdscomma-separated
Limit response to specific event IDs

Example

odds = client.odds(
    "baseball_mlb",
    regions="us",
    markets=["h2h", "spreads", "totals"],
    bookmakers=["draftkings", "fanduel", "pinnacle"],
)
curl "https://parlay-api.com/v1/sports/baseball_mlb/odds?regions=us&markets=h2h,spreads,totals&bookmakers=draftkings,fanduel,pinnacle" \
  -H "X-API-Key: YOUR_KEY"

Player Props

GET/v1/sports/{sport_key}/props3 credits

Player prop odds across every book in one call. Each row has over_price, under_price, line, and the bookmaker source. Includes the standard sportsbooks plus DFS apps (PrizePicks, Underdog, Betr, Sleeper, Pick6, ParlayPlay) and exchange data (Novig, ProphetX, Kalshi).

Parameters

marketscomma-separated
Filter to specific market keys, e.g. player_total_bases,player_hits_runs_rbis. See Market Keys.
bookmakerscomma-separated
Filter to specific books
playerstring
Partial-match player name (e.g. ?player=Judge)
eventIdstring
Limit to one game
dfsOddsenum
midpoint (default, +100/-100 zero-vig) or effective (-137/-137 reflecting actual 2-pick payout)
limitint 1-10000
Max rows returned, default 1000

Response shape

[
  {
    "bookmaker": "draftkings",
    "bookmaker_title": "DraftKings",
    "player": "Aaron Judge",
    "market_key": "player_home_runs",
    "market": "Home Runs",
    "line": 0.5,
    "over_price": 290,
    "under_price": -370,
    "home_team": "New York Yankees",
    "away_team": "Kansas City Royals",
    "canonical_event_id": "ee78855a3bdd1019",
    "commence_time": "2026-05-01T19:35:00Z",
    "last_update": 1746130000000
  },
  ...
]

Consensus

GET/v1/sports/{sport_key}/consensus3 credits

For each unique (event, player, market, line), returns the best and worst price across all books, the median consensus, and the spread between them. Useful for line-shopping. DFS books are excluded from the math.

Response per row

{
  "canonical_event_id": "ee78855a3bdd1019",
  "home_team": "New York Yankees", "away_team": "Kansas City Royals",
  "player": "Aaron Judge", "market_key": "player_home_runs", "line": 0.5,
  "num_books": 4, "total_books": 4,
  "consensus_odds": 290, "consensus_prob": 0.2564,
  "best_odds": {"bookmaker": "fliff", "price": 310},
  "worst_odds": {"bookmaker": "draftkings", "price": 270},
  "spread": 40,
  "all_books": [
    {"bookmaker": "fliff", "price": 310},
    {"bookmaker": "fanduel", "price": 295},
    ...
  ]
}

Arbitrage

GET/v1/sports/{sport_key}/arbitrage10 credits

Two-leg arbs across books on the same prop, with optimal stake split and projected profit. DFS books excluded. Profit cap 15% (anything higher is almost certainly stale or mis-paired data).

Parameters

limitint
Max arbs returned, default 50
min_profit_pctfloat
Min profit threshold, default 0.5%

+EV Picks

GET/v1/sports/{sport_key}/ev5 credits

Bets where one book's price implies a higher win probability than a "fair" baseline (Pinnacle de-vigged, with Novig and ProphetX as exchange-priced cross-checks). Returns book, line, edge percentage, and Kelly-optimal stake.

Live Games

GET/v1/sports/{sport_key}/live1 credit

Currently in-progress games with grouped book quotes. Sub-10s freshness on our in-play collectors.

Live Point-by-Point (PBP)

Real-time match-state events. Covers tennis, baseball (MLB), basketball (NBA), hockey (NHL), MMA (UFC), boxing, NFL, and soccer (Premier League, La Liga, Bundesliga, Serie A, Ligue 1, UEFA Champions / Europa, MLS). Cross-source redundancy: when our primary feed for a sport drops, a fallback (ESPN / SofaScore) auto-promotes within 30 seconds.

Snapshot (polling)

GET/v1/sports/{sport_key}/live/points1 credit

Returns current state for one match (with match_id) or all in-play matches for the sport (omit match_id). Free tier OK.

Parameters

match_idstring
Optional. Single match. Omit for all in-play.

Stream (Server-Sent Events)

GET/v1/sports/{sport_key}/live/sse7 credits per delivered event

Persistent SSE connection. Server pushes each state change (point won, game won, set closed, goal, foul, pitch outcome, period change) within ~50ms of the event. Starter+ tier required. Use the standard EventSource API.

A typical 3-set tennis match delivers ~200 events (~1,400 credits). A typical NBA game delivers ~400-500 actions. You pay proportional to the volume of state changes the match produces.

// JS
const es = new EventSource('https://parlay-api.com/v1/sports/tennis/live/sse?match_id=...&apiKey=...');
es.addEventListener('initial_state', e => console.log('snap', JSON.parse(e.data)));
es.addEventListener('pbp_event', e => console.log('event', JSON.parse(e.data)));

Cross-book latency

GET/v1/sports/{sport_key}/live/book_latency5 credits

Per-book lag relative to our primary PBP feed. Returns each book's effective latency in seconds. Pro+ tier. Use case: arb scanners check this every few seconds and flag matches where a specific book has stale lines (positive lag > 5s typically means an exploitable window).

{
  "sport_key": "baseball_mlb",
  "results": [
    {"match": "Yankees vs Rangers", "book": "fanduel",   "lag_seconds": 7.8, ...},
    {"match": "Yankees vs Rangers", "book": "draftkings","lag_seconds": 1.2, ...},
    {"match": "Yankees vs Rangers", "book": "caesars",   "lag_seconds": 4.0, ...}
  ]
}

Period markets (1H, Q1-Q4, halves, NHL periods)

GET/v1/sports/{sport_key}/live/period_markets2 credits

In-game spreads, totals, and h2h for sub-game periods: 1st half, 2nd half, quarters (NBA, WNBA, NFL, NCAAF), hockey periods (NHL), or first 5 / first 7 innings (MLB). Includes alternate lines: a single Q1 spread query for one NBA game returns ~8 to 10 alt lines. Open to all tiers (Free can run ~500 test calls; continuous high-frequency polling needs Pro or Business). Latency: 1 to 4 seconds (vs 30s+ on the-odds-api).

Query params: period (FT, 1H, 2H, Q1, Q2, Q3, Q4, OT, P1, P2, P3, F5, F7, or 'all'), match_id, source, market (spread, total, h2h). All optional except apiKey.

GET /v1/sports/basketball_nba/live/period_markets?period=Q1&market=spread&apiKey=...

{
  "sport_key": "basketball_nba",
  "period": "Q1",
  "market": "spread",
  "count": 18,
  "results": [
    {"source":"pinnacle", "home_team":"Oklahoma City Thunder",
     "away_team":"Los Angeles Lakers", "period_key":"Q1",
     "market":"spread", "side":"home", "line":-3.5, "price":-144,
     "age_seconds":1, ...},
    {"source":"pinnacle", "side":"away", "line":3.5, "price":120, ...},
    ...alt lines from -2.5 through -6.0...
  ]
}

GET /v1/sports/{sport_key}/live/period_markets/sources returns which books have which periods active right now (last 10 min). Useful for client-side discovery.

Sports with period coverage: NBA (1H, 2H, Q1-Q4), WNBA (1H, 2H, Q1-Q4), NCAAB (1H, 2H), NFL (1H, 2H, Q1-Q4), NCAAF (1H, 2H, Q1-Q4), NHL (P1, P2, P3), MLB (F5, F7), soccer leagues (1H, 2H). Coverage depends on book availability per period; e.g. Pinnacle has every period for every sport, DraftKings/FanDuel/BetMGM/Caesars vary by league.

In-Play Arbitrage Scanner

GET/v1/inplay/arbs10 credits

Cross-book arbs detected during live games. Updated every 5 seconds. Pairs with the WebSocket: subscribers receive {"type":"arb_flagged"} frames the moment a new arb is found.

Historical Odds

GET/v1/historical/sports/{sport_key}/odds5 credits
GET/v1/historical/sports/{sport_key}/closing-odds5 credits
GET/v1/historical/sports/{sport_key}/matches2 credits
GET/v1/historical/stats0 credits

Historical is split by product shape so modelers can tell prices from results. We do not derive or invent missing odds.

ProductEndpointUse caseImportant distinction
Point-in-time odds/oddsTOA-compatible historical snapshotsRequires date; limited by tier window.
Closing odds/closing-oddsBacktests at final pregame priceGame lines and prop closing rows where real prices exist.
Match/results archive/matchesSchedules, teams, scores, esports resultsRows include has_odds; result-only rows are not price history.
Forward line movement/line-movementCLV and price-change trackingStarts when ParlayAPI began capturing that market.

Esports note: CS2, Dota 2, and Valorant have historical match/result archives plus current forward Pinnacle price capture. They do not yet have deep historical before/during/after odds movement for past years.

Parameters

date*YYYY-MM-DD
Required. Date of the games
pricedOnlyboolean
For /matches, return only rows that include real odds.

Exchanges

GET/v1/exchanges1 credit
GET/v1/exchange/{exchange_key}/markets1 credit

Exchange-specific data including order book depth where available. Currently novig (sports) and prophetx (sports + politics).

Event Market Search

GET/v1/event-markets/search0 credits in beta
GET/v1/prediction-markets/search0 credits in beta

Free-text discovery across Kalshi, Polymarket, and Novig event markets. Built for Specials, next-team markets, coach-out markets, trade deadline markets, and other non-standard contracts that do not fit a fixed sport/event schema.

Try the live demo at /event-markets.

Parameters

qstring
Search text, for example AJ Brown next team or Mike Vrabel out before September.
sourcescomma-separated
kalshi,polymarket,novig. Default checks all three.
min_volumenumber
Hide low-volume markets below this source-native volume.
min_confidence0-1
Hide weak text matches. Default 0.
sortenum
balanced shows a mix of venues. match sorts by match confidence and volume.

Example

curl 'https://parlay-api.com/v1/event-markets/search?q=AJ%20Brown%20next%20team&sources=kalshi,novig,polymarket&min_volume=1000'

Response highlights

{
  "query": "AJ Brown next team",
  "credits_charged": 0,
  "source_summary": {
    "kalshi": {"count": 10, "max_volume": 283989.29},
    "novig": {"count": 4, "max_volume": 9458.94}
  },
  "markets": [
    {
      "source": "kalshi",
      "event_title": "A.J. Brown's Next Team",
      "outcome": "New England",
      "prices": {"yes_bid": 0.79, "yes_ask": 0.81}
    }
  ],
  "clusters": [
    {
      "cluster_key": "aj brown next team",
      "sources": ["kalshi", "novig"],
      "note": "Candidate text match only. Prices remain source-native and are not blended."
    }
  ]
}
Settlement matters. Event-market clusters are discovery leads, not automatic arb proof. Compare the source settlement rules before acting on a cross-venue price gap.

WebSocket: /ws/odds

WSwss://parlay-api.com/v1/ws/odds/{sport_key}?apiKey=YOUR_KEY

Real-time odds streaming for one sport. Business / Enterprise / Scale tier required. Receives a JSON frame the moment a price changes anywhere in our collector pipeline.

Full WebSocket docs. This section is a quick reference. For the complete protocol, code examples in 10+ languages, +EV alert pattern, player-prop streaming, troubleshooting, and SSE alternative, see /docs/websocket · Quickstart · Examples · Player props · Edge alerts · Troubleshooting · SSE · Migration.

Frame types

typeWhenPayload
initial_stateOn connectLast 500 props for the sport
odds_updateEvery changeArray of changed rows
arb_flaggedNew arb detectedThe arb opportunity (5s scanner)
heartbeatEvery 30sConnection health

Filter to one game

Send a subscribe frame after connect:

{"type": "subscribe", "event_id": "ee78855a3bdd1019"}

To unsubscribe and receive sport-wide updates again:

{"type": "unsubscribe"}

Python example

from parlay_api import ParlayAPI
import asyncio, json
import websockets

async def stream():
    client = ParlayAPI(api_key="YOUR_KEY")
    url = client.websocket_url("baseball_mlb")
    async with websockets.connect(url) as ws:
        async for raw in ws:
            frame = json.loads(raw)
            if frame["type"] == "odds_update":
                for row in frame["data"]:
                    print(row["bookmaker"], row["player"],
                          row["over_price"], row["under_price"])

asyncio.run(stream())

End-to-end delivery latency: 300–800 ms on Scale (raw), up to the tier coalesce window otherwise (Business 1 s, Enterprise 0.5 s). Source cadence varies by book and market.

SSE Hot Feed: /v1/sse/hot

GEThttps://parlay-api.com/v1/sse/hot/{sport_key}?apiKey=YOUR_KEY

EventSource-compatible HTTP stream for enterprise hot paths. It sends a connection frame, source freshness, initial state, then live updates with a 5-second heartbeat.

Filters

paramexamplemeaning
bookmakersfanduel,pinnacle,caesarsOnly these books
kindsgame,propGame lines, props, or both
marketsplayer_points,player_reboundsProp market keys
event_id2026-05-07_Team_A_Team_BSingle event filter
heartbeat_s51 to 30 seconds
const es = new EventSource(
  "https://parlay-api.com/v1/sse/hot/baseball_mlb?apiKey=YOUR_KEY&bookmakers=fanduel,pinnacle&kinds=game&heartbeat_s=5"
);

es.onmessage = (ev) => {
  const msg = JSON.parse(ev.data);
  if (msg.type === "odds_update") console.log(msg.data);
};
# Python quickstart
import json, requests

url = "https://parlay-api.com/v1/sse/hot/baseball_mlb"
params = {
    "apiKey": "YOUR_KEY",
    "bookmakers": "fanduel,pinnacle",
    "kinds": "game",
    "heartbeat_s": 5,
}

with requests.get(url, params=params, stream=True, timeout=60) as r:
    r.raise_for_status()
    for line in r.iter_lines(decode_unicode=True):
        if line and line.startswith("data: "):
            msg = json.loads(line[6:])
            if msg["type"] in ("hot_feed_status", "odds_update"):
                print(msg)

Hot feed means fast delivery once a book update lands in our pipeline. It does not invent prices or promise that every external book publishes a new price every 5 seconds.

Operational check: admins run python3 scripts/verify_book_coverage.py before broad outreach or deploys to prove active books survive REST and SSE visibility.

WebSocket: /ws/live

WSwss://parlay-api.com/ws/live/{sport_key}

Same protocol as /ws/odds but session-cookie authenticated (used by the live dashboard). For programmatic streaming, use /ws/odds with an API key.

Errors & Status Codes

CodeMeaningAction
200OKUse response body
400Invalid sport_key or paramCheck spelling and Sport Keys
401Missing or invalid API keyPass X-API-Key header or ?apiKey=
403Credit limit exceededWait for monthly reset or upgrade tier
404Resource not foundEndpoint or event_id doesn't exist
422Missing required paramCheck the param table for that endpoint
429Rate limitedSlow down or retry with backoff
500Server errorRetry. If it persists, email peakpotentialmediaventures@gmail.com

The Python SDK raises typed exceptions: InvalidAPIKeyError, CreditLimitExceededError, RateLimitedError, TierGatedError, all subclasses of ParlayAPIError.

Sport Keys

Live keys (those with active events in the last 24h). The /v1/sports endpoint returns the current authoritative list.

KeySport
baseball_mlbMLB
basketball_nbaNBA
basketball_wnbaWNBA
basketball_ncaabNCAAB
icehockey_nhlNHL
americanfootball_nflNFL
americanfootball_ncaafNCAAF
mma_mixed_martial_artsMMA / UFC
tennis_atpATP
tennis_wtaWTA
soccer_eplEnglish Premier League
soccer_spain_la_ligaLa Liga
soccer_germany_bundesligaBundesliga
soccer_italy_serie_aSerie A
soccer_france_ligue_oneLigue 1
soccer_usa_mlsMLS
golf_pgaPGA Tour
golf_livLIV Golf
esports_lolLeague of Legends
esports_cs2Counter-Strike 2
esports_valValorant

Plus 100+ regional soccer/basketball/baseball/hockey leagues via Pinnacle. Hit /v1/sports for the current full list.

Bookmaker Keys

KeyBookType
draftkingsDraftKingsSportsbook
fanduelFanDuelSportsbook
caesarsCaesarsSportsbook
bovadaBovadaSportsbook
betmgmBetMGMSportsbook
fanaticsFanaticsSportsbook
pinnaclePinnacleSharp book (de-vig baseline)
fliffFliffSportsbook
bet365bet365Sportsbook
betriversBetRiversSportsbook
hardrockHard RockSportsbook
tipicoTipicoSportsbook
pointsbetPointsBetSportsbook
parxParxSportsbook
stakeStakeSportsbook
sugarhouseSugarHouseSportsbook
novigNovigExchange
prophetxProphetXExchange
kalshiKalshiPrediction market
prizepicksPrizePicksDFS pick'em
underdogUnderdogDFS pick'em
betrBetrDFS pick'em
sleeperSleeperDFS pick'em
pick6Pick6 (DraftKings)DFS pick'em
parlayplayParlayPlayDFS pick'em

Market Keys

The most-used market keys per sport. Hit /v1/sports/{sport_key}/props/markets for the full live list.

MLB

player_total_bases, player_hits, player_home_runs, player_rbis, player_runs, player_singles, player_doubles, player_triples, player_walks, player_strikeouts, player_pitcher_outs, player_hits_allowed, player_earned_runs, player_hits_runs_rbis, player_first_hit, player_first_home_run

NBA / WNBA

player_points, player_rebounds, player_assists, player_threes, player_steals, player_blocks, player_turnovers, player_pra (pts+reb+ast), player_pts_rebs, player_pts_asts, player_rebs_asts, player_double_double, player_triple_double

NHL

player_goals, player_assists, player_points_nhl, player_shots_on_goal, player_saves, player_anytime_goal, player_powerplay_points, player_first_goal_scorer, player_anytime_goal_scorer

NFL

player_pass_yds, player_pass_tds, player_pass_completions, player_rush_yds, player_rec_yds, player_receptions, player_anytime_td, player_first_td, player_longest_rec, player_interceptions

Soccer

player_anytime_goalscorer, player_shots_on_target, player_assists, player_goals_assists, player_fouls, player_total_sets, plus the standard h2h, spreads, totals at the game level.

Migration from the-odds-api

If you're already using TOA, the URL surface for moneyline/spread/total odds is API-compatible. Change the host and you're done:

# Was:
TOA_BASE = "https://api.the-odds-api.com/v4"

# Now:
TOA_BASE = "https://parlay-api.com/v1"

Your existing TOA Python clients pointing at this base URL will work for /sports, /sports/{key}/odds, /sports/{key}/events, and /historical/sports/{key}/odds. Player props are available at /sports/{key}/props with a different (better) shape, see Player Props.

Detailed comparison: parlay-api.com vs the-odds-api