GET /events.
Connecting
:) are heartbeats. The server sends one every ~30 seconds. Treat an idle stream longer than 60s as disconnected and reconnect.
Event types
Payloads are filtered by the subscriber’s permissions — the server won’t stream events for items or edges the credential can’t read.Event catalog (quick reference)
Event catalog (quick reference)
Filtering
Clients can subscribe to a subset of events:Reconnecting with Last-Event-ID
On reconnect, the client sends the Last-Event-ID header with the last event id it received:
EventSource API in browsers handles Last-Event-ID automatically. Non-browser clients (SDKs, server-to-server consumers) should persist the most recent event id and re-send it on reconnect.
When the event log is stale
IfLast-Event-ID is older than the event log retention window, the server replies with a terminal event indicating the gap:
GET /items?updated_after=<timestamp>&limit=... sweep (paginated), then reconnect to live streaming.
This path doesn’t surface deletes — items deleted during the gap aren’t returned. A subsequent SSE delete event will reconcile on receipt. Clients that need deterministic delete reconciliation after long outages should keep the SSE stream within retention or re-seed the local store.
Catch-up strategy
A typical sync engine follows this pattern:1
First connection
Connect to
GET /events without Last-Event-ID. Persist the most recent id received.2
Live streaming
Apply events as they arrive. Persist
Last-Event-ID on each event.3
Reconnect on disconnect
Send persisted
Last-Event-ID. Server replays from that point.4
Handle `catchup_too_old`
Fall back to
GET /items?updated_after=<last_sync_timestamp> with pagination. Reconnect live after catch-up completes.Keepalive
The server sends:ping comment frames every ~30 seconds. Clients should close the connection and reconnect if no event (including pings) arrives for > 60 seconds — the connection is likely dead even if the TCP socket is open.
Scale
SSE is single-process on the emitting server. For deployments behind load balancers or multi-instance setups, configure sticky sessions or use the webhook delivery system instead — webhooks are durable and don’t require persistent connections.SSE vs webhooks
Both fire on the same event surface — an item creation produces both an SSE event and a webhook delivery. Use whichever matches your consumer.