Docs Menu & Search
Documentation
Streaming
Get chat replies token by token with Server-Sent Events.
Set "stream": true on /v1/chat/completions and the reply arrives as it is
generated, as Server-Sent Events
— the same format as OpenAI’s API, so any OpenAI SDK streams without changes. Streaming works on every
chat model.
curl -N https://api.nabh.cloud/v1/chat/completions \
-H "Authorization: Bearer nbh_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-oss-20b",
"stream": true,
"messages": [{"role": "user", "content": "Write a haiku about the monsoon"}]
}'from openai import OpenAI
client = OpenAI(api_key="nbh_your_key_here", base_url="https://api.nabh.cloud/v1")
stream = client.chat.completions.create(
model="gpt-oss-20b",
stream=True,
messages=[{"role": "user", "content": "Write a haiku about the monsoon"}],
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage: # last chunk: token counts for the whole request
print(f"\n{chunk.usage.prompt_tokens} in / {chunk.usage.completion_tokens} out")import OpenAI from "openai";
const client = new OpenAI({ apiKey: "nbh_your_key_here", baseURL: "https://api.nabh.cloud/v1" });
const stream = await client.chat.completions.create({
model: "gpt-oss-20b",
stream: true,
messages: [{ role: "user", content: "Write a haiku about the monsoon" }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
if (chunk.usage) console.log(`\n${chunk.usage.prompt_tokens} in / ${chunk.usage.completion_tokens} out`);
}The Event Stream
Each event is a data: line holding one JSON chunk; the text is in
choices[0].delta.content. The stream ends with data: [DONE].
data: {"choices":[{"index":0,"delta":{"role":"assistant","content":""}}], ...}
data: {"choices":[{"index":0,"delta":{"content":"Clouds"}}], ...}
data: {"choices":[{"index":0,"delta":{"content":" gather"}}], ...}
data: {"choices":[],"usage":{"prompt_tokens":14,"completion_tokens":21,"total_tokens":35}, ...}
data: [DONE]- Token usage comes last. nabh.cloud always asks for usage on streams, so the final chunk
(with an empty
choicesarray) carriesusagefor the whole request. You don’t need to sendstream_optionsyourself. - Reasoning models may send their thinking first in
delta.reasoning_contentbefore anydelta.content. Show it or skip it — onlycontentis the answer. - Cost. Non-streaming replies include
cost_inrandbalance_inrin the JSON body. A stream can’t carry them (the cost is known only at the end), so use theusagechunk with the model’s prices, or look the request up by its ID in your request log. - Request ID. Every response, streamed or not, has an
X-Request-IDheader. Keep it — it identifies the request in your request log and for support.
Timeouts and Stopping
A stream stays open as long as the model keeps sending; it is closed if the model goes quiet for 100 seconds
(504 GATEWAY_TIMEOUT before the first byte). Errors that happen before streaming starts (bad key, insufficient
credits, rate limit) come back as a normal JSON error — see Errors.