WebSockets (Live)
Real-time push za stat event-e, status promene i rezultate. Koristi Pusher protokol (naš server je Laravel Reverb), pa postojeći SDK-ovi rade out-of-box.
Connection config
| Host | stats-api.ds2.app |
| Port | 443 (wss, preko nginx proxy-ja) |
| App key | stats-admin-public-key |
| Protocol | Pusher 7.x |
| Auth endpoint | https://stats-api.ds2.app/api/v1/broadcasting/auth |
App key je javan — sigurnost dolazi od tajnog Bearer token-a na auth endpoint-u.
Kanali
Svi su private — moraš imati pretplatu na odgovarajuće takmičenje.
| Kanal | Šta šalje | Uslov pristupa |
|---|---|---|
private-match.{id} | .event.received (svaki shot/rebound/...), .status.changed | Pretplata na takmičenje tog meča |
private-competition.{id} | .status.changed (kad meč promeni status) | Pretplata na to takmičenje |
private-games | Sve .event.received i .status.changed globalno | Bilo koji aktivan nalog (za ticker) |
Tipovi događaja
.event.received
Novi stat event je upisan (shot, rebound, assist, itd.). 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-jsecho-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 — echoes 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,
},
},
})Primer: prati jedan meč
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)
}
})
// Kad završiš sa praćenjem:
echo.leave('match.123')Primer: global ticker
javascript
const ticker = echo.private('games')
ticker.listen('.event.received', (data) => {
// Svaki nov event iz bilo kog meča u sistemu
refreshTickerCard(data.match_id, data.home_score, data.away_score)
})
ticker.listen('.status.changed', (data) => {
// Live dot menja status u ticker karuselu
refreshTickerStatus(data.match_id, data.status)
})Reconnect i error handling
Pusher klijent automatski reconnect-uje. Za robustnost dodaj handler:
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 gap
})
echo.connector.pusher.connection.bind('disconnected', () => {
console.warn('WS disconnected — pusher-js will auto-reconnect')
})PHP / Python / drugi jezici
Pusher protokol ima zvanične SDK-ove za većinu jezika. Config je uvek isti:key=stats-admin-public-key, host=stats-api.ds2.app,port=443, tls=true, auth endpoint =/api/v1/broadcasting/auth sa Bearer header-om.
- PHP:
pusher/pusher-php-client— ali retko treba (obično server-side PHP ne subscribe-uje) - Python:
pusherclientilipysher - Go:
pusher-http-go - Java/Kotlin:
pusher-java-client