Horse Racing docs.
Overview
Worldwide horse racing schedule from 29 hippodromes across 8 countries.
Every race lists its runners (horse name + post position) and a live state that flips through
prematch → idle → live → archived
as the off-time approaches and passes.
The dataset is built around four entities — regions, tracks, races, and runners (horses + entries). Public pages and the (upcoming) API are read-only.
Coverage
| Region | Tracks | Races logged |
|---|---|---|
Australia AU |
7 | 50 |
United States of America US |
7 | 48 |
Japan JP |
5 | 47 |
United Kingdom GB |
5 | 22 |
France FR |
2 | 11 |
Argentina AR |
1 | 10 |
Brazil BR |
1 | 9 |
Ireland IE |
1 | 4 |
The set rotates daily — tracks only show up while they have races on the calendar.
Update cadence
| Job | Frequency | What it does |
|---|---|---|
sync_horseracing_live |
every minute | Refreshes races whose off-time is within ±2h so state flips hit the DB fast. |
sync_horseracing |
every 30 minutes | Full schedule for the next 7 days; catches new races as tracks publish them. |
Pages auto-refresh too — the home reloads every 60s, race detail every 30s while live.
Data model
| Model | Identifier | Key fields |
|---|---|---|
HRRegion |
ISO code (AR, AU, GB, …) |
code, name |
HRTrack |
upstream id | name, slug, region, tier, sort_score |
HRHorse |
upstream competitor id | name, grade, last_seen_at |
HRRace |
upstream race id (ta_*) |
name, slug, track, region, state, starts_at, on_line_at, off_line_at, provider, competitors_count |
HREntry |
(race, horse) unique | program_number, finish_position |
Races flip through five states. The lifecycle is roughly:
prematch— published, off-time in the future.idle— about to start (the gate is set, betting locks soon).live— running.archived— finished.cancelled— scratched.
Public pages
/horseracing/ — today's schedule, live ticker, tracks index/horseracing/upcoming/ — next 7 days/horseracing/results/ — archived races, last 72h/horseracing/tracks/ — all tracks currently on the calendar/horseracing/race/<race_id>/ — single race with runners/horseracing/track/<slug>/ — track page with recent + upcoming racesREST API
DRF v2 endpoints under /horseracing/api/v2/. Bundled into the
Sports Pack ($5/mo) alongside tennis, CS:GO, darts, hockey and basketball.
Pass Authorization: Token YOUR_TOKEN on every request.
/horseracing/api/v2/tracks/ — list (filter country, tier)/horseracing/api/v2/tracks/<slug>/ — track detail + last 40 races/horseracing/api/v2/races/ — filter date / date_from+date_to / country / track / state/horseracing/api/v2/races/live/ — currently live + next 30min/horseracing/api/v2/races/<race_id>/ — full runners/horseracing/api/v2/horses/?q=<name>/horseracing/api/v2/horses/<horse_id>/ — recent racescurl -H "Authorization: Token YOUR_TOKEN" \
"https://sports.bzzoiro.com/horseracing/api/v2/races/?date=2026-05-19&country=AU"
MCP server
Streamable-HTTP MCP at /horseracing/mcp/ exposes the dataset to Claude, ChatGPT and Gemini.
Bundled with the Sports Pack; one token unlocks all sports. JSON-RPC 2.0.
| Tool | Description |
|---|---|
list_tracks | Tracks filtered by country / tier |
get_track | Track detail with the 40 most recent races |
list_regions | Countries currently on the calendar |
search_races | Filter by date, country, track, state |
live_races | Live + about-to-start (next 30 min) |
get_race | Race detail with full runners list |
search_horses | Horse search by name substring |
get_horse | Horse detail with recent appearances |
curl -X POST -H "Authorization: Token YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"live_races","arguments":{}}}' \
https://sports.bzzoiro.com/horseracing/mcp/
WebSocket Coming soon
A live channel will broadcast race-state transitions
(prematch → idle → live → archived) to subscribers so race-day dashboards
stay in sync without polling. Subscription model: per-track or per-race.
wss://sports.bzzoiro.com/ws/horseracing/?token=YOUR_TOKEN
→ {"action":"subscribe","track_slug":"caulfield-93420d"}
← {"type":"state","race_id":"ta_11673002","old":"idle","new":"live","t":"…"}
Odds & results
Each runner carries decimal odds for three markets and three settlement flags. Once the race archives, the podium is derived from the settled outcomes:
| Field | Source | Notes |
|---|---|---|
odds.win | Win market price | Decimal odds, may be 0 for refunded/scratched |
odds.place | Place market price | Each-way (top 3) odds |
odds.top2 | Top 2 market price | Top-2 finish odds |
result_win | Win market settlement | P1 |
result_top2 | Top 2 market settlement | P1 or P2 (combine with result_win to isolate P2) |
result_place | Place market settlement | P1, P2 or P3 |
finish_position | Derived | 1 = Win, 2 = Top 2 ∖ Win, 3 = Place ∖ Top 2 |
Odds refresh runs every 2 minutes for the next 4 hours of fixtures plus the prior 24 hours of archived races so settled flags land soon after the off.
Roadmap
- WebSocket for state-flip subscriptions
- Form lines per horse — career placings, win/place returns chart
- Coverage of richer markets (Exacta, Trifecta) when needed
- Backfill historical seasons (2024-2025) once upstream allows