Skip to main content

When to use WebSocket vs polling

The simplest rule: use WebSocket for live/in-play events, use polling for pre-match.
WebSocket is available on all plans. Free plan: 30 connections/day. Pro plan: not included. Pro+ RT and Pro+ Live: unlimited. Check your plan at oddsstream.io/dashboard.

Prerequisites

  • An API key starting with os_live_ (get one here)
  • Free, Pro+ RT, or Pro+ Live plan (Pro plan does not include WebSocket)
  • Node.js 18+ or Python 3.10+ depending on your stack
Store your key in an environment variable — never hardcode it:

Step 1: Get a short-lived token

WebSocket connections require a short-lived token (5-minute TTL) rather than your API key directly. This is because:
  • Browsers cannot set custom headers on WebSocket connections
  • The WS server is separate from the API auth gateway — the token is the signed credential that crosses this boundary
Exchange your API key for a token before every new connection:

Step 2: Connect with the token

Pass the token as a ?token= query parameter on the WebSocket URL:

Step 3: Filter the stream

Without filters, you receive every odds change across all sports and bookmakers — potentially thousands of messages per minute. Filter at connection time to only receive what you care about. Append filters as additional query parameters after the token: Combine them freely:
Start filtered. An unfiltered stream across all sports can deliver 50–200 messages per minute during peak hours. Filter to your sport and competition to keep message volume manageable.

Step 4: Handle messages

Each message is a JSON object representing one selection’s odds changing. One market update (e.g. a moneyline with 3 outcomes) produces 3 separate messages — one per selection.
What each field means: A simple handler that builds a local price cache:

Step 5: Keepalive

The server drops idle connections after ~5 minutes. Send a "ping" string every 30 seconds. The server responds with "pong".

Step 6: Reconnect automatically

The server restarts for deployments. Your client must handle disconnects gracefully using exponential backoff — start with a 1-second retry delay and double it up to 30 seconds. Re-fetch the token on every reconnect attempt. Tokens expire after 5 minutes, so the old token may be invalid when you reconnect.

Complete working example

A minimal but complete app that connects, filters to EPL Football, maintains a live price table, and prints best available odds per selection.

Common errors

Your API key is missing or wrong. Check ODDSSTREAM_API_KEY is set and starts with os_live_. Try a simple test:
Your plan doesn’t include WebSocket streaming. Pro plan does not include WebSocket — upgrade to Pro+ RT or Pro+ Live at oddsstream.io/pricing. The Free plan has a 30 connections/day limit.
Free plan: 30 WS token requests per day. Each connection attempt counts. Implement keepalive (Step 5) to avoid unnecessary reconnects. To remove the limit, upgrade to Pro+ RT or Pro+ Live.
Your token is missing, expired, or invalid. Tokens expire after 5 minutes — always fetch a fresh token immediately before connecting. Never cache and reuse tokens across reconnects.
If you connect but receive nothing, your filters may be too narrow. Try removing all filter params to connect unfiltered — if you see messages, your filter value is wrong. Use GET /api/sports to check valid sport names and GET /api/bookmakers for valid bookmaker names.
Normal scrape-to-push latency is 1–3 seconds. Higher latency usually means a bookmaker’s scraper is running slowly. Check scraped_at in the message — if it’s consistently >30 seconds old, contact support.

WebSocket Reference

Full technical spec for the stream endpoint.

Best Practices

Production patterns for reliability and efficiency.