APIHorseRacing

Documentation / Webhooks & account

Subscribe

POST /v1/webhooks/subscribe

Point a URL at an event and we sign every delivery.

Available on

Free key 24h – 7d
Live today + 3 days
Archive back to 2017
Complete 2017 → upcoming
Complete + Analyst 2017 → upcoming

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.

Parameters

NameInTypeRequiredDescription
url body string yes Where to deliver. Must be https. We will not post to a plain http endpoint, because the payload identifies your account.
events body array yes One or more of result.received, race.abandoned, meeting.abandoned, racecard.published.
region body string no Only deliver for one jurisdiction. Most consumers want this; without it you receive twelve countries.
course_id body string no Only deliver for one course.
secret body string no Your own signing secret. If you do not supply one we generate it and return it once, in this response only.

Request

curl https://api.apihorseracing.com/v1/webhooks/subscribe \
  -H "X-API-Key: $AHR_KEY"

Response

No sample has been captured for this endpoint yet. Use the console below against your own key.

Errors this endpoint returns

CodeStatusWhen
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.
forbidden 403 The account is disabled or the key revoked. Contact support; this is never a rate limit.
invalid_param 422 A date that is not YYYY-MM-DD, a by= dimension we do not have, or a cursor that did not come from us. The message names the parameter.
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.

Run it live

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.

What this is for

Point a URL at an event and we tell you when it happens, instead of you asking every thirty seconds whether it has.

Four events. result.received when a race settles, which is the one nearly everybody wants. race.abandoned and meeting.abandoned when racing is called off, which is the event that silently breaks schedulers. And racecard.published when declarations land for a future day.

Deliveries do not count against your quota. Polling for results is the single largest source of wasted requests we see, and charging you for the alternative would be a strange way to discourage it.

Every delivery carries an X-AHR-Signature header: an HMAC-SHA256 of the raw body using your secret. Verify it before trusting the payload, and compare with a constant-time function rather than a string equality. The secret is returned once at subscription and never again; rotate by subscribing afresh.

A delivery that does not return a 2xx is retried with an increasing gap for about a day, then given up on. Deliveries are at-least-once, not exactly-once, so your handler needs to tolerate seeing the same race twice. Key on the race identifier and it will.

Common uses

Replacing a results poller

Subscribe to result.received for your region. A process polling every thirty seconds is about ninety thousand requests a month; this is none.

Not being caught by an abandonment

race.abandoned is the event that saves a scheduler from waiting forever on a result that will never arrive.

Preparing overnight

racecard.published tells you tomorrow is ready, rather than you guessing at what time to look.

Notes

The subscription belongs to the account rather than to the key, so rotating your key does not stop deliveries.

Related in Webhooks & account