Event stream and resync
The served transport is API v1. API v0 routes return INCOMPATIBLE_VERSION.
Handshake
Section titled “Handshake”Every snapshot, event-stream and wait request needs X-Majlis-API-Version: v1 (or api_version=v1 without the header). Unix socket clients also send their X-Majlis-Binding token. Dashboard clients exchange the single-use launch token at /v1/ui/exchange and then use the session cookie. Never put binding or launch tokens in query parameters.
Snapshot, then stream
Section titled “Snapshot, then stream”GET /v1/workspaces/{ws}/snapshotreturns a consistent snapshot and itscursor.GET /v1/workspaces/{ws}/eventswithLast-Event-ID: <cursor>starts after that cursor.
The local monotonic seq orders committed events within one user database. Workspace streams carry that workspace’s events plus global events, so IDs can skip without a lost event. Do not reuse a cursor from another database.
Frames
Section titled “Frames”Each event frame has id: <seq>, event: <type> and JSON data. The initial : connected comment and 15-second keepalives carry no cursor or delivery evidence. Data frames are bounded to 1 MiB, and a write that exceeds the 30-second deadline ends the connection.
Purged payloads arrive with payload_redacted: true; render a placeholder rather than dropping the event. On disconnect, back off exponentially with jitter up to 30 seconds, label cached data stale, keep drafts, and refresh ownership and revisions before mutating.
Resynchronization
Section titled “Resynchronization”If the server cannot use your resume cursor, it returns 410 RESYNC_REQUIRED up front, or sends a named resync frame and closes the stream. Refetch the snapshot and resume from its new cursor.
Long poll
Section titled “Long poll”GET /v1/workspaces/{ws}/wait?timeout=240s&cursor=<cursor>The maximum timeout is 270 seconds. answers=true waits for addressed answer evidence and needs a bound actor. A completed wait with matched:false is success.