Skip to content
Skip to Content
Batchwell Docs

Streaming

Server-sent events, the final usage chunk, the in-band error event and keep-alives.

Set "stream": true to receive text/event-stream. Each event is a data: line with a JSON chunk in the OpenAI streaming format, and the stream ends with data: [DONE].

Output is screened in windows before it reaches you, so text arrives in bursts rather than token by token. Reasoning content (delta.reasoning_content) and tool calls (delta.tool_calls) are forwarded and screened the same way.

The last chunk before [DONE] always has empty choices and a usage object with cost_micro, whether or not you set stream_options.include_usage:

Text
data: {"choices":[],"usage":{"prompt_tokens":412,"completion_tokens":288,"cost_micro":470},"batchwell":{"generation_id":"gen_0193...","model":"batchwell/deepseek-v4.1-flash-uncensored","ai_generated":true}}

data: [DONE]

If something fails after output has started, we never switch models mid-answer. Instead you get one error event, then the usage chunk for what was delivered, then [DONE]:

Text
data: {"error":{"code":"upstream_error","message":"The provider closed the stream early.","generation_id":"gen_0193..."}}

A content block during streaming looks the same with "code": "content_blocked" and a class field. A request blocked while its output is being screened is billed for the input and the screening. You are never billed for any output, even output that had already streamed to you before the block.

While waiting for output we send an SSE comment every 15 seconds:

Text
: keep-alive

Ignore lines that start with :. Most SSE clients, including the OpenAI SDKs, already do.

If your client disconnects, we cancel the upstream request and bill only the tokens delivered so far.