18+ Only  |  Gambling can be addictive — please gamble responsibly  |  Gambling Help: 1800 858 858  |  GambleAware

API reference / Racing Archive

GET /v1/racing/closing-lines

Permanent closing-line and result archive

The permanent closing-line archive: one row per race, runner and bookmaker, carrying the last price seen before the jump, the first price seen after the market opened, and the finishing position where one is known. **Plans.** Every paid tier from Standard (A$29) upward reads the whole archive; `window_days` comes back null for them. Free and Hobby get a 403. Legacy `starter`, `pro` and `growth` keys keep full access but cannot be bought — Starter was retired from checkout on 2026-08-22, `pro` on 2026-08-12 and `growth` on 2026-08-15. No tier is currently clamped; `window_days` is non-null only if a rolling-window tier is reintroduced. **This is not the same data as `/v1/racing/price-history`.** That endpoint reads the live 45-day snapshot store and returns every price move for one race. This one reads a separate, permanent table and returns one collapsed row per series across any date range. Price history disappears at 45 days; the archive does not. **Read the flags before you model on this.** Measured 2026-08-18 over 348,889 archived series: * `is_closing_line` — only 85.5% of series have their final observation within 300s of the jump. The rest stopped being quoted early and their close is a last-seen price. Filtered in by default. * `open_is_baseline` — only 42.5% of series start at the 60-minute window entry. The rest joined mid-window, so their "open" is not a market open. * `finish_position` **NULL does not mean the runner lost.** `race_results.placings` carries only the placegetters, so most runners in a fully resulted race have no published position. Check `result_status`: NULL there means the race has no result at all. * `venue_split_suspect` / `name_fragment_suspect` — the archive's record of its own known contamination. Excluded by default. **Result coverage is thin and forward-growing.** The results feed began on 2026-08-15 and is AU/NZ only, so on 2026-08-18 only 5.3% of archived races carry a result. `resulted_rows` on the response is the measured count for your actual selection, not a marketing figure. **`runner_ref` is the join key** (last column, since 2026-09-05). The stable registry id for the runner — `ra:<horsecode>` for thoroughbreds, `grv:<dogId>` for greyhounds — the same value `/v1/racing/results` carries on every `runners[]` entry and `/v1/racing/horses/form` accepts, so an archive row joins to its result and to the horse's form without matching names. Filled from Racing Australia acceptances for AU thoroughbreds and from the result itself for every code once it lands, so it can be null on a row whose race has not resulted yet, on harness (no registry feed), and on rows archived before the identifiers existed (late August 2026). Appended after `venue_site` so positional CSV readers keep working. Betfair Exchange rows are withheld from customer responses pending a data licence, so `close_lay_price` — which only an exchange quotes — is NULL for customers. **Dates.** `from`/`to` bound the range. `date=YYYY-MM-DD` is a convenience alias for a single day and is exactly `from=YYYY-MM-DD&to=YYYY-MM-DD`; it exists because `/v1/racing/events` takes `date` and callers reasonably expect the same spelling here. Passing `date` together with `from` or `to` is a free 422 rather than a silent precedence rule. An unknown bookmaker key, an unknown parameter, a reversed date range or a bad date is an error and costs nothing.

Requires X-API-Key 5 credits (JSON) / 20 credits (CSV)

Request

curl 'https://api.puntersedge.online/v1/racing/closing-lines?from=2026-08-10&to=2026-08-17&category=horse&format=csv' \
  -H 'X-API-Key: YOUR_KEY'

Parameters

NameIn TypeRequired Description
from query string no ISO date/time on the race start. Defaults to the archive floor.
to query string no ISO date/time. Defaults to now.
date query string no Single-day alias: date=YYYY-MM-DD is exactly from=YYYY-MM-DD&to=YYYY-MM-DD. Mutually exclusive with from/to. Also accepted by /v1/racing/results. NOT by /v1/racing/events, which is forward-looking and takes hours_ahead — this line claimed it did until 2026-08-25, and that false claim is how a Racing subscriber learned to send date= to /results, where it was undeclared and silently dropped for 143 requests.
venue query string no Venue name, case-insensitive, exact match.
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.
category query string no horse, harness or greyhound
country query string no Two-letter country code, e.g. AU, NZ
race_id query string no Single race, joinable to /v1/racing/price-history while that race is still inside the 45-day snapshot window.
closing_only query boolean no Only rows whose last observation was within 300s of the jump. True by default because 14.5% of series are NOT closing lines and silently mixing them in is how a CLV study goes wrong.
resulted_only query boolean no Only rows from races that have a result.
include_flagged query boolean no Include rows flagged venue_split_suspect or name_fragment_suspect. False by default; set true if you want the contaminated rows and intend to handle them.
format query string no csv streams a flat table with a stable column order — the format a modeller actually wants.
limit query integer no
offset query integer no

Responses

Status codes: 200, 401, 402, 422, 429, 500. Response bodies are JSON; the full schema is in /openapi.json.

Example response

200 application/json — this call costs 5 credits (JSON) / 20 credits (CSV). Field names and types are as the API returns them; values are a real sample, trimmed to a few items.

{
  "archive_from": "2026-08-04T09:20:44Z",
  "limit": 500,
  "offset": 0,
  "resulted_rows": 640,
  "rows": [
    {
      "bookmaker_key": "sportsbet",
      "category": "horse",
      "close_secs_to_jump": 41,
      "close_win_price": 7.0,
      "country": "AU",
      "finish_position": 2,
      "is_closing_line": true,
      "meeting_date_aet": "2026-08-15",
      "name_fragment_suspect": false,
      "open_is_baseline": true,
      "open_secs_to_jump": 3595,
      "open_win_price": 6.5,
      "points_observed": 10,
      "race_id": "race_123",
      "race_number": 2,
      "result_status": "final",
      "runner_key": "aeolian",
      "runner_name": "Aeolian",
      "runner_number": 4,
      "runner_ref": "ra:2098765",
      "start_time": "2026-08-15T03:00:00Z",
      "venue": "Caulfield",
      "venue_id": "caulfield",
      "venue_site": "caulfield",
      "venue_split_suspect": false
    }
  ],
  "rows_returned": 1,
  "total_rows": 12480
}

Related endpoints

Try it against live data

The free tier needs no credit card, and the sandbox endpoints need no key at all.

Get a free API key Quickstart
This site contains wagering-related analysis and is intended for Australian users aged 18+. Gambling involves risk. Please gamble responsibly.