CLI
Install the CLI with uv tool install betflux for automatic updates on Linux
and macOS; see the installation guide.
pip install betflux also installs the CLI, without automatic
updates. Run betflux login to save a key for the CLI and Python SDK, or
supply BETFLUX_API_KEY. --api-key overrides the environment; --base-url
overrides the API host.
Updates
Section titled “Updates”On verified Linux and macOS uv tool install betflux installations, BetFlux
checks for updates before data commands about once per day and installs
an eligible stable release automatically. This may occasionally delay command
startup. The updater does not mutate project or pip installations, temporary
uvx runs, or installations it cannot verify. Use uv to install and own the
CLI environment. It preserves the installation’s version constraints and
package source; uv may also change dependency versions within those
constraints. Pinned installations update only when a compatible release is
available. uv upgrades are not atomic and do not roll back automatically. If
an upgrade leaves the tool unusable, repair it with
uv tool upgrade betflux --reinstall.
Set BETFLUX_NO_AUTO_UPDATE=1 to disable automatic updates for one process,
including in CI or scripts. Persistent preference and manual update commands
are available:
betflux auto-update statusbetflux auto-update offbetflux auto-update onbetflux update # check and install now, even if auto-update is offbetflux update --check # check onlyThese controls, --help, and --version do not trigger an automatic network
check. Automatic update progress is written to stderr; an unsuccessful
automatic check lets the requested command continue. Explicit update failures
return a nonzero status. Coordination applies to BetFlux launches in the same
verified tool installation; external package-manager operations and older
pre-updater processes are outside that coordination.
Only the CLI launcher performs these checks. Importing betflux or using the
Python SDK never triggers an update.
Browser login
Section titled “Browser login”Complete onboarding and activate API access on the website first, then run:
betflux login- The CLI opens your browser. If it doesn’t open automatically, navigate to the URL printed in your terminal.
- Sign in to your BetFlux account if prompted.
- The link fills in the code automatically, including after signing in. Confirm it matches your terminal and select Approve access. If you open the activation page without the link, enter the code manually.
- When the website shows App access approved, return to your terminal. Wait for Signed in. API key saved. CLI commands and Python clients will now automatically use it, unless you supply another key explicitly.
Verify your connection:
betflux keys checkCodes expire after ten minutes. If a code is invalid, expired, or already used,
run betflux login again to get a new one. Each login uses an account API key slot; you don’t need to log in before every command.
The key is saved in your system keychain. On a headless machine, explicitly
choose protected file storage with --credential-store file; add --no-browser
to print the link without launching a browser. The key uses the CLI’s default
name; use --name when starting login to choose a different name.
CLI credential priority is --api-key, BETFLUX_API_KEY, --api-key-file,
then saved login. Saved keys are isolated by API URL. Custom API URLs require
an explicit website origin through login --auth-url or BETFLUX_AUTH_URL.
betflux logout # revoke the saved key and remove local loginbetflux logout --local-only # remove local login without server revocationLogout operates only on the saved key. It retains the credential if revocation cannot be confirmed, so you can retry. Revoked keys can remain cached at the API edge for up to five minutes.
If saved login is unreadable, unlock your keychain and retry. To reset broken
metadata or switch away from an unavailable keychain, run betflux logout --local-only, then betflux login --credential-store file. For a custom API,
pass the same --base-url before both commands and provide --auth-url for login.
Local-only logout does not revoke the server key; revoke it from your
account keys separately. If the CLI warns
that a keychain entry may remain, remove it when the keychain is accessible.
Common commands
Section titled “Common commands”betflux keys check # plan, limits and the period's games via GET /v1/mebetflux usage # the same standing; `betflux usage games` lists the counted gamesbetflux datasetsbetflux leaguesbetflux teams --league NBAbetflux players --league NBA --team-id <team-uuid>betflux games --league NBA --date-from 2026-05-01 --date-to 2026-05-07 --costbetflux games --id NBA_ORL_DET_20260503 --format recordbetflux get closing-lines --league NBA --date-from 2026-05-01 --date-to 2026-05-07 --dry-runbetflux get closing-lines --league NBA --date-from 2026-05-01 --date-to 2026-05-07betflux get market-results --game MLB_BOS_NYY_20260715 --outcome WONbetflux get sportsbook-lines --game MLB_BOS_NYY_20260715 --output lines.parquetbetflux get game-state-timeline --game NBA_ORL_DET_20260503betflux get
Section titled “betflux get”betflux get <dataset> queries one of the four datasets. The payloads are
per-game Parquet files; the CLI downloads them and evaluates filters and
rendering locally.
| Dataset | Addressing |
|---|---|
closing-lines, market-results |
Date range (--league --date-from --date-to) or --game |
game-state-timeline, sportsbook-lines |
--game only |
sportsbook-lines is --game-only by policy, not shape: one game’s file is
the full change-only line history and runs to tens of megabytes, so a range
pull would download that for every game in the window. The CLI says so if
you try. Cost is per game, the same for every dataset: once a game is
counted, all of its datasets are free for the rest of the period.
| Option | Meaning |
|---|---|
--league, --date-from, --date-to |
Range query (ET game_date, inclusive); the CLI discovers games via /v1/games, previews what they would cost, and fetches each game’s file |
--game <id> |
One game by id |
--dry-run |
Range queries: print the preview — how many games are new, already counted, exempt, outside the free sample or invalid, and whether they fit — and stop without downloading (JSON with --format json) |
--allow-partial |
Range queries: when the pull would exceed the allowance, read the games that fit instead of aborting |
--quiet |
Silence the games usage line printed to stderr after a read |
--operator, --market-type, --team, --player-id, --side |
Local filters — applied after download, so they don’t change what a game costs |
--outcome |
market-results only: WON, LOST, PUSH, INDETERMINATE |
--limit N |
Range queries: stop after N rows — no further game files are fetched, so no further games are counted |
--output PATH |
With --game: save the raw Parquet file instead of rendering rows |
--no-progress |
Suppress the progress display (also BETFLUX_NO_PROGRESS=1) |
A date-range get previews its cost first and aborts before downloading
anything when the pull would go over the allowance, naming how many games are
over and how many fit. After get, live-board and live-tail, one stderr
line reports what the read cost and what is left, in the form
games: N new, M already counted · X of Y left · resets YYYY-MM-DD
(--quiet silences it).
--player-id matches either player-ID list on closing-lines, market-results,
and sportsbook-lines. Rows that match both lists are returned once.
A filter the dataset has no column for is rejected up front, and flag
combinations the request would ignore (e.g. --output with filters) are
errors rather than silent no-ops.
While a get runs interactively, progress renders to stderr: game
discovery, a per-game bar for range pulls, per-file byte progress, and any
retry waits (rate limits, transient server errors). stdout carries only the
result, so piping or redirecting jsonl/csv output stays byte-clean; when
stderr is not a terminal the display turns off automatically.
Saving raw files: --output
Section titled “Saving raw files: --output”$ betflux get sportsbook-lines --game MLB_BOS_NYY_20260715 --output lines.parquetwrote lines.parquet — sportsbook-lines for MLB_BOS_NYY_20260715: <rows> rows, <bytes> bytesThe bytes are written untouched — the same artifact curl would save — so
the file is immediately queryable with DuckDB, pyarrow, pandas, or polars.
Output formats
Section titled “Output formats”Rendering is entirely client-side. The default is a compact table showing a curated column subset (the datasets are wide). Reshape it:
| Flag | Effect |
|---|---|
--wide |
Table with every column |
--columns game_date,operator,side,closing_odds |
Pick exact columns |
--format record |
Vertical key: value blocks — ideal for one wide row |
--format json|jsonl|csv |
Machine formats, always full-fidelity |
Table and record views are display projections only; json, jsonl, and
csv always carry every column. With --format jsonl|csv on a range query,
rows stream as each game’s file arrives instead of waiting for the whole
window. Timestamps render as ISO 8601 in every format.
betflux get closing-lines --game NBA_ORL_DET_20260503 --format jsonl > lines.jsonlReference data: games, leagues, teams, players
Section titled “Reference data: games, leagues, teams, players”The JSON reference data that the datasets
key on. All four render through the same --format / --columns controls as
get; json, jsonl, and csv always carry every field.
betflux games --league NBA --date-from 2026-05-01 --date-to 2026-05-07betflux games --league NFL --status STARTED --columns id,away_score,home_score,current_periodbetflux games --id NBA_ORL_DET_20260503 --format record| Command | Options |
|---|---|
betflux games |
--league, --date-from / --date-to (ET game date, inclusive, paired), --team (canonical name, home or away), --status; or --id <game_id> alone. --wide shows every column; --cost adds a free_to_read column (true for a game already counted or exempt this period) at the price of one preview call |
betflux leagues |
none |
betflux teams |
--league |
betflux players |
--league and/or --team-id <team-uuid> |
A game row is the full record — schedule,
teams, score, venue, weather. The default table is a curated subset (id, date,
start, status, teams, score, venue, weather type); --wide, --columns, or
--format record show the rest.
betflux keys check and betflux usage
Section titled “betflux keys check and betflux usage”betflux keys check validates the key against GET /v1/me and prints your
standing — the plan, the period’s games (used, allowance, left, reset) and
the plan’s limits (recent-game window, live, league datasets) — and it works
even when the allowance is spent. Every number comes from the key at runtime;
--json prints the raw /v1/me body for scripts and agents to parse.
betflux usage # the same standingbetflux usage games # games counted or exempt this period, newest read firstbetflux usage games --league NFL --from 2026-09-01 --to 2026-09-30 --jsonEvery game usage games lists is free to read again, in any dataset, until
the period resets, and listing them counts nothing. See
Rate limits & quotas for the
counting rules.