API reference
Relay (WebSocket)
Live state stream — team, mapMarkers, devices, mapNotes — over a single WebSocket per dashboard / overlay client.
The relay is a separate Fly app (fly-relay/). It speaks Rust+ to your paired servers and broadcasts the normalised state to dashboard / overlay clients over a single WebSocket per client.
Connect
wss://relay.rustpulse.app/v1?token=<jwt>
Mint the JWT via POST /relay/token on the API (session auth required). JWT lifetime is ~5 minutes.
Client → server messages
// subscribe to a paired server's stream
{ "type": "subscribe", "serverId": "ckxxxx" }
// unsubscribe
{ "type": "unsubscribe", "serverId": "ckxxxx" }
// command (e.g. toggle a smart switch)
{ "type": "deviceToggle", "serverId": "ckxxxx", "deviceId": "..." }
// ping (keep-alive; server replies with pong)
{ "type": "ping" }
Server → client messages
// initial snapshot after subscribe
{ "type": "snapshot", "serverId": "...", "state": { team, mapMarkers, devices, mapNotes } }
// live diff
{ "type": "patch", "serverId": "...", "patch": [...] } // JSON Patch ops
// world events
{ "type": "event", "serverId": "...", "event": { kind: 'cargo', grid: 'D2', ... } }
// chat mirror
{ "type": "chat", "serverId": "...", "chat": { author, text, ts } }
// raid alert
{ "type": "raid", "serverId": "...", "alarmId, alarmName, ts" }
// pong
{ "type": "pong" }
Rate limiting
- Each connection: 60 messages / 10 seconds outbound.
- Snapshot replies on subscribe are throttled to one per 5s per server (so a refresh-spam doesn't hammer the relay).
Reconnect
The dashboard reconnects with capped exponential backoff (1s → 30s). On reconnect it re-mints a JWT and re-subscribes to the previously-subscribed servers. Snapshot semantics make state convergence safe.
Health
GET https://relay.rustpulse.app/health
→ { ok: true, activeConnections: 42, uptime: 12345 }
Used by the Discord status board and by the admin's relay-reachability check.