Skip to main content

Connection

wss://v2.football.sportsapipro.com/ws?x-api-key=YOUR_API_KEY

Authentication

Pass your API key via:
  • Query string (recommended for browser clients): ?x-api-key=YOUR_API_KEY
  • Header: x-api-key: YOUR_API_KEY

Sport Selection

Optionally set the x-sport header during connection to scope live-scores to a specific sport (default: football). Supported values: football, basketball, ice-hockey, tennis, rugby, handball, volleyball, baseball, american-football, cricket, futsal, mma, motorsport, darts, snooker, badminton, table-tennis, beach-volley, cycling, esports, bandy, aussie-rules, floorball, minifootball, waterpolo.

Message Format

All messages are JSON. Send actions to subscribe/unsubscribe from channels:
{ "action": "subscribe", "channel": "live-scores" }
{ "action": "subscribe", "channel": "match:14109842" }
{ "action": "subscribe", "channel": "match:14109842:incidents" }
{ "action": "unsubscribe", "channel": "match:14109842" }
{ "action": "ping", "channel": "live-scores" }

Available Channels

ChannelDescriptionDelivery
live-scoresAll live match scores & status changes (auto-scoped to your x-sport)NATS push — sub-second
live-scores:{sport}Live scores for a specific sport (e.g. live-scores:basketball)NATS push — sub-second
match:{matchId}Score & status updates for a single matchNATS push — sub-second
match:{matchId}:incidentsGoals, cards, substitutions, VAR decisionsNATS-triggered fetch — sub-second
match:{matchId}:statsMatch statistics (possession, shots, passes)NATS-triggered fetch — sub-second
match:{matchId}:oddsLive odds from all providersNATS-triggered fetch — sub-second
match:{matchId}:lineupsTeam lineups (typically available pre-match)Polling — 60s interval

Delivery Modes

  • NATS push — Data is pushed directly from the real-time feed with no delay
  • NATS-triggered fetch — When any match update is detected, detailed data is fetched instantly (no waiting for poll cycle)
  • Polling — Data is fetched at regular intervals (used for lineups which rarely change)

Response Types

welcome

Sent immediately on connection:
{
  "type": "welcome",
  "message": "SportsAPIData WebSocket v3.1 — All Channels Sub-Second",
  "sport": "football",
  "natsConnected": true,
  "channels": ["live-scores", "match:{matchId}", "..."]
}

subscribed

Confirms a channel subscription:
{
  "type": "subscribed",
  "channel": "match:14109842:incidents",
  "mode": "realtime (NATS-triggered fetch, 15000ms safety-net poll)"
}

snapshot

Last known data sent immediately upon subscribing (if available):
{
  "channel": "match:14109842",
  "type": "snapshot",
  "data": { ... },
  "timestamp": 1710729600000
}

update

New data pushed in real-time:
{
  "channel": "match:14109842:incidents",
  "type": "update",
  "data": { ... },
  "source": "nats",
  "timestamp": 1710729600437
}

pong

Response to a ping (for keep-alive):
{
  "type": "pong",
  "channel": "live-scores",
  "timestamp": 1710729600000
}

Quick Start Examples

const ws = new WebSocket('wss://v2.football.sportsapipro.com/ws?x-api-key=YOUR_API_KEY');

ws.onopen = () => {
  // Subscribe to all live football scores
  ws.send(JSON.stringify({ action: 'subscribe', channel: 'live-scores' }));

  // Subscribe to a specific match's incidents (goals, cards, subs)
  ws.send(JSON.stringify({ action: 'subscribe', channel: 'match:14109842:incidents' }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(`[${msg.type}] ${msg.channel}:`, msg.data);
};

Best Practices

Each subscription consumes server resources. Only subscribe to channels your application actively uses.
Use match:{id}:incidents for real-time match events rather than polling the REST endpoint.
When you subscribe, you immediately get the last known state so your UI is never blank.
Send {"action":"ping","channel":"live-scores"} every 30s to keep the connection alive.
If disconnected, reconnect with exponential backoff (1s, 2s, 4s, 8s…).
Unsubscribe from match channels when the user navigates away.