Documentation / Guides
Authentication
One key, two ways to send it, and what a refusal looks like.
One key
One account, one key, and it never needs replacing. Your entitlement is read from your plan on every single request, so upgrading widens what the key you already hold can reach. There is nothing to reissue and nothing to re-integrate.
That is a deliberate choice. Most APIs make you rotate keys to change plan, which means a plan change is a deployment. Here it is a database read.
Two ways to send it
The header, which you should use
curl https://api.apihorseracing.com/v1/countries \
-H "X-API-Key: ahr_..."
The query string, which exists for tools that cannot set headers
curl "https://api.apihorseracing.com/v1/countries?key=ahr_..."
The second one is convenient for a spreadsheet, a browser tab or a quick look. It is also worse everywhere else: a key in a URL ends up in server logs, browser history, referer headers and anything the link is pasted into. Use the header unless you cannot.
What a refusal looks like
Three different things can go wrong with a key, and they are three different responses on purpose.
| Status | Code | Means |
|---|---|---|
| 401 | unauthorized |
No key, or one we do not recognise. Check the header name and that the key has not been rotated. |
| 403 | upgrade_required |
The key is valid; the plan does not reach this endpoint. The body names every plan that does. |
| 403 | outside_window |
The key is valid and the endpoint is allowed; the date is outside what your plan reads. The body names the window and the date you asked for. |
None of those is transient. Retrying will produce the same answer, and a client that retries a 403 on a backoff is just burning its own quota.
{
"error": {
"code": "upgrade_required",
"message": "Your plan does not reach this endpoint.",
"your_plan": "complete",
"reaches_on": ["analyst"],
"doc_url": "https://apihorseracing.com/documentation/trainers-stats"
}
}
Keeping it safe
- Never put it in client-side code. Anything shipped to a browser is public. Proxy through your own server.
- Never commit it. Environment variable, secrets manager, anything but a repository.
- Do not share it across organisations. Usage counts against your quota whoever made the request.
- If it leaks, rotate it from your account page. The new key works immediately and the old one stops immediately, so plan the swap before you press it.
We will never ask you for your key. If you are reporting a problem, send the
request_id instead: it identifies the request without identifying the
credential.