Stream public Events from a Forward Session Thread over Server-Sent Events.
GET /api/v1/forward/sessions/{session_id}/threads/{thread_id}/stream
Request headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer <PAT or SAT> |
| Accept | No | text/event-stream is recommended. The connection can still be established when omitted. |
| Last-Event-ID | No | Resume after this Thread Event. |
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| session_id | string | Yes | Session ID with the sess_ prefix. |
| thread_id | string | Yes | Thread ID with the sthr_ prefix. |
type, types, types[], include_tool_calls, include_thinking, or event_deltas[]. Passing any of these parameters, even with an empty value, returns 400 invalid_request without opening the downstream stream.
Example request
Stream format
: heartbeat comment lines to keep the connection alive. Consume every frame, filter presentation locally, and persist the latest SSE id for reconnection.
Last-Event-ID
Last-Event-ID must be usable for the current Thread:
- A cursor that belongs to another Thread, is not visible to the current caller, or cannot be used in the current state returns
400 invalid_event_cursor. - When the Thread exists but the Event referenced by the cursor is no longer available, it returns
404 event_cursor_not_found. - If omitted, delivery starts at the tail of the Thread event stream at connection time. Only Events created after the connection is established are delivered; historical Events are not replayed. To retrieve historical Events or Events created while disconnected, first query List Thread Events, and then establish the stream with
Last-Event-ID. - An SSE connection can close because of gateway timeouts, server restarts, or similar conditions. The server does not guarantee that a connection remains open indefinitely. Clients must implement their own reconnection and retry logic. When reconnecting, send the last received Event ID in
Last-Event-IDto resume from that point.
Errors
| HTTP | Type | Code | Condition |
|---|---|---|---|
| 400 | invalid_request | invalid_request | An unsupported selector was provided. |
| 400 | invalid_request_error | invalid_event_cursor | Last-Event-ID is invalid for the current Thread. |
| 401 | authentication_error | authentication_required | The PAT or SAT is invalid or expired. |
| 404 | not_found | session_not_found | The Session does not exist or is not visible to the caller. |
| 404 | not_found_error | thread_not_found | The Thread does not exist or is not visible to the current caller. |
| 404 | not_found_error | event_cursor_not_found | The Thread exists, but the Event referenced by Last-Event-ID is no longer available. |
| 502 | api_error | runtime_unavailable | The Thread runtime service is unavailable. |
Thread discovery and recovery
The parent Session history or stream exposes child Thread creation and state changes through session.thread_created, session.thread_status_running, session.thread_status_idle, session.thread_status_rescheduled, and session.thread_status_terminated.
After receiving session.thread_created from the parent Session stream, use that Event ID as the first Last-Event-ID for the child Thread stream to avoid missing Events produced between discovery and connection.
The event_cursor_not_found error message is Event '<event_id>' was not found. When this error occurs, re-query the Thread event history and establish a new connection; it does not mean the Thread was deleted.
If you discover an active child Thread through the Thread list, first read its Event history and then open the stream with the response last_id. After a Thread is archived, you cannot open or resume its stream. Recover lifecycle Events from the parent Session history or stream, and retrieve final state with the get Thread endpoint.

