Sports & Odds

Get Props

Get player prop odds from 10+ sources. 3 credits.

Sourced from DraftKings, FanDuel, Caesars, Bovada, Pinnacle, Fliff (real American odds), PrizePicks, Underdog, Betr, Pick6, Sleeper, Novig, ProphetX, Polymarket (event markets, opt-in via include_event_markets=true).

Freshness. Active books are polled every few seconds; the poll cadence per source runs ~30-120s depending on the book. This endpoint serves the most recent row per book within its 60-minute freshness window, so a quiet market can return a line several minutes old. Every row (and every entry in a grouped books[]) carries age_seconds: validated Pinnacle observation age when available, otherwise write age. Original quote time remains in last_update. To enforce a tighter window pass ?maxAgeSec= (e.g. ?maxAgeSec=120 for props no older than two minutes); rows past the bound, and rows whose freshness clock can't be parsed, are dropped.

Supported sports: NFL, NBA, MLB, NHL, MMA/UFC, Soccer, Tennis, Golf, and more.

Market keys: player_points, player_rebounds, player_assists, player_three_pointers, player_strikeouts, player_hits, player_home_runs, player_total_bases, player_runs, player_rbis, player_goals, player_shots_on_goal, player_pts_rebs_asts, and 50+ more.

Example: GET /v1/sports/basketball_nba/props?markets=player_points,player_rebounds

Period player props and the period field. DFS boards publish first-quarter and first-half player lines next to the full-game line for the same player and stat. They are separate markets and carry their own keys, using the same _1st_quarter / _1st_half suffixes as the game-line period markets: player_pass_yds_1st_quarter, player_pass_yds_1st_half, player_rush_yds_*, player_reception_yds_*, player_receptions_*, player_fantasy_points_*. GET /v1/markets is the authoritative list. Every row (and every grouped prop) carries a period field so you never parse the key yourself: "FULL" for a confirmed full-game line, "Q1" first quarter, "1H" first half, plus "P1" / "F5" where a sport uses them. Legacy unsuffixed PrizePicks rows whose segment was not retained say "UNKNOWN" instead of being guessed as full game. It sits on the prop rather than on each book, because the segment belongs to the market and not to whoever priced it.

