Documentation / Guides
WebSocket stream
Stream greyhound results and race status changes over wss://: channels, the subscribe protocol, the replay window and connection limits.
Live keys can hold up to 2 connections to
wss://greyhoundapi.com/v1/stream. Sandbox keys have no stream.
Present your key on the upgrade in whichever way suits your client: the
X-API-Key header (or Authorization: Bearer) for server-side
clients, or — since browsers can't set handshake headers — as a WebSocket subprotocol:
// browser: pass a marker protocol and your key
const ws = new WebSocket('wss://greyhoundapi.com/v1/stream',
['gapi-stream', 'gapi_live_yourkey']);Subscribe by channel — topic {results|status|cards} and region
{GB|AU|*}:
{ "action": "subscribe",
"channels": ["results:GB", "status:*", "cards:AU"] }Events
result.received when a result lands in the pipeline;
race.status_changed on off / results_pending / void / abandoned transitions;
card.updated for runner changes on upcoming races.
{ "event": "result.received", "channel": "results:GB",
"race_id": 1229082, "track": "Romford",
"results_delay_s": 1060, "ts": "2026-07-08T21:03:41Z" }Reconnecting
Heartbeat ping every 30s. On reconnect, send
{"action":"replay","channel":"results:GB","since":"<iso>"} to replay the
last 15 minutes; for anything older, catch up over REST with
GET /v1/results/latest?since=.
Close codes
The gateway closes with 4401 (unknown, revoked or expired key),
4403 (sandbox key, or a live key suspended mid-session — you'll get a
{"event":"closing","reason":…} frame first) or 4408 (you already
hold the maximum 2 connections). A suspended or expired key is
dropped within a minute, not just refused on the next connect.