Racing

One thoroughbred's runs in our own settled results

Cost: 3 credits. Every run we hold for one AU thoroughbred, newest first, out of our own settled results.

THIS IS NOT A CAREER RECORD. Each run here is a race WE collected and settled: the same rows /v1/racing/results serves, flattened one-per-horse. The store begins at the first complete card on source.coverage_from and source.coverage_to is the latest race in it, so runs_total is this horse's record SINCE THAT DATE, not its lifetime. The same run never changes once written, so the record only grows — build a longer history forward from here.

WHY YOU WOULD USE IT INSTEAD OF /v1/racing/horses/form. That endpoint is Racing Australia's own form page: deeper (career splits, sectionals, position-in-running, the price path to SP) but dependent on RA serving us the page. Since 2026-09-21 RA's edge answers every fresh form read with a human-verification challenge, so horses we have not already stored cannot be read at all, and we do not automate that challenge. This endpoint has no such dependency — it reads only what we already hold — and it is the honest answer to "what do you have on this horse today". Use both: form for depth when RA lets us in, runs for availability always.

RESOLVING horse — PASS THE NAME, OR ITS horse_ref. A name is folded to letters and digits (the trailing country parenthetical stripped first) and must match in full — the same rule /v1/racing/horses/form applies, so one name resolves identically on both. pe:custo, the horse_ref published on every thoroughbred runner, placing, live-board entry and archive row, is the same fold already done and resolves to exactly the same runs. A Racing Australia horsecode (ra:MjgwNjM0ODg2NDA, or the bare code) is accepted too, but it finds one run rather than a horse: Racing Australia issues a new code for the same horse each day, so a code filter returns the one run that carries it. runner_refs lists every code published under the name; more than one is normal. The other side of grouping on a name is that a registered name reused by two horses returns the union of both. A horse we hold no run for is a 404 and costs nothing; an unknown query parameter is a 422 and costs nothing.

READING A RUN. position is the finishing place, null when the horse did not start (status is scratched) or started and did not finish — abnormal is then RA's own reason cell, verbatim and from no closed list. sp is the official starting price and sp_note RA's favouritism marker; null sp means unknown, never zero. margin is RA's own text in lengths. time_s is the WINNER's time only: RA prints one time per race, in its race header, and no per-runner time in the results table, so since 29 September 2026 a position-1 run carries the race time and every other run's time_s is null. Every run of a race also carries the race-level race_time_s and last_600m_s (RA's header, seconds) and prize_total, and each placed run its prize_won off RA's prize line (dead heats share the places they tie for; 0 outside the paid places); all four are null on runs stored before that date until the meeting is re-read, and before 29 September no run carried any time (0 of 17,344 stored runs, measured 2026-09-28). trainer and jockey are the ones of that day, which is what the result published — profile.trainer on the form endpoint is the CURRENT trainer. field_size counts the horses that ran. weight_kg is the allotted weight and carried_kg the weight actually carried when RA printed one (a claim under it, or an overweight rider over it); race_class is RA's own leading conditions term ('Maiden', 'BenchMark 64'). All three are kept since 28 September 2026. On origin: tabtouch runs, and on runs from 10 August to 27 September 2026 whose result lacked them, race_class and weight_kg come from TABtouch's race page instead: its own class wording ('BM58 HCP', 'MDN-SW') and its printed weight, with carried_kg null. result_id joins back to /v1/racing/results, except on origin: history and origin: tabtouch runs, whose synthetic 'hist:...' id joins to nothing.

stats is computed over every held run, not just the limit returned, and counts only starts (status: ran). runs_total is that same count of starts; held_rows_total is every held row, scratchings included, and runs is the newest limit of those rows -- compare len(runs) with held_rows_total to know whether you have them all. Before 2026-10-13 runs_total counted the scratchings too.

Cached 10 minutes per query; the store itself refreshes hourly at :59.

get/v1/racing/horses/runs

Request

  • Base URL: https://api.puntersedge.online
  • URL: https://api.puntersedge.online/v1/racing/horses/runs
  • Auth: API key in header X-API-Key

Query parameters

horsestring required

Horse NAME (matched on letters and digits, case- and punctuation-insensitive, whole name), or the horse_ref any thoroughbred surface publishes ('pe:custo') — either gathers the whole record, and they resolve identically. A Racing Australia horsecode from runner_ref ('ra:MjgwNjM0ODg2NDA' or the bare code) is accepted too, but it pins one results entry, usually one meeting's runs, not the horse.

limitinteger

Most recent runs to return.

Headers

X-API-Keystring
X-RapidAPI-Proxy-Secretstring

Response

Successful Response

horsestring required

The horse's name as our results spell it.

name_keystring required

The identity the runs were grouped on (letters and digits).

horse_refstring nullable

name_key as the identifier every thoroughbred surface publishes: pe:<name_key>. Pass it back here, or to /v1/racing/horses/form, and read it off /v1/racing/results runners and placings, the live board and the closing-line and price-path archives to gather one horse across meetings.

runner_refsstring[] required

Every Racing Australia horsecode our results published under this name, sorted. Several is normal, not an error — see runs[].runner_ref.

runs_totalinteger required

STARTS held for this horse since source.coverage_from: runs with status ran, the same count as stats.starts. A scratching is not a start. Before 2026-10-13 this counted every held row, scratchings included; that count is held_rows_total.

held_rows_totalinteger required

Every row held for this horse since source.coverage_from, scratchings included. runs is the newest limit of THESE rows, so page on this, not on runs_total. Measured on 2026-10-12, 61,719 of the store's 282,639 rows (21.8%) were scratchings.

Example response

{
  "held_rows_total": 1,
  "horse": "Please Mizter",
  "horse_ref": "pe:pleasemizter",
  "name_key": "pleasemizter",
  "runner_refs": [
    "ra:MjgwNjM0ODg2NDA"
  ],
  "runs": [
    {
      "box": 13,
      "date": "2026-09-20",
      "dead_heat": false,
      "distance_m": 1300,
      "field_size": 12,
      "horse_ref": "pe:pleasemizter",
      "jockey": "Jason Li",
      "last_600m_s": 34.61,
      "margin": "0.75L",
      "number": 14,
      "origin": "results",
      "position": 1,
      "prize_total": 50000,
      "prize_won": 27500,
      "race_class": "Maiden",
      "race_name": "Mdn Plate",
      "race_number": 4,
      "race_time_s": 77.12,
      "result_id": "res_9f1c…",
      "runner_ref": "ra:MjgwNjM0ODg2NDA",
      "sp": 7.5,
      "start_time": "2026-09-20T03:35:00Z",
      "status": "ran",
      "time_s": 77.12,
      "track_condition": "Good 4",
      "trainer": "Peter Fernie",
      "venue": "Rosehill",
      "weight_kg": 57
    }
  ],
  "runs_total": 1,
  "source": {
    "collectors": [
      "racing_australia",
      "tabtouch"
    ],
    "coverage_from": "2026-09-01",
    "coverage_to": "2026-09-20",
    "feed": "puntersedge",
    "refreshed_hourly": true,
    "region": "AU",
    "sport": "thoroughbred"
  },
  "stats": {
    "place_pct": 100,
    "places": 1,
    "starts": 1,
    "win_pct": 100,
    "wins": 1
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.