Internal Betting Feed API Reference
Version: 1.0Last Updated: March 23, 2026
PR: #1065
Overview
The Internal Betting Feed provides authenticated, sequence-aware access to Hyperscape’s duel lifecycle events and renderer health signals. This API is designed for betting market synchronization and should be used by trusted consumers only.Base URL
Authentication
All endpoints require authentication via Bearer token or query parameter.Bearer Header (Recommended)
Query Parameter (EventSource Fallback)
Token Configuration
Server (.env):
- Tokens are compared using timing-safe
timingSafeEqualon SHA-256 digests - Development bypass available via
BETTING_FEED_SKIP_AUTH=true(NEVER in production) - Production fails closed when
BETTING_FEED_ACCESS_TOKENis unset
Endpoints
GET /api/internal/bet-sync/state
Bootstrap endpoint providing current state and replay buffer. Authentication: Required (Bearer header only, no query param) Response:- Initial connection (get current state)
- Reconnection after long disconnect (catch up via replay buffer)
- Sequence gap recovery (re-bootstrap when gaps detected)
GET /api/internal/bet-sync/events
Server-Sent Events (SSE) feed for real-time duel lifecycle updates. Authentication: Required (Bearer header or?streamToken= query param)
Query Parameters:
since=<sequence>(optional) - Resume from specific sequence numberlimit=<number>(optional) - Max frames in initial replay (default: 100, max: 2048)
STREAMING_SSE_HEARTBEAT_MS)
Rate Limit: 60 requests/minute per IPMax Clients: 32 concurrent connections (configurable via
BETTING_SSE_MAX_CLIENTS)
Example:
"bootstrap"- Client is behind or first connection (full buffer)"incremental"- Client is caught up (frames sincesince)"reset"- Client is ahead of server (server restarted, re-bootstrap needed)
- Clients with
writableLength > STREAMING_SSE_MAX_PENDING_BYTESare disconnected - Default threshold: 1MB (configurable)
- Prevents slow clients from blocking the feed
Data Types
BettingFeedPayload
StreamingCycleState
AgentSnapshot
RendererHealth
"socket_disconnected"- WebSocket connection lost"world_not_ready"- 3D world not initialized"terrain_not_ready"- Terrain system not loaded"camera_target_unresolved"- Camera hasn’t locked to target"initialization_failed"- World init error"renderer_unavailable"- WebGPU not available
"agent1_invalid"- Agent 1 missing or invalid HP"agent2_invalid"- Agent 2 missing or invalid HP"arena_positions_invalid"- Positions overlapping or missing
"loading_overlay_active"- Loading screen still visible"initializing"- Waiting for duel data (IDLE phase)"waiting_for_duel_data"- No streaming state yet
Configuration
Server Environment Variables
Rate Limits
Bootstrap Endpoint (/api/internal/bet-sync/state):
- 240 requests/minute per IP
- No concurrent connection limit (stateless)
/api/internal/bet-sync/events):
- 60 requests/minute per IP
- Max 32 concurrent connections
- Slow clients evicted at 1MB pending bytes
Integration Examples
TypeScript Client
Browser Client
Error Handling
HTTP Errors
401 Unauthorized:- Missing or invalid
BETTING_FEED_ACCESS_TOKEN - Check token is set in server
.env - Verify token matches exactly (no whitespace)
- CORS origin not allowed
- Set
INTERNAL_BET_SYNC_ALLOWED_ORIGINto your domain
- Rate limit exceeded
- Bootstrap: 240 req/min per IP
- SSE: 60 req/min per IP
- Max concurrent SSE clients reached (32 default)
- Wait for slot to open or increase
BETTING_SSE_MAX_CLIENTS
SSE Errors
Connection Closed:- Slow client evicted (pending bytes > 1MB)
- Network interruption
- Server restart
Best Practices
Idempotent Processing
UsephaseVersion for idempotent deduplication:
Renderer Health Checks
Always check renderer health before updating market state:Sequence Continuity
Detect server restarts viasourceEpoch changes:
Gap Detection
Monitor for missing sequence numbers:Monitoring
Health Checks
Server Health:Metrics
SSE Client Count:Troubleshooting
Authentication Failures
Symptom: 401 Unauthorized Solutions:- Verify
BETTING_FEED_ACCESS_TOKENis set in server.env - Check token is passed correctly (Bearer header or
?streamToken=) - Ensure token matches exactly (no extra whitespace)
- Check server logs for “Betting feed auth failed” warnings
Renderer Always Degraded
Symptom:rendererHealth.ready is always false
Solutions:
- Check
degradedReasonfor specific issue - Verify streaming state is present
- Check agent snapshots have valid HP
- Verify arena positions are not overlapping
- Check loading overlay has dismissed
SSE Connection Drops
Symptom: EventSource closes unexpectedly Solutions:- Check server logs for “Slow client evicted” warnings
- Verify client is consuming frames fast enough
- Increase
STREAMING_SSE_MAX_PENDING_BYTESif needed - Implement reconnection logic with exponential backoff
Sequence Gaps
Symptom: Missing sequence numbers Solutions:- Check
sourceEpoch- if changed, server restarted - Use bootstrap endpoint to get full replay buffer
- Implement gap detection and re-bootstrap logic
- Check network stability (SSE requires persistent connection)
Migration from Public Polling
Old Pattern (Deprecated)
- Polling delay (1 second minimum)
- No renderer health signals
- No sequence continuity
- Higher server load
- No replay buffer for reconnection
New Pattern (Recommended)
- Real-time updates (no polling delay)
- Renderer health signals
- Sequence-aware (idempotent deduplication)
- Replay buffer (reconnection support)
- Lower server load
Security Considerations
Token Storage
Server:- Store in environment variables or secret manager
- Never commit to git
- Rotate periodically
- Use strong random tokens:
openssl rand -base64 32
- Store in secure backend (never in browser localStorage)
- Pass to frontend via secure session
- Never expose in client-side JavaScript
Logging
Server:- Use
redactStreamingSecretsFromUrlfor all log output - Never log
BETTING_FEED_ACCESS_TOKENin access logs - Redact
streamTokenquery params from logs
CORS
Restrict to Specific Origin:*) for authenticated endpoints.
References
- PR #1065: Internal bet sync feed and renderer health
- Hyperbet Consumer PR: HyperscapeAI/hyperbet#28
- Streaming Guardrails:
packages/shared/src/utils/rendering/streamingGuardrails.ts - DuelBettingBridge:
packages/server/src/systems/DuelScheduler/DuelBettingBridge.ts - Betting Feed Routes:
packages/server/src/routes/streaming-betting-routes.ts - Integration Guide:
docs/streaming-betting-integration.md