DocsAPI keys

Requests

Streaming

Set streaming and the reply becomes server-sent events. Text and reasoning arrive as separate bracketed runs so you can render them apart; tool calls arrive whole. The frames are the same whichever provider answers.

The shape of a stream

Each SSE event's name is the frame kind; its data is an envelope carrying either the frame or a failure. The HTTP status is 200 as soon as the stream opens, so everything after that point — including failure — is reported in the stream rather than in the status line.

{
  "model": "claude-sonnet-5",
  "streaming": true,
  "systemPrompt": "Answer in one sentence.",
  "messages": [{ "type": "user", "value": "What is the capital of France?" }],
  "parameters": { "maxTokens": 1024 }
}

Event names and discriminators

The SSE event: name and the type discriminator inside data.value use the same lower-camel spelling. event: streamStart carries "type":"streamStart". The error event carries no value object.

The envelope

Every data payload is a result envelope — success, code, and either value or message. One parse handles both outcomes, so a failure never needs a different code path than a success.

{ "success": true,  "code": 200, "value": { "type": "content", "value": "Paris." } }
{ "success": false, "code": 502, "message": "The provider closed the connection mid-answer." }

Frame kinds

event value.type Payload
streamStart streamStart model — canonical name, tier, publisher, and provider. The only place the resolved model appears.
thinkingStart thinkingStart None. Opens a reasoning run.
thinking thinking value — a text delta to append to the open reasoning run.
thinkingEnd thinkingEnd data — the provider state needed to replay this reasoning natively later.
contentStart contentStart None. Opens an answer run.
content content value — a text delta to append to the open answer run.
contentEnd contentEnd None. Closes an answer run.
tool tool value — the whole call at once: id, name, arguments. Never partial.
stop stop usage. Always last on a successful stream.
streamError streamError model — the provider that broke after producing output.
error — Terminal. success:false, an HTTP code, a message. No value.

A run can open and close more than once. A model that thinks, answers, thinks again and then calls a tool emits thinkingStart … thinkingEnd contentStart … contentEnd thinkingStart … thinkingEnd tool stop. Render each bracketed run as its own element rather than appending everything to one buffer.

Tool calls arrive whole

There are no argument deltas to reassemble.

event: tool
data: {"success":true,"code":200,"value":{"type":"tool","value":{"id":"toolu_01H","name":"lookupIncident","arguments":"{\"id\":\"INC-4412\"}"}}}

One parse, both outcomes

var envelope = JsonSerializer.Deserialize<Result<ModelResponse>>(sse.Data, JsonHelper.SerializerOptions);
if (!envelope.Success)
{
    throw new GatewayException(envelope.Code, envelope.Message);
}

switch (envelope.Value)
{
    case ModelResponse.StreamStart start: view.OpenSegment(start.Model); break;
    case ModelResponse.Thinking thinking:  view.Thinking.Append(thinking.Value); break;
    case ModelResponse.Content content:    view.Answer.Append(content.Value); break;
    case ModelResponse.Tool tool:          await Dispatch(tool.Value); break;
    case ModelResponse.StreamError failed: view.MarkHandover(failed.Model); break;
    case ModelResponse.Stop stop:          view.Finish(stop.Usage); break;
}

Assembling a turn from frames

The frames assemble back into exactly the messages the unary route would have returned: thinking frames between thinkingStart and thinkingEnd become one thinking message carrying that data, content frames become one content message, and each tool frame becomes a toolCall. Markers are not messages and are discarded.

If you persist conversations, store the assembled messages rather than the raw frames — that is the shape you send back, and it is what carries the provider state that lets reasoning replay natively.

How a stream ends

Exactly one terminal outcome closes a completed stream. An EOF without either means the stream was cut short and is a failure, not a finished answer.

Ending Meaning
stop The model finished. usage is attached.
error The request failed. code and message say how.
error with 502 The provider opened a stream and produced nothing, or ended without a terminal event.
EOF with neither Incomplete. Do not treat the text so far as a finished answer.

Disconnecting cancels the provider call rather than letting it run on.

Updated Oct 6, 2026
Esc