Skip to main content
Sessions

Stream Session Thread Events

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

HeaderRequiredDescription
AuthorizationYesBearer <PAT or SAT>
AcceptNotext/event-stream is recommended. The connection can still be established when omitted.
Last-Event-IDNoResume after this Thread Event.

Path parameters

ParameterTypeRequiredDescription
session_idstringYesSession ID with the sess_ prefix.
thread_idstringYesThread ID with the sthr_ prefix.
This endpoint has no query parameters and does not support 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

curl -N -X GET 'https://api.qoder.com/api/v1/forward/sessions/sess_xxx/threads/sthr_child_xxx/stream' \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Accept: text/event-stream" \
  -H "Last-Event-ID: evt_cursor_xxx"

Stream format

id: evt_xxx
event: agent.message
data: {"id":"evt_xxx","type":"agent.message","session_id":"sess_xxx","content":[{"type":"text","text":"Task received"}],"processed_at":"2026-06-22T11:05:00Z"}
The server periodically sends : 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 belong to the current Thread:
  • A cursor from another Session or Thread returns 404 thread_not_found.
  • A cursor the runtime identifies as invalid for this Thread returns 400 invalid_event_cursor.
  • If omitted, replay starts from the first Event in the Thread. No Events are missed, but already consumed Events are delivered again. Use the Event ID for idempotent processing.
  • 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-ID to resume from that point.

Errors

HTTPTypeCodeCondition
400invalid_requestinvalid_requestAn unsupported selector was provided.
400invalid_request_errorinvalid_event_cursorLast-Event-ID is invalid for the current Thread.
401authentication_errorauthentication_requiredThe PAT or SAT is invalid or expired.
404not_foundsession_not_foundThe Session does not exist or is not visible to the caller.
404not_found_errorthread_not_foundThe Thread does not exist, does not belong to the Session, or the cursor points to another Session or Thread.
502api_errorruntime_unavailableThe 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. 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.