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

API reference / Racing

GET /v1/racing/horses/form

Thoroughbred form, career record and profile for one horse

One AU thoroughbred's recent form, career record and profile, parsed from Racing Australia's public horse page — the registry's own data. SOURCE AND FRESHNESS. The horse's page is read on demand and the parsed result stored (`source.fetched_at` dates it), so the first query for a horse pays a page-read to RA (typically under two seconds) and later reads are instant. A horse's form only changes when it races or trials, so the stored copy is re-read from RA only when our own results archive shows the horse has started since it was read, or when the copy is more than seven days old (a barrier trial is invisible to results, so it surfaces within a week at worst). Inside six hours it is served without even that check. A horse collected once, by you or by anyone, is therefore served from our store without another RA read for as long as it stays unraced. When RA cannot be reached and a stored copy exists, that copy is served with `source.stale: true` rather than an error. When RA is refusing reads (its bot wall) and no stored copy exists, the answer is 503 with a `Retry-After` header and fresh reads pause for that long; stored horses keep serving throughout. Only a 200 is billed — a 404, 502 or 503 costs nothing. RESOLVING `horse`. Pass a name, or the `pe:` horse_ref that every thoroughbred surface now publishes — they resolve identically, because the horse_ref is the folded name. An `ra:` code from `runner_ref` is accepted too, but prefer the name or horse_ref: Racing Australia issues a new code for the same horse each day. Names resolve against horses seen on our own feeds: acceptances roughly three days ahead, plus every archived result runner (from 2026-09-01) — and, failing both, our own run store and stored form pages, so a horse that last raced months ago still resolves (2026-10-03). Where we hold runs but no readable RA page, those runs are the answer (`source.feed` 'puntersedge_results'). A name we have never seen returns 404 even when RA knows the horse — there is deliberately no name-search against RA itself. ONE NAME, ONE HORSE. A name resolves to the horse, and the most recently seen of its Racing Australia codes is read — a horse that has raced more than once holds several codes, because Racing Australia issues a new one each day. `ambiguous` is always false and `candidates` always empty; both stay on the response for compatibility. Two different horses sharing one folded name cannot be told apart here; the AU register does not allow two ACTIVE horses to share one (a name is released about 17 years after its horse retires). `horse_ref` ON THE RESPONSE is that identity, `pe:<name>`, and it is the same value on /v1/racing/results runners and placings, the live board, the closing-line and price-path archives, /v1/racing/horses/runs and the backfill. `runner_ref` is the code the page was read under; it changes from day to day. Join a horse on `horse_ref`; join the rows about one race on `runner_ref`. THE STORE IS KEYED ON THE HORSE. A page collected under ANY of the horse's codes — by you, by another customer, or by the paced backfill — answers every later lookup of that horse. READING A RUN. Runs come newest first: the page's recent-form table, typically the last ten starts plus barrier trials (`trial: true` — RA publishes those with $0 prize, 0kg weights and no market). `race_class` is RA's official class string ('MDN-SW', 'BM64', 'CTRY MDN'), the first place race class appears anywhere on this API. `prices` is the published price path oldest-quote-to-SP and `sp` its last entry. `margin_l` is lengths behind the winner — on the horse's own win, its winning margin. `pir` is position in running at the 800m and 400m marks where published. `placegetters` names the two nearest finishers with their own ra: codes, so one horse's page walks to its rivals'. Track names are RA's compressed codes ('W FM', 'RAND') served as published. `trainer` on a run is the trainer OF THAT DAY, joined from our own results archive — populated for runs from 2026-09-01 onward and NULL before, because RA's form table names only the current trainer (`profile.trainer`); the archive floor moves back nowhere, so the populated share grows with every meeting. THE CAREER BLOCK. RA's own summaries, not derived from the runs list: overall starts/wins/seconds/thirds, prizemoney, and per-dimension splits (first_up, second_up, firm/good/soft/heavy/synthetic; track/distance splits appear when RA renders them). These cover the whole career even where the runs list shows only recent starts. JOINING TO LIVE DATA. `runner_ref` here, on /v1/racing/results runners and on enriched live runners is the same identifier FOR ONE MEETING, so a pre-race model row joins to that day's official result and to the form read for it. Across meetings, join on `horse_ref` instead — it is on all of those surfaces too and it does not change. `jockey_code` and `meet_code` are RA's own identifiers for the rider and the meeting, and those do persist. Cached 10 minutes per query on top of the six-hour page store.

Requires X-API-Key 3 credits

Request

curl 'https://api.puntersedge.online/v1/racing/horses/form?horse=YOUR_HORSE' \
  -H 'X-API-Key: YOUR_KEY'

Parameters

NameIn TypeRequired Description
horse query string yes Horse name, the `pe:` horse_ref published on every thoroughbred surface ('pe:custo'), or the ra: entry code from runner_ref on results/live runners. Names match case- and punctuation-insensitively on the whole name, and a name and its horse_ref resolve identically.

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 3 credits. Field names and types are as the API returns them; values are a real sample, trimmed to a few items.

{
  "ambiguous": false,
  "candidates": [],
  "career": {
    "prizemoney": 4875,
    "seconds": 0,
    "splits": {
      "first_up": {
        "seconds": 0,
        "starts": 2,
        "thirds": 1,
        "wins": 0
      },
      "good": {
        "seconds": 0,
        "starts": 2,
        "thirds": 1,
        "wins": 0
      }
    },
    "starts": 3,
    "thirds": 1,
    "wins": 0
  },
  "horse_name": "Zweigelt",
  "horse_ref": "pe:zweigelt",
  "profile": {
    "age_sex": "4yo Bay Gelding",
    "colours": "Lime, Purple And Gold Braces And Armbands",
    "dam": "MEDGRINDA",
    "dob": "2022-11-01",
    "last_gear_change": "20-Aug-2026, Blinkers, First Time",
    "sire": "VINO ROSSO (USA)",
    "trainer": "Matthew Dunn",
    "trainer_location": "Murwillumbah"
  },
  "runner_ref": "ra:MTMwNDY2ODI0NA",
  "runs": [
    {
      "barrier": 9,
      "date": "2026-08-18",
      "distance_m": 1430,
      "field_size": 9,
      "going": "Soft",
      "going_rating": 7,
      "jockey": "Andrew Mallyon",
      "jockey_code": "MTQ5MjQ5OTIw",
      "margin_l": 0.76,
      "meet_code": "MTI2NzM2MDQwMA",
      "pir": [
        {
          "at_m": 800,
          "position": 7
        },
        {
          "at_m": 400,
          "position": 7
        }
      ],
      "placegetters": [
        {
          "name": "Sunset Trail",
          "position": 1,
          "runner_ref": "ra:MTMwMDQ4MDk2MA",
          "weight_kg": 58.0
        }
      ],
      "position": 4,
      "prices": [
        7.5,
        4.0,
        4.8,
        5.0
      ],
      "prize_total": 27000,
      "prize_won": 1300,
      "race_class": "MDN",
      "race_number": 4,
      "result_raw": "4th of 9",
      "sectional_distance_m": 600,
      "sectional_time_s": 37.16,
      "sp": 5.0,
      "time_s": 86.82,
      "track": "GRAF",
      "trial": false,
      "weight_kg": 58.5
    }
  ],
  "source": {
    "feed": "racing_australia",
    "fetched_at": "2026-09-01T11:20:00+00:00",
    "region": "AU",
    "sport": "thoroughbred",
    "stale": false
  }
}

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.