Bulk export of the permanent price-movement archive
Cost: 5 credits (JSON) / 20 credits (CSV). Every OBSERVED PRICE POINT in the permanent movement archive: one row per race, runner, bookmaker and captured price, from market open to the last pre-jump quote.
This is the bulk, downloadable form of /v1/racing/price-history. That endpoint answers for one race; this one exports a date range as a flat table (CSV loads straight into pandas — pd.read_csv(url) with your key in the header; format=parquet returns the same table typed, pd.read_parquet(BytesIO(r.content))). The archive is permanent: nothing here ages out, and coverage runs from archive_from (capture began 2026-08-04) forward, forever.
The series is change-only. Each row is a price MOVE, not a fixed-interval sample — a gap between two points means the price held. To build T-snapshots (T-60/30/15/5/2), take the last row at or before each mark per (race_id, runner_key, bookmaker_key).
Window guard. Points run ~9x the series rows, so a request without race_id is capped at a 7-day from/to window per call — page a season week by week. A reversed or over-wide range is a free 422.
runner_ref (the column after venue_site, since 2026-09-05) is the registry id stored on the row — ra:<horsecode> for thoroughbreds, grv:<dogId> for greyhounds — identical to the runner_ref on /v1/racing/results runners[] entries, on /v1/racing/closing-lines and /v1/racing/markets, and on the live board on race day, so every point in this export joins to its result and to the race's other rows on one key. Null where no registry id is known: harness, rows archived before late August 2026, and a race whose result has not landed and whose acceptance list we did not hold. On a thoroughbred it is the code Racing Australia published on race day, not the horse: Racing Australia issues a new code for the same horse each day, so it changes from meeting to meeting. A greyhound's does not — grv:/grsa: are per-dog registry ids.
horse_ref (the column after runner_ref, added 2026-09-21) is the horse identity this export was missing: pe:<name>, the registered name folded to letters and digits (trailing country parenthetical removed). Derived at serve time from runner_name rather than stored, so every point ever archived carries it from today, and appended after runner_ref so no positional reader moves. Group a horse's whole price history on it — across meetings, tracks and seasons — and use runner_ref to join the rows about one race. Null on greyhound and harness rows.
place_price (LAST column, added 2026-09-29) is the book's PLACE price at that point. NULL on every point archived before 2026-09-29 and at books that quote no place price. A point is written when the WIN (or exchange lay) price moves — a place-only move does not create one — so it is the place price at each win move, not a separate place series.
top2_price, top3_price, top4_price (LAST three columns, added 2026-10-05) are the book's Same Race Multi Top 2 / Top 3 / Top 4 price at that point, on the same win-move cadence. Only sportsbet, ladbrokes_au, neds and pointsbetau publish them — NULL at every other book — and NULL on every point before 2026-09-29.
Plans. Plus and above, and Standard keys issued before 2026-09-20. Any other key gets a free 403 that carries a sample: the last five moves in one book's price for the winner of one recent race, as rows of this export.
Betfair Exchange rows are withheld pending a data licence, so lay_price — which only an exchange quotes — is NULL for customers. BSP and traded volume are absent for the same reason; when a licence lands they will arrive as new columns, not a changed contract.
Request
- Base URL: https://api.puntersedge.online
- URL: https://api.puntersedge.online/v1/racing/price-paths
- Auth: API key in header X-API-Key
Query parameters
ISO date/time on the race start.
ISO date/time.
Single-day alias: date=YYYY-MM-DD is exactly from=YYYY-MM-DD&to=YYYY-MM-DD. Mutually exclusive with from/to.
Venue name, case-insensitive, exact match.
Comma-separated bookmaker keys, case-insensitive. An unrecognised key is a free 422 naming the valid keys.
horse, harness or greyhound — comma-separated for more than one. categories= is accepted as an alias (2026-09-24); an unknown value is a free 422.
Alias of category. Comma-separated horse, harness, greyhound. Both spellings are accepted on every racing endpoint.
Two-letter country code, case-insensitive; comma-separated for more than one, e.g. AU, or GB,IE for British and Irish racing.
Single race. With race_id the window guard does not apply.
Include rows flagged venue_split_suspect or name_fragment_suspect. False by default.
csv streams a flat table with a stable column order — the bulk download this endpoint exists for. parquet returns the same table, same column order, as one Apache Parquet file with typed columns (UTC timestamps, a date, float64 prices) — pd.read_parquet(BytesIO(r.content)). Same credit cost and row cap as csv.
Headers
Response
Successful Response
Changes
No recorded changes to this operation across all 1 revision of this API.