Skip to main content
Each odds line is identified by (period, market, line) and carries a stable integer line_id.

Market types

For 2-way markets (spread/totals), odds0 is null.

units — the line’s unit (tennis: games vs sets)

Some sports price the same market in two different units. In tennis, a spread can be a set handicap (line ±1.5) or a game handicap (line -4.5, +5.5…), and a totals can cover sets (2.5) or games (21.5). The units field removes the ambiguity: Tennis per-player totals (home_totals / away_totals) are always in games (units = "Games"). The field is present on /api/odds, /api/opening, /api/closing, /api/history and the real-time streams.

Periods

period = 0 = full match. Other periods depend on the sport (1 = first half / set, etc.). Fetch the catalog via /api/periods.

Main lines vs alt-lines

By default, /api/odds returns all lines (including alternatives). Add main_lines_only=1 to keep only the main line of each market (null alt_line_id).

max_win

max_win = maximum accepted stake (Pinnacle limit) on the line, a liquidity indicator.

History: max_win and status are series points

/api/history returns one point per actual change, never a repeated value. A point is created as soon as any of these fields moves: A max_win going up while the price stays put is a confidence signal from the book; a collapsing max_win often precedes a suspension. The series is already de-duplicated server-side, so it can be plotted as-is.

Isolating a single bet

Without a filter, /api/history returns the timeline of every line in the match. On a basketball game with its alt-lines, that routinely exceeds 24,000 points spread across more than 400 bets — when all you wanted was one curve. Two ways to name the bet, depending on what you already have:
For a market without a line (moneyline), pass line=null or line=. Omitting the parameter means “no filter on the line” — you would also get every handicap.
The filters apply to opening and closing too: you get the opening and closing of the bet you asked for, not those of the other 414. Measured on a real match:

The three levels of status

Pinnacle publishes a status at three different scales, each with its own vocabulary. Confusing them is the most common mistake: a closed market does not mean a finished match, and a settled half does not close betting on the full game.

Line level

Status belongs to the line, not the market. Within the same (event_id, period, market), rungs of the ladder diverge — Pinnacle closes one specific total while keeping its neighbours open:
Two fields describe it: status, a BIC-parity integer (1 = open, 2 = everything else), and status_raw, the word exactly as Pinnacle sends it.
status_raw is only populated on current prices. History (/api/history, full_history=1) stores the integer only: the original word is not kept, so the field is null there.

Period level

/api/fixtures exposes periods, a list of {period, status, cutoff}. This is where Pinnacle declares that a half is closed, independently of the lines and of the match state:
A period settling is an event in its own right on the stream: a half flipping to settled triggers an event: update frame, with no price needing to move.
Here the first half is settled while the full match is still open for betting.

Telling a suspension from a definitive close

No field says it — time does:
  • suspension — the line stays published, flips to closed, keeps its last known price (we do not erase it, just as the Pinnacle interface greys the price out), then returns to open;
  • definitive close — the line stops being republished: its cutoff passes, it leaves /api/odds, and a removal is announced on the stream (see Pre-match & live).
Across 327,832 statuses observed continuously on the feed, status_raw only ever takes the values "open" and "closed" — a tennis suspension between two points also arrives as "closed". Do not rely on a dedicated word to tell the two apart; this measurement covers an observation window, not a contractual guarantee from Pinnacle.