Deciding whether to subscribe
Ask for this on a free key first. If the jurisdictions you care about come back with a low position_pct, the data cannot answer your question and no plan will change that.
Documentation / Reference & coverage
/v1/countries
Every country in the archive with its race count and which fields it publishes.
Send your key in the X-API-Key header, or as
?key= if your tool cannot set one. A date outside your plan's window returns
403 outside_window naming the window, never an empty array.
None. This endpoint takes nothing beyond your key.
curl https://api.apihorseracing.com/v1/countries \ -H "X-API-Key: $AHR_KEY"
$ch = curl_init('https://api.apihorseracing.com/v1/countries'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('AHR_KEY')], ]); $data = json_decode(curl_exec($ch), true)['data'];
const res = await fetch( 'https://api.apihorseracing.com/v1/countries', { headers: { 'X-API-Key': process.env.AHR_KEY } } ); const { meta, data } = await res.json();
import os, requests r = requests.get( "https://api.apihorseracing.com/v1/countries", headers={"X-API-Key": os.environ["AHR_KEY"]}, ).json()
curl https://api.apihorseracing.com/v1/countries?key=$AHR_KEY
$url = 'https://api.apihorseracing.com/v1/countries' . '?key=$AHR_KEY'; $data = json_decode(file_get_contents($url), true)['data'];
const res = await fetch( 'https://api.apihorseracing.com/v1/countries?key=$AHR_KEY' ); const { meta, data } = await res.json();
import os, requests r = requests.get( "https://api.apihorseracing.com/v1/countries?key=$AHR_KEY", ).json()
{ "meta": { "request_id": "03a993f1c72ac391", "data_as_of": "2026-09-12T05:10:27+00:00", "plan": "analyst", "window": "2017 → upcoming", "count": 18 }, "data": [ { "country_code": "USA", "name": "United States", "races": 238963, "full_result_order": false, "position_pct": 0.64, "official_rating": true, "race_class": false, "winning_times": true, "note": null }, { "country_code": "GB", "name": "Great Britain", "races": 100606, "full_result_order": true, "position_pct": 0.83, "official_rating": true, "race_class": true, "winning_times": true, "note": null }, "… 16 more" ] }
A real response from /v1/countries,
captured by calling the live API rather than written by hand.
Each field is described once and rendered on every endpoint that returns it, so the wording cannot drift between pages.
| Field | Type | What it is |
|---|---|---|
| name | string | Race title as published, sponsor and all. |
| official_rating | integer | Handicap mark. Values outside 0 to 200 are dropped as source errors. |
Britain, Ireland and America carry a rating on roughly three quarters of runners. France and Germany carry one on about three percent. Values outside 0 to 200 are dropped, because the source returns sentinels there rather than ratings.
| Code | Status | When |
|---|---|---|
| unauthorized | 401 | No key, or one we do not recognise. Check the header name and that the key has not been rotated from your account page. |
| rate_limited | 429 | Past your per-minute rate. Retry-After is set, and X-RateLimit-Remaining tells you where you stand on every successful response too. |
| server_error | 500 | Ours, not yours. Every response carries a request_id; quote it and we can find the exact request. |
A real request from your browser straight to
api.apihorseracing.com with
your own key. Nothing is proxied and nothing is logged by this page.
Remembered in this browser so you do not paste it on every page. Forget it
The honest starting point. Before you write a line against this API, this endpoint tells you how much of each jurisdiction we hold and which fields it publishes, so you can decide whether your idea is possible rather than discovering it is not.
Every figure is counted from the loaded archive at the last data load, not declared in a configuration file. If the crawl reaches a new country it appears here without anyone editing anything, and if a jurisdiction stops publishing ratings the flag flips on its own.
Ask for this on a free key first. If the jurisdictions you care about come back with a low position_pct, the data cannot answer your question and no plan will change that.
position_pct below about 0.6 means most runners have no finishing position, so anything counting placings will be wrong. Read this once at startup and refuse to run on a region you cannot support.
official_rating false for a country is the reason your handicap column is empty there. It is not a gap in the fetch.
A country appearing here means we hold races from it, not that we hold all of its racing. Compare races against what that jurisdiction actually stages.