Skip to main content
GET /v1/runs/{run_id}/stream returns a run’s stored state as server-sent events (SSE). Read this page if your stack already consumes text/event-stream, or if you are deciding between the stream and polling. It is not token streaming: the answer arrives once, whole, after the run has settled.

What the stream is

  • A snapshot. The server reads the stored run, writes one or two events, and closes the response. It does not wait for a pending run to settle.
  • Read-only. It never calls a model and never costs anything.
  • Whole answers only. There are no partial-answer events. A verdict is only valid once the whole document has passed your schema, and a decision is only valid once every question is read, so OpenType never sends part of either.
  • No resume. Frames carry no id: and no retry: field, and the server ignores Last-Event-ID. To observe a run again, request the route again.
It needs the runs_read scope, like GET /v1/runs/{run_id}.

Response headers

Events

Each frame is one event: line, one data: line holding a single line of JSON, and a blank line. A completed run sends both events:
A failed run sends both events, with no kind and no answer:
A pending run sends only the first event, then the response closes:
The answer in terminal has the stored shape, the same as GET /v1/runs/{run_id}: a decision carries answers, draws and read, without model, stages or the thought fields. The stream carries no usage or cost_micros; read those with GET /v1/runs/{run_id}. Read fields by name. The order of keys inside data is not part of the contract.

Read it

The response ends on its own, so read the whole body and split it into frames. You do not need an SSE library.

With EventSource

A browser EventSource reconnects automatically when the response closes, so it would request the snapshot again and again. If you use one, close it after the first terminal event, or after the first state event when the run is pending. EventSource also cannot send an Authorization header, and an API key does not belong in a browser. Read the stream from your server with the code above.

Waiting for a pending run

The stream does not wait. To wait for a run that is pending, request it again after a delay, with the same limits as polling: a run still pending after its deadline (at most 150 seconds after it was sent) failed before a model call and will not settle. Send the original request again with a new Idempotency-Key. Polling has the loop and the details.

When to use it

POST /v1/runs already waits and returns the answer. Use the stream, or GET /v1/runs/{run_id}, when you hold a run_id but not the answer: after a client timeout, after a 202 on a replayed key, or in a different process from the one that created the run.

Errors

Errors before the stream starts are ordinary JSON errors, the same as for GET /v1/runs/{run_id}:
  • Polling - read a run by id and tell a slow run from one that will stay pending.
  • Idempotency - why a replayed key can answer 202 with a pending run.
  • Runs - run states and what a run returns.
  • Errors - the error envelope and every code.
  • API reference - the stream route in the full spec.