Skip to content
Product Documentation

closing-lines

One row per (game, operator, market, selection, side): where the side opened, where it closed, how much it moved, and book-only CLV. Built from change-only odds records observed from scrape start through game end. One row per priced selection id per side — ≈ 12,000 rows for an MLB game with full props coverage — the compact, analysis-ready summary of a game’s odds; reach for sportsbook-lines when you need every intermediate move.

Terminal window
curl -s "https://api.betflux.ai/v1/games/NBA_GSW_MIA_20260401/closing-lines" \
-H "Authorization: Bearer $BETFLUX_API_KEY" -o closing.parquet

One Parquet file per game. Date-range queries are a client-side loop over /v1/games — the CLI and SDK do it for you, with local filters (operator, market_type, team, player_id, side):

Terminal window
betflux get closing-lines --league NBA \
--date-from 2026-04-01 --date-to 2026-04-07 --operator FANDUEL
  • One row per selection id per side: market_key (= OPERATOR:market_external_id) and selection_external_id identify the market and selection by the operator’s own ids, so two markets or two players that share a name never share a row — see Market identity.
  • Books that mint a new selection id per line value (DraftKings, BetMGM, Pinnacle, FanDuel alternates) show a moved line as a new row whose opening equals its closing. To get DraftKings’ main-line close for a side, take the row with the latest closing_ts among the market’s rows for that side — a heuristic until a line-stable key ships. FanDuel main markets keep one id, so that row’s opening → closing is the whole pre-game move.
  • Opening = first observed record for the side. Closing = the latest eligible quote strictly before game_start: both the market and selection must be explicitly active, prices must be valid, and a recognized market must have its required selection values and compatible sides. Its observed market meaning must also agree with the closing classification; an earlier points quote cannot become a rebounds quote or another player’s quote through relabeling. Missing or unknown status does not establish an active quote.
  • A closing quote’s price, applicable spread/total, and timestamp come from the same observation. A later suspended or incomplete observation does not replace it, and an old threshold is never combined with a newer price.
  • If no eligible pre-game quote exists, all closing columns are null, including for live-only or all-suspended histories. The row, opening observation, and history statistics remain present. Unclassified and excluded markets can retain active priced quotes, but their unknown dimensions are not inferred.
  • Odds come in three encodings per snapshot: American (*_odds), decimal (*_decimal), and implied probability (*_implied, vig included).
  • line_move_count counts odds changes between consecutive records; min_odds/max_odds/distinct_odds_count span all records including live ones.
  • clv_odds / clv_implied compare the side’s own open to its own close. They are null if either price is unavailable or the opening observation’s market meaning or selection identity is incompatible with the close — see Core concepts.
  • scope is reserved and always null.
ColumnTypeNullableDescription
game_idstringnoPublic game id: LEAGUE_AWAY_HOME_YYYYMMDD (ET date; `_2` suffix for the second game of a doubleheader).
leaguestringnoLeague code, e.g. NBA, NFL, MLB, NHL, NCAAM.
game_datestringnoCalendar date of the scheduled start in US Eastern time (YYYY-MM-DD).
game_startstringnoScheduled start time, ISO-8601 UTC.
home_teamstringnoCanonical home team name.
away_teamstringnoCanonical away team name.
operatorstringnoSportsbook operator code, e.g. FANDUEL, DRAFTKINGS, PINNACLE.
market_typestringnoMarket classification, e.g. SPREAD, MONEYLINE, TOTAL, PLAYER_METRIC_OVER_UNDER. A classification, not an identity: a book can offer several markets of one type (main + alternate lines, one per player).
periodstringnoGame segment the market covers, e.g. the full game, a half, or a quarter.
scopestringyesReserved for future market scoping; always null.
market_keystringnoGlobal market identity: `OPERATOR:market_external_id` — the operator code plus the operator's own market id. Join key across closing-lines, market-results and sportsbook-lines.
selection_namestringyesOperator's label for the selection (e.g. a player for prop markets, `Over`); display only — shared across selections, never an identity. Null for plain team markets.
sidestringnoPriced side within the selection, e.g. HOME, AWAY, OVER, UNDER.
opening_oddsintegeryesAmerican odds of the first observed record for this side.
opening_decimalnumberyesDecimal odds at open.
opening_impliednumberyesImplied probability at open (vig included, 0-1).
opening_spreadnumberyesPoint spread (handicap) at open; null for non-spread markets.
opening_totalnumberyesTotal (over/under line) at open; null for non-total markets.
opening_tsstringyesTimestamp of the first observed record, ISO-8601 UTC.
closing_oddsintegeryesAmerican odds of the last eligible active quote strictly before game_start; null when no eligible pre-game quote exists.
closing_decimalnumberyesDecimal odds at close.
closing_impliednumberyesImplied probability at close (vig included, 0-1).
closing_spreadnumberyesPoint spread (handicap) at close.
closing_totalnumberyesTotal (over/under line) at close.
closing_tsstringyesTimestamp of the last eligible active pre-game quote, ISO-8601 UTC; null when no eligible pre-game quote exists.
min_oddsintegeryesLowest American odds observed across all records, pre-game and live.
max_oddsintegeryesHighest American odds observed across all records, pre-game and live.
distinct_odds_countintegeryesNumber of distinct American-odds values observed.
line_move_countintegeryesNumber of records where the odds changed from the previous record.
pre_game_recordsintegeryesChange-only records observed before game_start.
live_recordsintegeryesChange-only records observed at or after game_start.
first_seen_atstringyesTimestamp this side was first observed, ISO-8601 UTC.
last_seen_atstringyesTimestamp this side was last observed (including live), ISO-8601 UTC.
clv_oddsintegeryesclosing_odds - opening_odds in American odds; null when either is missing or the opening and closing market meanings are incompatible.
clv_impliednumberyesopening_implied - closing_implied; null when either is missing or the opening and closing market meanings are incompatible.
market_player_idsstring[]yesPlayer UUIDs referenced by the market, as of the closing record.
selection_player_idsstring[]yesPlayer UUIDs referenced by the selection, as of the closing record.
market_metricstring[]yesStructured stat metric(s) the market prices (SportsMetric enum, e.g. FOOTBALL_RECEIVING_YARDS); null for non-player-metric markets. Join key for prop analysis — no name parsing needed (adr-0027).
selection_metricstringyesStructured metric for the priced selection; set only for method-of-score selections, else null.
market_external_idstringnoOperator's market id — the identity of the market within (game, operator); `market_key` is `operator` + `:` + this value. Same value as `market_external_id` on market-results and sportsbook-lines.
market_namestringyesOperator's market label, e.g. `Run Line Alternate`; display only.
selection_external_idstringnoOperator's selection id — the row identity together with `market_key` and `side`. For FanDuel main markets it is stable and the line moves on it (one row, opening → closing). DraftKings, BetMGM, Pinnacle and FanDuel alternates mint a new id per line value, so one market carries several rows per side and a moved line is a new row with opening == closing.