Cutover note (ticket #582). Until this change was deployed, period projections were written under the full-game market_key, so one player/market/snapshot group could hold several different lines with nothing to tell them apart. Rows written from the deploy onward carry the suffixed key and the right period. There is no single cutover instant: the PrizePicks collection paths are deployed separately, so each one changes over when it ships. Rows written before a path changed over keep the old mixed key and report "UNKNOWN": the segment was never stored, so it cannot be recovered from the archived row. Until those legacy rows age out, filtering markets=player_pass_yds can still include them alongside confirmed full-game lines.

Filter by player: ?player=LeBron

Filter by book: ?bookmakers=fliff,pinnacle

NFL touchdown identity: player_anytime_td means at least one scored touchdown and returns line: 0.5. The accepted anytime aliases return that same key. Bovada half/quarter offers have separate _1st_half, _2nd_half and _1st_quarter through _4th_quarter keys, with the period removed from the player name. The unsuffixed key is full game. Novig's higher thresholds use player_touchdowns_scored, retaining the native line: 1.5 means 2+ scores, 2.5 means 3+ scores. These are scored touchdowns, not passing touchdowns or combined passing/rushing/receiving totals. A missing under_price means this feed did not supply a usable No or Under quote; never infer it from the Yes price. It does not establish that the sportsbook never offers that side. Read the player name from player; player_name is not a field of this response.

DFS directions and identity: Current Pick6 and Underdog observations return active native directions in available_sides, with literal selection IDs and entry payout multipliers in selection_by_side. payout_multiplier_scope: "entry" makes explicit that these multipliers are not American side prices. native_identity names the provider's projection-line identifiers; a changed line can have a new line identity, so persist the returned IDs rather than deriving identity from player and market names. Pick6 American price fields remain null, and dfsOdds does not normalize them.

DFS projection tags (odds_type, projection_type): rows from a DFS pick'em source carry a normalized source-declared type. Common values are standard, demon, goblin, boosted, discounted, gimme_pick, stat_slice, and power_up; values only appear when the source provides enough native evidence to classify the line. odds_type is lowercase and projection_type is the same value upper-cased, kept as an additive alias. Underdog also exposes has_alternates independently because an ordinary projection may have an alternate ladder. A row without source type evidence has neither key, so test for presence rather than a falsy value.

With grouped=true these two fields live inside each books[] entry, next to that book's prices, and are absent from the entries of books that did not report them. They are NOT a property of the prop: a group that holds both a PrizePicks demon and a DraftKings price gets no top-level tag at all. For one release, a group whose books[] holds exactly one book also repeats its tag at the top level as a compatibility bridge, since on a single-book group the value is unambiguous. Read the tag from books[]; the top-level copy goes away in the next release.

Observation freshness (last_observed, last_update_type): a row whose line came from a validated live observation rather than an unvalidated archive row also carries the instant it was observed and last_update_type: "collector_observation". A row without that evidence has neither key. Like last_update, the pair describes ONE book, so with grouped=true it lives inside that book's books[] entry and follows the same single-book bridge as the DFS tags above.

Pinnacle rows with this validated observation metadata use last_observed for age_seconds and maxAgeSec. Their original quote time stays in last_update, so an unchanged price can remain freshly observed.

FanDuel native metadata: ?includeSids=true adds validated native selection IDs when available. ?includeLinks=true adds per-side add-to-betslip URLs only when the stored observation marked the market OPEN and runner ACTIVE. Some rows have no native metadata. A named single-outcome market follows its existing over_price slot; that slot does not mean the named outcome is an Over direction.

Polymarket / Kalshi event markets: ?bookmakers=polymarket (auto-includes event markets) or ?include_event_markets=true (any source). For a dedicated prediction-market endpoint with question text + event_url, use /v1/prediction-markets/{sport_key}.

Pagination headers (sleep_iter_7 #508): every response carries x-result-page-size, x-result-row-count, x-result-limit, x-result-offset, x-result-has-more. When x-result-has-more: true, the response also carries x-next-offset: <int> showing the offset to request for the next page. Use these to walk a large result set without truncating silently. The default limit of 5000 is fine for most queries; a full bet365 baseball_mlb response needs ~3 pages of 5000 to retrieve all available rows.

Completeness (x-result-degraded): when a book's own query fails while the board is being built, the response carries x-result-degraded listing those books and sets x-result-truncated: true. A failed deeper read retains earlier rows but leaves completeness unknown. If the page you asked for falls past the end of such a board, the response is 503 with Retry-After rather than an empty 200: a short board caused by a failed source is not the end of the result set, and no credits are charged for it.

Under load (X-Parlay-Stale: props_scan_busy): when a fresh board cannot be built in time, the response may instead be a recent board the serving process already built or served for the same query (by default at most five minutes old; another process may hold a newer one). It carries X-Parlay-Stale: props_scan_busy, X-Parlay-Stale-Built-At (ISO 8601 UTC) and X-Parlay-Stale-Age-Seconds, and costs the usual 3 credits. Every row keeps its own last_update and age_seconds; rows that aged past the 60-minute window since the board was built are left out, and maxAgeSec applies as usual. If no such board exists, or no row of it is left for the page you asked for (every row older than maxAgeSec, or offset past its end), the answer is still 503 with Retry-After, and no credits are charged.

Pagination with grouped=true: limit and offset count ROWS (one row per book) in both modes, so x-next-offset means the same thing either way. A grouped page therefore returns FEWER entries than limit - several rows collapse into one prop - and x-result-page-size (props returned) will sit below x-result-row-count (rows behind them). Trust x-result-has-more, not the entry count, to decide whether to ask for another page. A prop whose books straddle a page boundary arrives with a partial books[] on each page; merge pages on (event_id, player, market_key, line). To avoid that entirely, narrow with ?markets= / ?bookmakers= so the whole result fits in one page.

Returns over/under lines with American odds from each source.

get/v1/sports/{sport_key}/props

Request

  • Base URL: https://parlay-api.com
  • URL: https://parlay-api.com/v1/sports/{sport_key}/props
  • Auth: one of:
    • API key in header X-API-Key
    • API key in query parameter apiKey
    • HTTP bearer

Path parameters

sport_keystring required

Query parameters

marketsstring nullable

Comma-separated prop market keys (e.g. player_pass_yds,player_points)

Comma-separated prop market keys (e.g. player_pass_yds,player_points) Repeating this parameter is the same as the comma form: ?markets=h2h&markets=spreads and ?markets=h2h,spreads are one request, billed identically, and return the union. A value repeated across occurrences is counted once.

bookmakersstring nullable

Comma-separated bookmaker keys

Comma-separated bookmaker keys Repeating this parameter is the same as the comma form: ?markets=h2h&markets=spreads and ?markets=h2h,spreads are one request, billed identically, and return the union. A value repeated across occurrences is counted once.

playerstring nullable

Filter by player name (partial match)

eventIdstring nullable

Filter by event ID

oddsFormatstring
dfsOddsstring

DFS normalization for legacy flat-payout rows: 'midpoint' = +100/-100 (default, zero-vig), 'effective' = per-book implied. Explicit Pick6 offers ignore this option and return null American prices with available_sides and selection_by_side payout metadata.

limitinteger

Max rows returned (default 5000, max 10000)

offsetinteger

Page offset within the result set. Combine with limit for pagination. For results past 10000 rows, narrow via ?markets= or ?bookmakers= filters instead.

groupedboolean

Return one entry per prop with a books[] array (recommended) instead of one row per book

include_event_marketsboolean

Include futures and prediction-market rows that lack a single home/away_team (Polymarket yes/no questions, Underdog season-longs, etc). Auto-enabled when bookmakers includes 'polymarket'.

maxAgeSecinteger nullable

Only return prop rows with age_seconds within this bound. Pinnacle rows with validated last_observed use observation age; other rows use last_update write age. Rows with no parseable freshness clock are excluded. Omit to serve the full recency window (up to 3600s / 60 min).

includestring nullable

Accepted only as 'normalized', which is what this endpoint already returns. /props serves one shape, so any other token (for example 'raw' or 'slim') is rejected with 400 instead of being ignored. The shape tokens live on GET /v1/sports/{sport_key}/odds.

includeLinksboolean

Include validated FanDuel per-side betslip links when the stored observation marked the native market OPEN and runner ACTIVE.

includeSidsboolean

Include validated FanDuel per-side native selection IDs.

Response

Successful Response

unknown required

Changes

No recorded changes to this operation across all 1 revision of this API.