Connect
:heartbeat comment every 25 seconds to keep the TCP connection alive.
Error responses before the stream opens
Event frame format
Each event follows the standard SSE wire format:id field is a UUIDv7 string. Store it as Last-Event-ID for gap-free reconnects.
Event types
All emitted event types are registered at startup. Current set (updated with each release):Community — spaces
Community — discussions
Community — comments
Payloads carry IDs only (for example
comment_id, discussion_id, contact_id). Fetch the full resource from the REST API when you need body text or attributes.
Community — notifications
Use
community.notification.created to update the unread badge in real time without polling GET /api/v1/hubs/{hub_id}/notifications/unread-count. The payload carries the notification’s id and hub_id; fetch the full notification resource if you need its category, kind, or preview text.
Community — profiles and DMs
Broadcasts
Test
Payload shape
Every event’sdata is a JSON object. The exact fields vary by event type, but all payloads include identifiers (for example discussion_id, space_id, contact_id) so the client can look up the full resource if needed. Payloads intentionally carry IDs rather than full bodies to keep the event stream lean.
Access scoping
Events are delivered based on the member’s access at connect time:- Hub-scoped events (spaces, directory) reach all connected members.
- Space-scoped events (discussions, reactions) are filtered: restricted spaces are only delivered to members whose segment grants access.
- Direct-targeted events (DMs, 1:1 presence) are delivered only to the named contact IDs.
Terminal events
The server closes the stream by emitting a terminal event before dropping the TCP connection. Terminal events have noid field and are not resumable.
Reconnect and gap-free resume
Store the most recentid value from received events. On reconnect, send it as Last-Event-ID:
stream.stale_resume — on receiving that event, perform a full page refresh to reload state, then reconnect without a Last-Event-ID.
Last-Event-ID must be a UUIDv7 string. Sending any other format returns 400.
Heartbeat
The server sends an SSE comment line every 25 seconds:Last-Event-ID flow.
Connection limit
A single contact may hold at most 5 concurrent SSE connections across all hubs. Opening a sixth connection returns429. Close unused connections (for example, when navigating away from a hub view) to stay within this limit.
X-API-Version
Every SSE response (including the initial HTTP 200 that establishes the stream) includes theX-API-Version response header set to the running build version. See X-API-Version below.
X-API-Version header
Every response from the API — including SSE streams, webhooks, and preflight CORS responses — includes:version field from GET /version). Use it to:
- Confirm a deploy has completed and the expected version is live.
- Emit version metadata in client telemetry.
- Debug which build served a specific request when the
X-Request-IDalone is not enough.
X-API-Version on requests — it is a response-only header.