Every price move for a race, per runner per bookmaker, with the opening and closing line. Identify the race either by `race_id`, or by `venue` + `race_number` + `date` — use the latter for past races, because race ids are only resolvable from the live feed, which holds the next ~6 hours. **The series is change-only.** Each point is a price MOVE, not a sample: a gap means the price held steady. `move_pct` is open→close, positive meaning the price drifted out. **`open_price` and `close_price` are the first and last CAPTURED prices for that book, not guaranteed market open and close.** Capture starts when a race enters the 60-minute window, and a book that does not quote that early gets its first price whenever it starts quoting: measured over 30,448 series on 2026-08-15, 44% of series began at the 60-minute baseline and 56% began later. At the other end 63% of series have a final point inside 120s of the jump and 81% inside 300s, so the rest are not closing lines either. Read `open_secs_to_jump`, `close_secs_to_jump` and `open_is_baseline` on each bookmaker before using a series for closing-line value, and drop the ones that do not reach the jump. **History is permanent.** Races inside the ~45-day live window are served from the live store; older races come from the permanent archive, which is never purged. `history_from` on the response is the true floor — capture began 2026-08-04, and the archive only deepens from there. (Identify past races by `venue` + `race_number` + `date`; both stores resolve that key.)
X-API-Key
5 credits
curl 'https://api.puntersedge.online/v1/racing/price-history?race_id=YOUR_RACE_ID' \
-H 'X-API-Key: YOUR_KEY'
| Name | In | Type | Required | Description |
|---|---|---|---|---|
race_id |
query | string | no | Race id. If omitted, give venue + race_number + date. |
venue |
query | string | no | Venue name, case-insensitive (with race_number + date) |
race_number |
query | integer | no | |
date |
query | string | no | Race date, YYYY-MM-DD (UTC) |
bookmakers |
query | string | no | Comma-separated bookmaker keys, case-insensitive. An unrecognised key is a free 422 naming the valid keys, so a typo costs nothing — it used to return a billed empty response. |
include_points |
query | boolean | no | False returns open/close/high/low only |
max_points |
query | integer | no | Cap on returned points; response flags truncation |
Status codes: 200, 401, 402, 422, 429, 500. Response bodies are JSON; the full schema is in /openapi.json.
200 application/json
— this call costs 5 credits.
Field names and types are as the API returns them; values are a real sample, trimmed to a few items.
{
"category": "horse",
"country": "AU",
"history_from": "2026-08-04T09:22:00Z",
"points_returned": 2481,
"race_id": "race_123",
"race_number": 2,
"runners": [
{
"bookmakers": [
{
"close_price": 7.0,
"close_secs_to_jump": 41,
"high": 7.0,
"key": "sportsbet",
"low": 6.0,
"move_pct": 7.69,
"open_is_baseline": true,
"open_price": 6.5,
"open_secs_to_jump": 3595,
"points": [
{
"captured_at": "2026-08-15T02:00:04Z",
"secs_to_jump": 3595,
"win_price": 6.5
}
],
"points_count": 10
}
],
"name": "Aeolian",
"number": 4
}
],
"start_time": "2026-08-15T03:00:00Z",
"truncated": false,
"venue": "Caulfield"
}
GET /v1/racing/acceptances — Full-day AU thoroughbred acceptance card: every meeting, race and runnerGET /v1/racing/best-odds — Best racing price per runner across booksGET /v1/racing/changes — Races and prices that changed since a timestampPOST /v1/racing/clv — Score bets against the closing line (CLV)GET /v1/racing/events — Upcoming race listGET /v1/racing/form — Every runner in one race with its recent runs, from our own resultsGET /v1/racing/greyhounds/form — Greyhound form history for one dog, from our own resultsGET /v1/racing/greyhounds/stats — Greyhound record by track, distance, box or grade, from our own resultsThe free tier needs no credit card, and the sandbox endpoints need no key at all.
Get a free API key Quickstart