Growing Discord community — direct access to the developer, live coverage & picks. Join the Discord Join now →
Leagues Matches Predictions Stats Coverage
Docs / WebSockets addon

WebSockets#

Push-based live data over WebSocket. One addon ($3/mo at /addons/) unlocks both channels; the token is the same one you use for REST.

Hands-on guide with working clients: Connect to live WebSockets.

Channels#

URL Sports Notes
wss://sports.bzzoiro.com/live/football/ Football Recommended. Unified channel: score/stats, ball position, odds; on fully-covered matches also per-action events with pitch coordinates ("WS+")
wss://sports.bzzoiro.com/ws/live/ Football + tennis Legacy multi-sport channel; tennis subscriptions go here with "sport": "tennis"

Frame references: Football channel · Tennis channel.

Authentication#

Same API token, two transports:

wss://sports.bzzoiro.com/live/football/?token=YOUR_API_KEY

or the token subprotocol (preferred — keeps keys out of URL logs):

new WebSocket("wss://sports.bzzoiro.com/live/football/", ["token", "YOUR_API_KEY"]);

On failure the server accepts the socket, sends one error frame, then closes:

Close code Error code Meaning
4401 auth_required Missing/invalid token
4402 subscription_required No active WebSocket addon
4404 not_found Unknown WebSocket path

Client → server protocol#

All frames are JSON:

Frame Effect
{"action":"subscribe","event_id":N} Follow a match
{"action":"subscribe","event_id":N,"bookmaker_slug":"…"} Also stream one bookmaker's odds for it
{"action":"subscribe","event_id":N,"sport":"tennis"} Tennis (on /ws/live/ only)
{"action":"unsubscribe","event_id":N} Stop following
{"action":"ping"} {"type":"pong"}

Limit: 10 concurrent subscriptions per socket (match and bookmaker subscriptions counted separately; football and tennis share the budget on /ws/live/).

Error frames#

{"type":"error","code":…,"message":…} with codes: bad_frame, bad_json, bad_action, bad_event_id, not_tracked (match has no live coverage), limit (subscription cap), bad_slug, unknown_bookmaker. Only the three 4xxx cases above close the socket.

Which matches are covered#

Check the REST live list: GET /api/v2/events/live/

  • live_websocket: true — subscribable on the WebSocket
  • websocket_plus: true — full per-action coverage (action frames with coordinates)

Subscribing to an uncovered match returns not_tracked.

Operational notes#

  • Server pings every 25 s; unanswered pings drop the connection (~20 s timeout). Standard clients handle this automatically.
  • Subscriptions don't survive reconnects — re-subscribe after reconnecting.
  • No rate limit on the socket itself; connection read timeout is 1 hour of silence.
  • Try real frames without code at the debug console.
View this page as Markdown · Found a mistake? Tell us