Streaming API
Real-time streaming endpoints for live updates.
Overview
Data Stream provides three streaming protocols:
| Protocol | Endpoint Pattern | Use Case |
|---|---|---|
| WebSocket | ws://host/ws/:game | Bidirectional, low latency |
| SSE | GET /sse/:game | Server push, auto-reconnect |
| WebTransport | https://host:4433/wt | Ultra-low latency |
WebSocket
Endpoints
ws://localhost:3000/ws/:game
ws://localhost:3000/ws/type/:type
wss://datastream.hypetech.games/ws/:game
wss://datastream.hypetech.games/ws/type/:type
Connection
// By game
const ws = new WebSocket('wss://datastream.hypetech.games/ws/crash');
// By type
const ws = new WebSocket('wss://datastream.hypetech.games/ws/type/multiplier');
Message Format
Messages are JSON-encoded round objects:
{
"round_id": 512,
"game_id": 1,
"game_slug": "crash",
"game_type": "multiplier",
"finished_at": "2026-01-17T00:45:42Z",
"extras": "{\"point\": \"11.72\"}",
"timestamp": 1768621542123
}
Events
| Event | Description |
|---|---|
onopen | Connection established |
onmessage | New round received |
onclose | Connection closed |
onerror | Error occurred |
Example
const ws = new WebSocket('wss://datastream.hypetech.games/ws/crash');
ws.onopen = () => {
console.log('Connected');
};
ws.onmessage = (event) => {
const round = JSON.parse(event.data);
console.log(`Round ${round.round_id}: ${round.extras}`);
};
ws.onclose = (event) => {
console.log(`Closed: ${event.code}`);
// Implement reconnection
};
ws.onerror = (error) => {
console.error('Error:', error);
};
Server-Sent Events (SSE)
Endpoints
GET /sse/:game
GET /sse/type/:type
Headers
Request:
Accept: text/event-stream
Response:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Event Types
| Event | Description |
|---|---|
initial | First message with latest result |
message | New round result |
| (comment) | Heartbeat (: prefix) |
Event Format
event: initial
data: {"round_id":512,"game_slug":"crash",...}
: heartbeat 1705432800
event: message
data: {"round_id":513,"game_slug":"crash",...}
Example
const sse = new EventSource('/sse/crash');
// Initial data
sse.addEventListener('initial', (e) => {
const round = JSON.parse(e.data);
console.log('Initial:', round);
});
// New messages
sse.addEventListener('message', (e) => {
const round = JSON.parse(e.data);
console.log('New round:', round);
});
// Connection events
sse.onopen = () => console.log('Connected');
sse.onerror = () => console.log('Reconnecting...');
curl Testing
curl -N https://datastream.hypetech.games/sse/crash
WebTransport
Experimental
WebTransport is disabled by default. See WebTransport docs for setup.
Endpoint
https://datastream.hypetech.games:4433/wt
Connection
const wt = new WebTransport('https://datastream.hypetech.games:4433/wt');
await wt.ready;
Datagrams
WebTransport uses unreliable datagrams for lowest latency:
const reader = wt.datagrams.readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
const text = new TextDecoder().decode(value);
const round = JSON.parse(text);
console.log('Datagram:', round);
}
Message Schema
All streaming protocols use the same message format:
interface Round {
round_id: number; // Unique identifier
game_id: number; // Database ID
game_slug: string; // URL-friendly name
game_type: string; // Category
finished_at: string; // ISO 8601 timestamp
extras: string; // JSON-encoded game data
timestamp: number; // Unix milliseconds
}
Extras Schema
Crash
{"point": "11.72"}
Double
{"color": "red", "number": 5}
Slot
{"reels": ["cherry", "lemon", "orange"], "multiplier": "2.00"}
Wall Street
{"trending": "up"}
Subscription Patterns
By Game
Subscribe to a specific game:
/ws/crash → Only crash results
/sse/double → Only double results
By Type
Subscribe to all games of a type:
/ws/type/multiplier → crash + slot results
/sse/type/color → double results
Latency Characteristics
| Protocol | Typical Latency | Notes |
|---|---|---|
| WebSocket | 1-5ms | TCP overhead |
| SSE | 10-50ms | HTTP chunked |
| WebTransport | 0.5-2ms | UDP datagrams |
Latency Measurement
Each message includes a timestamp field (Unix ms). Calculate latency:
ws.onmessage = (event) => {
const round = JSON.parse(event.data);
const latency = Date.now() - round.timestamp;
console.log(`Latency: ${latency}ms`);
};
Connection Management
WebSocket Reconnection
class ReconnectingWebSocket {
constructor(url) {
this.url = url;
this.ws = null;
this.reconnectDelay = 1000;
this.maxDelay = 30000;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.reconnectDelay = 1000;
};
this.ws.onclose = () => {
this.scheduleReconnect();
};
}
scheduleReconnect() {
setTimeout(() => {
this.connect();
}, this.reconnectDelay);
// Exponential backoff
this.reconnectDelay = Math.min(
this.reconnectDelay * 2,
this.maxDelay
);
}
}
SSE (Auto-Reconnect)
SSE reconnects automatically. Just handle the error event:
sse.onerror = () => {
console.log('Connection lost, auto-reconnecting...');
// Browser handles reconnection
};
Error Handling
WebSocket Errors
| Code | Meaning | Action |
|---|---|---|
| 1000 | Normal close | Clean shutdown |
| 1001 | Going away | Server restart |
| 1006 | Abnormal | Network issue |
| 1011 | Server error | Retry with backoff |
SSE Errors
SSE auto-reconnects on network errors. Handle via:
sse.onerror = (event) => {
if (event.target.readyState === EventSource.CLOSED) {
console.log('Connection closed');
} else {
console.log('Reconnecting...');
}
};
Best Practices
1. Choose the Right Protocol
// SSE for simple server push
if (needsOnlyServerPush) {
return new EventSource('/sse/crash');
}
// WebSocket for bidirectional
if (needsBidirectional) {
return new WebSocket('wss://host/ws/crash');
}
// WebTransport for lowest latency
if (typeof WebTransport !== 'undefined' && needsLowestLatency) {
return new WebTransport('https://host:4433/wt');
}
2. Handle Reconnection
Always implement reconnection for WebSocket:
ws.onclose = () => {
setTimeout(() => connect(), 3000);
};
3. Parse Extras Safely
function parseExtras(extras) {
try {
return JSON.parse(extras);
} catch (e) {
console.error('Invalid extras:', extras);
return {};
}
}
4. Monitor Latency
function handleMessage(round) {
const latency = Date.now() - round.timestamp;
if (latency > 100) {
console.warn(`High latency: ${latency}ms`);
}
}
5. Graceful Degradation
async function connect() {
// Try best protocol first
if (typeof WebTransport !== 'undefined') {
try {
return await connectWebTransport();
} catch (e) {}
}
try {
return await connectWebSocket();
} catch (e) {}
// Fallback to SSE
return connectSSE();
}