Live Plus · Statistics endpoints

Answers, not rows.

Three endpoints that return greyhound form already aggregated — strike rate by distance, trap, track, grade and going for any dog, trainer or owner. One call replaces an archive download and an aggregation layer you would otherwise write and maintain.

3
Endpoints
14
Splits returned
1
Call per subject
~4KB
Fits any prompt
Without these endpoints
38 requests
M E Wiley has 1,887 runners in twelve months. Paged at 50 a time that is 38 calls, then you aggregate them yourself — per trainer, per race.
With them
1 request
Same answer, already grouped by track, distance, trap, grade and going. No archive to hold, no aggregation to keep correct.
A six-runner race
228 → 6
Every runner profiled before the off, inside your rate limit, fast enough to do it live.

Built for models, useful to everyone

Language models reason well over small, clean inputs — and badly over raw form

Hand an assistant three hundred race lines and ask which trap suits a dog and it will do arithmetic it is not good at, confidently. Hand it one object where the arithmetic is already done and it reasons over facts instead. That is the whole design brief for these endpoints, and it happens to be what a human analyst wants too.

01

Small enough to fit

A complete dog profile is around 4KB. Three hundred form lines are not, and truncating them silently changes the answer.

02

Nothing left to infer

Every percentage arrives with its runs. A model cannot mistake three runs at 33% for thirty at 33%, because both numbers are present.

03

One tool call, not a pipeline

Function calling works best when a question maps to a single call. These map one-to-one onto the questions people actually ask.

What each one does

Three endpoints, fourteen splits

Every example below is a real response from the live API.

GET /v1/dogs/{dog_id}/statsLive Plus

A career, cut five ways

Distance, trap, track, grade and going — each with runs, wins, places, strike rate and place rate. by_distance also carries best and average winning time.

Times appear only there, deliberately. A time averaged across a 268m sprint and a 500m race describes neither, and returning it would invite exactly the wrong comparison.

Going is banded — fast, standard, slow — because the raw allowance shatters a career into slices too small to read. The underlying values still come back in going_values.

# A Bad Winter — 59 runs, real response
"overall": { "runs": 59, "wins": 11, "win_pct": 18.64 }

"by_distance": [
  { "distance_m": 462, "runs": 28, "win_pct": 21.43,
    "best_time_s": 28.02 },
  { "distance_m": 268, "runs": 11, "win_pct": 9.09 }
]

# same dog. right trip, wrong trip.
"by_trap": [ { "trap": 1, "runs": 40, "win_pct": 22.5 } ]
GET /v1/trainers/{trainer_id}/statsLive Plus

Does this yard travel?

The same splits over a rolling window, plus track_id to narrow every one of them to a single course. This is the question a flat results list cannot answer without you counting.

The window is bounded on purpose. A busy yard has thousands of runners a year, and trainer form is not permanent — a strike rate from four years ago describes a different operation.

# M E Wiley — 12 months, real response
"overall": { "runs": 1887, "wins": 342, "win_pct": 18.12 }

"by_track": [
  { "track": "Romford",      "runs": 1831, "win_pct": 18.3 },
  { "track": "Central Park", "runs": 43,   "win_pct": 13.95 },
  { "track": "Hove",         "runs": 6,    "win_pct": 0 }
]

# a home-track yard. now you know.
GET /v1/owners/{owner_id}/statsLive Plus

Which yard is earning its keep

by_trainer is unique to this endpoint and answers something nothing else in the API can: not how the dogs are running, but which trainers an ownership is getting results from.

For a syndicate paying several sets of training fees, that is the entire question, and it arrives in one request.

# Justin Bowman — real response
"overall": { "runs": 97, "wins": 9, "win_pct": 9.28 }

"by_trainer": [
  { "trainer": "Justin Bowman", "runs": 66, "win_pct": 12.12 },
  { "trainer": "Carolyn Jones", "runs": 12, "win_pct": 8.33 },
  { "trainer": "Chloe Bowman",  "runs": 19, "win_pct": 0 }
]

# three yards. one is working.

Twelve things people build with these

Four uses for each endpoint

Not a feature list — the questions these were built to answer.

Dog statistics

/v1/dogs/{dog_id}/stats

Is this trip right for it?

A dog with 21% over 462m and 9% over 268m is not an inconsistent dog — it is a dog in the wrong race. by_distance answers that before you look at anything else.

Box preference, separated from track bias

A 22.5% trap-1 record means one thing at Romford and another at Hove. Read by_trap against the track's own draw bias and you can tell the dog from the draw.

Grounding an AI preview

One compact object per runner fits in a prompt. Hundreds of raw form lines do not, and a model asked to aggregate them will quietly get it wrong.

Honest sales and stud copy

runs travels with every percentage, so a 100% strike from one run cannot be presented as a record.

Trainer statistics

/v1/trainers/{trainer_id}/stats

Does this yard travel?

M E Wiley runs 18.3% at Romford across 1,831 runners and 0% at Hove across 6. track_id answers "are they any good here" in one call.

Form that is actually current

A rolling window means you are reading this season, not a career average diluted by four years ago. months widens it when you want the long view.

Model features, ready-made

Trainer strike rate at track, at distance and at grade are standard runner-level features. Computing them yourself means holding the whole archive.

Tool calls that stay grounded

An assistant asked "is this trainer in form at Monmore" returns a number instead of an impression.

Owner statistics

/v1/owners/{owner_id}/stats

Which yard is earning its keep

by_trainer is unique to this endpoint. One ownership, three trainers, three strike rates — 12.12%, 8.33% and 0.00%. Nothing else in the API answers that.

Connections that outperform both parties

Owner-trainer pairings carry signal neither carries alone. Cross-reference with trainer statistics and the partnerships stand out.

Ownership pages worth visiting

With /v1/owners/search, enough for a browsable owner section with real substance rather than a list of runners.

Syndicate reporting

For a syndicate paying several sets of training fees, this is the whole picture in a single request.

Together

Three calls describe a runner completely

Each endpoint answers one question. Combined, they answer the one that matters: is this animal, in this race, in the right place tonight — and are the people behind it any good at this track.

CALL 1

The dog

Right trip? Right box? by_distance and by_trap for tonight's 400m from trap 1.

CALL 2

The trainer

With track_id set to tonight's course. A yard at 28% here is a different runner from the same yard at 6%.

CALL 3

The ownership

by_trainer shows whether this owner-trainer pairing is one that works, or one of three they are trying.

# one runner, three calls, in parallel
dog     = GET /v1/dogs/654594/stats
trainer = GET /v1/trainers/118/stats?track_id=14
owner   = GET /v1/owners/2231/stats

# what you can now say, with the sample size attached to every claim
Trap 1 over 400m: 22.5% from 40 runs — the dog's best box.
Trainer at this track: 18.3% from 1,831 runners — home yard.
Owner with this trainer: 12.12% from 66 — their strongest pairing.

# six runners = 18 calls, well inside 180/min. Do it at declaration time.

Live Plus

All 38 endpoints, including these three

Everything on Live, plus the statistics endpoints, more than double the request allowance and a higher rate limit for profiling a full card before the off.

  • Dog, trainer and owner statistics — the three above
  • 600,000 requests a month, up from 250,000
  • 180 requests a minute, up from 120
  • Everything Live already includes — live-day data, full archive, results stream, webhooks
$199/mo

Live is $99/mo and reaches 35 of the 38 endpoints.

Cancel any time from your dashboard. Your existing keys keep working — the three endpoints simply start answering.