Events and replay
Synchronize clients with global and session-scoped server events.
Every event is an envelope with a server ID, kind, subject, timestamp, cursor information, and an event-specific payload.
{
"id": 42,
"globalEventId": 42,
"subjectRevision": 7,
"serverId": "build-box",
"kind": "session.updated",
"subjectId": "session-id",
"createdAt": "2026-07-10T12:00:00.000Z",
"payload": {}
}id is the cursor for the stream that delivered the envelope. globalEventId identifies the event
in the global shell log when it belongs there. subjectRevision is monotonic within one subject and
drives session-scoped replay. Optional cursor fields are absent when they do not apply.
Close the snapshot race
To load a snapshot without missing an event created during the request:
- Read
GET /v1/events/cursorand save itscursor. - Fetch the project, workspace, or session snapshot needed by the screen.
- Connect to
/v1/events/socket?since=CURSORor/v1/events?since=CURSOR. - Apply the replayed events, then continue with live events.
Capturing the cursor first guarantees that changes concurrent with the snapshot are replayed.
Persisted session history
GET /v1/sessions/{id}/transcript returns a session's stored transcript one page at a time,
starting from the newest items. Pass the page's nextBefore cursor as before to load older items. Read the tool calls, diffs,
plans, and other non-text events behind one item with
GET /v1/sessions/{id}/transcript/{itemId}/details.
Each page includes an eventCursor. Pass it as since to the session socket to continue with live
events. GET /v1/sessions/{id}/events is no longer a history API; it returns 410 Gone.
Server-Sent Events
GET /v1/events?since=CURSOR returns text/event-stream, replays persisted global events after the
cursor, and stays open for new events.
WebSockets
/v1/events/socket?since=CURSORstreams global shell events./v1/sessions/{id}/events/socket?since=CURSORstreams one session and uses its subject revision as the cursor.
Each WebSocket message is one JSON-encoded event envelope. Reconnect with the last processed cursor.
Passing Number.MAX_SAFE_INTEGER as since requests live events without replay.
The session socket sends a kind: "keepalive" envelope about every 25 seconds. Its id equals the
current session cursor; do not advance the saved cursor or render it as session activity. On session
sockets, the envelope id has already been rewritten to the subject-revision cursor.
Event handling should be idempotent. Replayed metadata events may replace cached resources, while append-only output should be deduplicated by its event cursor.