WebSockets (Live)

Real-time push for stat events, status changes, and scores. Uses the Pusher protocol (our server is Laravel Reverb), so existing SDKs work out of the box.

Connection config

Hoststats-api.ds2.app
Port443 (wss, through the nginx proxy)
App keystats-admin-public-key
ProtocolPusher 7.x
Auth endpointhttps://stats-api.ds2.app/api/v1/broadcasting/auth

The app key is public — security comes from the secret Bearer token sent to the auth endpoint.

Channels

All channels are private — you must be subscribed to the relevant competition.

ChannelWhat it sendsAccess condition
private-match.{id}.event.received (every shot/rebound/...), .status.changedSubscription to the match's competition
private-competition.{id}.status.changed (when a match changes status)Subscription to that competition
private-gamesEvery .event.received and .status.changed globallyAny active account (good for tickers)

Event types

.event.received

A new stat event was recorded (shot, rebound, assist, etc.). Payload:

json
{
  "match_id": 123,
  "home_score": 45,
  "away_score": 42,
  "current_period": 2,
  "current_clock": "07:23",
  "status": "in_progress",
  "event": {
    "id": 9871,
    "client_id": "7b2a...uuid",
    "type": "3pt_made",
    "team_id": 16,
    "player_id": 88,
    "period": 2,
    "clock": "07:23",
    "x": 42.5,
    "y": 18.2,
    "event_at": "2026-04-13T20:15:30+00:00"
  }
}

.status.changed

json
{
  "match_id": 123,
  "competition_id": 4,
  "status": "finished",
  "previous_status": "in_progress",
  "home_score": 89,
  "away_score": 84
}

Setup (Node.js / browser)

bash
npm install laravel-echo pusher-js
echo-client.jsjavascript
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'

// Pusher must be on window for laravel-echo to find it
window.Pusher = Pusher

export const echo = new Echo({
  broadcaster: 'reverb',
  key: 'stats-admin-public-key',
  wsHost: 'stats-api.ds2.app',
  wssPort: 443,
  forceTLS: true,
  enabledTransports: ['ws', 'wss'],
  disableStats: true,

  // Private channel auth — sends our Bearer token to the server
  authEndpoint: 'https://stats-api.ds2.app/api/v1/broadcasting/auth',
  auth: {
    headers: {
      Authorization: 'Bearer ' + process.env.STATS_API_TOKEN,
    },
  },
})

Example: follow one match

javascript
import { echo } from './echo-client'

const channel = echo.private('match.123')

channel.listen('.event.received', (data) => {
  console.log(`Score: ${data.home_score} : ${data.away_score}`)
  console.log(`Last event: ${data.event.type}`)
  updateScoreboard(data)
})

channel.listen('.status.changed', (data) => {
  if (data.status === 'finished') {
    showFinalResult(data)
  }
})

// When you are done watching:
echo.leave('match.123')

Example: global ticker

javascript
const ticker = echo.private('games')

ticker.listen('.event.received', (data) => {
  // Every event from every match in the system
  refreshTickerCard(data.match_id, data.home_score, data.away_score)
})

ticker.listen('.status.changed', (data) => {
  // Live dot updates the status in the ticker carousel
  refreshTickerStatus(data.match_id, data.status)
})

Reconnect and error handling

The Pusher client reconnects automatically. For robustness, add handlers:

javascript
echo.connector.pusher.connection.bind('error', (err) => {
  console.error('WS error:', err)
})

echo.connector.pusher.connection.bind('connected', () => {
  console.log('WS connected — refetch state from HTTP API to catch missed updates')
  // Re-fetch box score / standings via /api/v1 to backfill the gap
})

echo.connector.pusher.connection.bind('disconnected', () => {
  console.warn('WS disconnected — pusher-js will auto-reconnect')
})

PHP / Python / other languages

The Pusher protocol has official SDKs for most languages. The config is always the same:key=stats-admin-public-key, host=stats-api.ds2.app,port=443, tls=true, auth endpoint =/api/v1/broadcasting/auth with a Bearer header.

  • PHP: pusher/pusher-php-client — rarely needed (server-side PHP rarely subscribes)
  • Python: pusherclient or pysher
  • Go: pusher-http-go
  • Java/Kotlin: pusher-java-client