Skip to content
Product Documentation

CLI

Install the CLI with uv tool install betflux for automatic updates on Linux and macOS. pip install betflux also installs the CLI, without automatic updates. It reads BETFLUX_API_KEY (override with --api-key; --base-url overrides the host).

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:

Terminal window
betflux auto-update status
betflux auto-update off
betflux auto-update on
betflux update # check and install now, even if auto-update is off
betflux update --check # check only

These 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.

Terminal window
betflux keys check # tier, rate limit, and monthly usage via GET /v1/me
betflux datasets
betflux leagues
betflux teams --league NBA
betflux players --league NBA --team-id <team-uuid>
betflux games --league NBA --date-from 2026-04-01 --date-to 2026-04-07
betflux games --id NBA_GSW_MIA_20260401
betflux get closing-lines --league NBA --date-from 2026-04-01 --date-to 2026-04-07
betflux get market-results --game MLB_BOS_NYY_20260715 --outcome WON
betflux get sportsbook-lines --game MLB_BOS_NYY_20260715 --output lines.parquet
betflux get game-state-timeline --game NBA_GSW_MIA_20260401

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: quota is debited per file downloaded, and one game is ~190k rows — a range pull would debit that for every game in the window. The CLI says so if you try.

Option Meaning
--league, --date-from, --date-to Range query (ET game_date, inclusive); the CLI discovers games via /v1/games and fetches each game’s file
--game <id> One game (public id)
--operator, --market-type, --team, --player-id, --side Local filters — applied after download, so they don’t reduce quota spend
--outcome market-results only: WON, LOST, PUSH, INDETERMINATE
--limit N Range queries: stop after N rows — no further game files are fetched, so it caps quota spend too
--output PATH With --game: save the raw Parquet file instead of rendering rows
--no-progress Suppress the progress display (also BETFLUX_NO_PROGRESS=1)

--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.

Terminal window
$ betflux get sportsbook-lines --game MLB_BOS_NYY_20260715 --output lines.parquet
wrote lines.parquet — sportsbook-lines for MLB_BOS_NYY_20260715: 190,412 rows, ... bytes

The bytes are written untouched — the same artifact curl would save — so the file is immediately queryable with DuckDB, pyarrow, pandas, or polars.

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.

Terminal window
betflux get closing-lines --game NBA_GSW_MIA_20260401 --format jsonl > lines.jsonl

Validates the key against GET /v1/me and prints your standing — it works even when your monthly quota is spent:

key valid (https://api.betflux.ai)
tier: Beta — 120 requests/min
usage: 12,345 rows this month (no row cap on this plan)

Tiers with a configured row cap also see the percentage used and the reset date.