Overview
The V1 WebSocket provides real-time score updates with adaptive polling: 1-second intervals when live games exist, 2-second when no live games. This delivers the fastest possible score updates.
Connection
wss://v1.{sport}.sportsapipro.com/ws?x-api-key=YOUR_API_KEY
Replace {sport} with any supported sport slug (e.g., football, tennis, baseball).
The WebSocket connection requires authentication via the x-api-key query parameter.
Welcome Message
On successful connection, you receive:
{
"type": "connected",
"version": "1.0",
"sports": [
{ "id": 1, "name": "Football", "slug": "football" },
{ "id": 2, "name": "Basketball", "slug": "basketball" },
{ "id": 3, "name": "Tennis", "slug": "tennis" },
{ "id": 4, "name": "Hockey", "slug": "hockey" },
{ "id": 5, "name": "Handball", "slug": "handball" },
{ "id": 6, "name": "American Football", "slug": "american-football" },
{ "id": 7, "name": "Baseball", "slug": "baseball" },
{ "id": 8, "name": "Volleyball", "slug": "volleyball" },
{ "id": 9, "name": "Rugby", "slug": "rugby" }
],
"channels": ["all", "live", "football", "basketball", "tennis", "hockey", "handball", "american-football", "baseball", "volleyball", "rugby"]
}
Client Messages
Subscribe
{ "type": "subscribe", "channel": "football" }
{ "type": "subscribe", "channel": "live" }
{ "type": "subscribe", "channel": "match:4467358" }
Unsubscribe
{ "type": "unsubscribe", "channel": "football" }
Ping / Pong
Response:
{ "type": "pong", "ts": 1712345678000 }
Server Messages
Sport Channel Updates
{
"type": "scores",
"channel": "football",
"games": [{ ... }],
"updateId": 5612062220,
"ts": 1712345678000
}
Live Channel (All Sports)
{
"type": "scores",
"channel": "live",
"games": [{ ... }],
"updateId": 5612062220,
"ts": 1712345678000
}
Match-Specific Updates
{
"type": "match-update",
"channel": "match:4467358",
"game": { ... },
"updateId": 5612062220,
"ts": 1712345678000
}
Available Channels
| Channel | Description |
|---|
all | All updates across all sports (default on connect) |
live | Only live games across all 9 sports |
football | Football updates only |
basketball | Basketball updates only |
tennis | Tennis updates only |
hockey | Hockey updates only |
handball | Handball updates only |
american-football | American Football updates only |
baseball | Baseball updates only |
volleyball | Volleyball updates only |
rugby | Rugby updates only |
match:{gameId} | Single game updates |
Code Examples
const ws = new WebSocket('wss://v1.football.sportsapipro.com/ws?x-api-key=YOUR_API_KEY');
ws.onopen = () => {
console.log('Connected to V1 WebSocket');
ws.send(JSON.stringify({ type: 'subscribe', channel: 'live' }));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'connected') {
console.log(`Connected — ${msg.sports.length} sports available`);
}
if (msg.type === 'scores') {
console.log(`${msg.channel}: ${msg.games.length} games updated`);
msg.games.forEach(game => {
console.log(`${game.homeCompetitor.name} ${game.homeCompetitor.score} - ${game.awayCompetitor.score} ${game.awayCompetitor.name}`);
});
}
if (msg.type === 'match-update') {
const g = msg.game;
console.log(`Match update: ${g.homeCompetitor.name} ${g.homeCompetitor.score} - ${g.awayCompetitor.score} ${g.awayCompetitor.name}`);
}
};
ws.onclose = () => console.log('Disconnected');
Update Frequency
| Condition | Polling Interval |
|---|
| Live games in progress | 1 second |
| No live games | 2 seconds |
The V1 WebSocket uses adaptive polling to minimize latency during live games while reducing server load during quiet periods.
World Cup reliability: pair V1 + V2
For high-stakes matches (World Cup knockouts, finals), run both the V1 and the V2 WebSocket in parallel. The two feeds sit on independent infrastructure paths with different upstream sources, so a hiccup on one side does not interrupt the other.
| Capability | V1 WebSocket | V2 WebSocket |
|---|
| Per-match score updates | match:{gameId} | match:{matchId} |
| Per-match incidents (goals, cards, subs, VAR) | Use REST /api/v1/game/{id}/events between ticks | match:{matchId}:incidents (sub-second) |
| Per-match aggregate stats | Use REST /api/v1/game/{id}/stats | match:{matchId}:stats (sub-second) |
| Data path | Direct feed, adaptive polling (1-2s) | NATS push + safety-net poll |
| Best as | Stable fallback / score-of-truth | Primary real-time source |
Recommended pattern
- Connect to V2 as the primary source for sub-second incidents and stats.
- Connect to V1 in parallel and subscribe to
match:{gameId} for the same match — treat its match-update payload as a hot fallback for score and status.
- If V2 drops or stops emitting for more than a few seconds, your UI keeps updating from V1 without any user-visible gap.
- Combine with V1’s dedicated World Cup REST endpoints (
/api/v1/world-cup/...) for tournament-level context (groups, brackets, predictions).
Both feeds are independent and counted separately for quota. Subscribe only to the channels you actually render — match:{gameId} on V1 plus match:{matchId} and match:{matchId}:incidents on V2 is a typical World Cup matchday setup.