Overview
NanoGPT supports streaming responses via Server-Sent Events (SSE). Streaming is available on these endpoints:
All SSE streams are delivered as a sequence of
data: frames separated by a blank line. Some endpoints also include an event: line to name the event type.
Recover billing after a disconnect
For Chat Completions, save the server-generatedX-Request-ID response header
before reading the stream. If the final usage chunk is lost, use that ID and the
same inference API key with Request Billing
to look up the recorded primary charge within its rolling 24-hour window.
Accounting token counts may be estimated after an interrupted stream.
Billing can take time to appear. A lookup 404 does not mean the request was
free; honor its Retry-After: 30 header. Looking up billing does not repeat
inference. Repeating inference can create another charge, even if you reuse
X-Request-ID: it is a correlation ID, not an idempotency key.
Enabling Streaming
Set"stream": true in the JSON request body.
Chat Completions:
stream is omitted or false, the endpoint returns a single JSON response.
Chat Completions Streaming (/v1/chat/completions)
Chat Completions streams OpenAI-style chat.completion.chunk objects.
Frame Format
Each SSE frame is a JSON object in adata: line:
delta.role: "assistant". Subsequent chunks typically include only incremental deltas like delta.content.
Finish Reasons
The final chunk has a non-nullfinish_reason:
stoplengthtool_callscontent_filter
End of Stream
After the final chunk, the stream terminates with:[DONE] as a literal string (do not JSON-parse it).
Reasoning / Thinking Deltas
Some models stream reasoning alongside content. Depending on the endpoint variant you use, the delta field may bereasoning or reasoning_content.
Example:
Tool Call Deltas
Tool calls stream viadelta.tool_calls[]. Accumulate function.arguments across frames for the same tool_calls[index].
Usage In Streaming
Usage is not included by default in streaming. To receive usage, set:usage field. (Some features, like prompt caching helpers, can cause usage to be included automatically.)
usage can include provider-dependent fields beyond basic token counters, including nested details and cache fields:
prompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details.cached_tokensprompt_tokens_details.audio_tokenscompletion_tokens_details.reasoning_tokenscompletion_tokens_details.audio_tokenscompletion_tokens_details.accepted_prediction_tokenscompletion_tokens_details.rejected_prediction_tokensreasoning_tokenscitation_tokensnum_search_queriescache_creation_input_tokenscache_read_input_tokensinput_tokens
x_nanogpt_pricing.inputTokens / x_nanogpt_pricing.outputTokens) for consistency.
x_nanogpt_pricing In Streaming
x_nanogpt_pricing is an extension object:
- In streaming: appears on the final chunk only
- In non-stream JSON responses: appears as a top-level field
amount?: numbercurrency?: stringerror?: { status?: number; message: string }(messageis sanitized)
cost?: numberpaymentSource?: stringinputTokens?: numberoutputTokens?: numbercacheCost?: numberbilledToTeam?: booleanbilledTeamId?: number | nullbilledTeamName?: string | null
Messages Streaming (/v1/messages)
The Messages endpoint streams Anthropic-style named SSE events. Each event includes an event: line and a data: line.
Typical sequence:
message_startcontent_block_startcontent_block_delta(repeated)content_block_stopmessage_deltamessage_stop
Tool Use
Tool calls appear astool_use content blocks. Tool input streams as input_json_delta fragments inside content_block_delta events.
Thinking Blocks
Thinking can appear as a separate content block type (thinking) before normal text blocks.
Usage
Usage information is included near the end of the stream (for example onmessage_delta), and includes input_tokens and output_tokens. When prompt caching is active, cache token fields may also appear.
Responses Streaming (/v1/responses)
Responses streams a sequence of typed objects. NanoGPT emits these as SSE data: frames containing JSON with a type field (for example response.created, response.output_text.delta, etc.).
Example:
response.completedresponse.incompleteresponse.failed
Tool Calls
Tool calls appear asfunction_call output items. Arguments stream via response.function_call_arguments.delta frames and finish with response.function_call_arguments.done.
Usage
Usage appears on the terminal event inside the fullresponse object (for example response.completed.response.usage).
Error Handling Notes
- If an error happens before streaming begins, you will receive a normal JSON error response with an HTTP status code.
- If an error happens mid-stream, the stream may end early. Your parser should handle EOF without a terminal marker as an error/retry condition.
Raw SSE Parsing Tips
When parsing SSE manually:- Events are separated by a blank line (
\\n\\nor\\r\\n\\r\\n). - A single event can include multiple
data:lines; concatenate them with\\nbefore parsing as JSON. - Handle
[DONE]as a sentinel string.