game-state-timeline
Our estimate of a game’s state over wall-clock time: score, period, clock
and, by league, the MLB half-inning and outs or the NFL down, distance and
possession. We estimate it from every source we hold (MySportsFeeds,
DraftKings, BetMGM and Pinnacle), and each field carries a confidence measured
against independent play-by-play. Join it to odds records (e.g.
sportsbook-lines timestamp) to estimate the game situation behind any line
move.
Fetching
Section titled “Fetching”curl -s "https://api.betflux.ai/v1/games/NBA_ORL_DET_20260503/game-state-timeline" \ -H "Authorization: Bearer $BETFLUX_API_KEY" -o timeline.parquetbetflux get game-state-timeline --game NBA_ORL_DET_20260503Per-game only — the grain is the game, so there are no date-range pulls. Beta access includes all available game artifacts.
Row shape
Section titled “Row shape”One row each time the state changes, and one every 10 seconds while the
clock runs. A row holds until the next row’s ts, so join on it as of a
time:
SELECT l.timestamp, l.odds, s.home_score, s.away_score, s.period_number, s.clock_seconds_remainingFROM read_parquet('lines.parquet') lASOF JOIN read_parquet('timeline.parquet') s ON l.game_id = s.game_id AND l.timestamp >= s.ts- Columns that do not apply to the league are null (
mlb_*outside MLB,nfl_*outside the NFL, the clock in MLB). - From about 30 seconds after each report we run the clock on. When the next report shows the clock had stopped (a timeout, a score), the clock can step back up by up to about 30 seconds.
<field>_confidenceis the calibrated probability that the value is exactly right, given how recently a source reported it.clock_seconds_remaining_p90_erroris the clock’s error in seconds at the 90th percentile.- Before the first source reports, there is no row: a line from before then joins to nothing.
What a row describes
Section titled “What a row describes”A row is our best estimate of the state that was true at ts. Sources
report with a delay, so the estimate uses reports that arrived after ts,
including the game’s full play-by-play, which can come minutes or hours
later. It is the right view for explaining a line move. It is not what was
knowable at ts: before backtesting a strategy that reacts to the game
state, allow for that delay.
How often each estimate is right, measured on 119 recent games (autumn 2026) against independent play-by-play. None of these games were used to tune the estimates:
| League | Both scores | Period | Clock within ±30 s | Other |
|---|---|---|---|---|
| MLB | 99% | 99.8% | — | half-inning 99%, outs 62% |
| NBA | 76% | 97% | 89% | — |
| NHL | 98% | 99.7% | 95% | — |
| NFL | 97% | 98% | 94% | down 78%, possession 96% |
Games from late September 2026 on also carry BetMGM’s live scoreboard, which lifts MLB outs to about 95%, NFL down to about 84% and NBA both scores to about 78% on the games we could measure. NBA scores change every few seconds and our sources report them 10–30 seconds late, so expect the score to trail the true score briefly after some baskets.
Columns
Section titled “Columns”| Column | Type | Nullable | Description |
|---|---|---|---|
game_id | string | no | Game id: LEAGUE_AWAY_HOME_YYYYMMDD (ET date; `_2` suffix for the second game of a doubleheader). |
league | string | no | League code: MLB, NBA, NHL or NFL. |
game_date | string | no | Calendar date of the scheduled start in US Eastern time. |
ts | string | no | When this state began. It holds until the next row's ts, so as-of join on it (DuckDB `ASOF JOIN ... ON l.timestamp >= s.ts`). It is the best estimate of when the state was true, built with reports that arrived later (including the game's full play-by-play), so it is not what was knowable at that moment. |
home_score | integer | yes | |
home_score_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
away_score | integer | yes | |
away_score_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
period_number | integer | yes | Quarter (NBA, NFL), period (NHL) or inning (MLB); null between games and once no source has reported it for 30 minutes, as after the final. |
period_number_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
clock_seconds_remaining | integer | yes | Seconds left on the game clock in the period (NBA, NHL, NFL); null for MLB. From about 30 seconds after each report we run the clock on, so it can step back up by up to about 30 seconds when a report shows the clock had stopped. |
clock_seconds_remaining_p90_error | number | yes | The clock is within this many seconds of the true clock 90% of the time. |
mlb_inning_half | string | yes | TOP or BOTTOM. |
mlb_inning_half_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
mlb_outs | integer | yes | Outs in the half-inning. No source reports outs promptly, so expect a low confidence. |
mlb_outs_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
nfl_down | integer | yes | Down, 1–4; null at kickoffs and tries. |
nfl_down_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
nfl_yards_remaining | integer | yes | Yards to go for a first down. |
nfl_yards_remaining_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
nfl_possessing_team_side | string | yes | HOME or AWAY: the team with the ball. |
nfl_possessing_team_side_confidence | number | yes | Calibrated probability that the value is exactly right, measured against independent play-by-play; null when the value is null. |
dataset_version | string | yes | Version of the dataset this game's file was built at, e.g. `v5`. Games in one pull can differ: versions of a compatibility line only add columns or carry documented changes (see `versions` on /v1/datasets). Columns added after a game's version read null for it. Files built before this column existed lack it entirely (null when read with DuckDB `union_by_name = true`); the `X-Betflux-Dataset-Version` response header still names their version. |
Coverage
Section titled “Coverage”MLB, NBA, NHL, and NFL (no NCAAM or NCAAF). Before version v3 the dataset
served each source’s raw observations (ts, field, value, source); see
versions on /v1/datasets.