Streaming API replies in every format
How to receive a reply as it is written in each format, Chat Completions, Responses, Messages and Gemini, with usage, errors mid-stream and tips.
With streaming, the reply arrives in parts as the model writes it, so your user sees text at once instead of waiting for the whole reply. Every format supports it, through Server-Sent Events: lines that start with data:, sometimes after an event: line.
Turn it on#
- Chat Completions, Responses and Messages: add
"stream": trueto the body. - Gemini: call
:streamGenerateContent?alt=sseinstead of:generateContent.
With cURL, add -N so the parts print as they arrive. In Python with requests, pass stream=True and read the lines with iter_lines. The official libraries handle all of this for you.
curl --request POST "https://api.5abeer.ai/v1/chat/completions" \
--header "Authorization: Bearer $KHABEER_API_KEY" \
--header "Content-Type: application/json" \
--data '{"model":"claude-sonnet-5.5","messages":[{"role":"user","content":"Write a product idea in one sentence."}]}'{
"id": "chatcmpl-9f2",
"object": "chat.completion",
"model": "claude-sonnet-5.5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 21,
"completion_tokens": 12,
"total_tokens": 33
}
}The key is read from KHABEER_API_KEY, so it never appears in your code.
What arrives in each format#
- Chat Completions:
data:lines, each achat.completion.chunkwith text inchoices[0].delta.content. It ends withdata: [DONE]. - Responses: named events,
response.created, thenresponse.output_text.deltaand the function call events. It ends withresponse.completed, which holds the full reply. - Messages:
message_start, then for each blockcontent_block_start,content_block_deltaandcontent_block_stop, thenmessage_delta. It ends withmessage_stop. - Gemini: each event is a partial reply in the same shape as the full one. The last event carries
finishReasonandusageMetadata.
Full examples of each stream are in the references: Chat Completions, Responses, Messages and Gemini.
Usage numbers#
- Chat Completions: add
"stream_options": {"include_usage": true}and the last part before[DONE]carriesusage, with an emptychoices. GPT models always send it, even without the option. - Responses:
usageis inresponse.completed. - Messages: the input usage is in
message_start, the output usage inmessage_delta. - Gemini:
usageMetadatais in the last event.
Errors mid-stream#
An error before the stream starts arrives as a normal JSON response with its HTTP status. Once the stream has started, the status is already 200, so the error arrives inside the stream:
- Chat Completions and Gemini: a
data:line with anerrorobject. - Responses: a
response.failedevent. - Messages: an
errorevent.
Each one carries the same code as a normal error; see Limits and error codes. Show the user what was written so far, and offer to try again.
Tips#
- Read the stream line by line and ignore empty lines and
event:lines you don't use. - Keep your timeouts generous: a long answer can stream for several minutes.
- Don't parse partial JSON from a tool call until its block ends; join the
argumentsorinput_json_deltaparts first.
Was this page helpful?