Core API
Streaming
Consume OpenAI-compatible server-sent events without dropping usage or terminal frames.
On this page
This page is for developers building low-latency output or a typewriter interface with Chat Completions.
Set stream: true to receive server-sent events. The gateway forwards SSE bytes without reframing them. If you omit stream_options, the gateway adds {"include_usage":true} so the final chunk can report usage.
Inspect raw SSE with curl#
curl -N https://api.clssai.com/v1/chat/completions \
-H "Authorization: Bearer $CLSSAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/gpt-5.4-nano","messages":[{"role":"user","content":"Count to three."}],"stream":true}'Each event carries a data: line. Append choices[0].delta.content when present. The terminal chunk carries usage. Depending on the upstream provider, it may repeat the final choice or send choices: [], so always check the array length before indexing. After that chunk, data: [DONE] ends the stream.
data: {"choices":[{"index":0,"delta":{"content":"One"},"finish_reason":null}],"usage":null}
data: {"choices":[{"index":0,"delta":{"content":""},"finish_reason":"stop"}],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}
data: [DONE]Stream with Python#
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.clssai.com/v1", api_key=os.environ["CLSSAI_API_KEY"])
stream = client.chat.completions.create(
model="openai/gpt-5.4-nano",
messages=[{"role": "user", "content": "Count to three."}],
stream=True,
)
for chunk in stream:
if chunk.choices:
print(chunk.choices[0].delta.content or "", end="", flush=True)
if chunk.usage:
print(f"\nUsage: {chunk.usage}")Stream with JavaScript#
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.clssai.com/v1",
apiKey: process.env.CLSSAI_API_KEY,
});
const stream = await client.chat.completions.create({
model: "openai/gpt-5.4-nano",
messages: [{ role: "user", content: "Count to three." }],
stream: true,
});
for await (const chunk of stream) {
if (chunk.choices.length > 0) process.stdout.write(chunk.choices[0].delta.content ?? "");
if (chunk.usage) console.log("\nUsage:", chunk.usage);
}Cancellation and retries#
Cancel with the SDK abort mechanism or an AbortController. Once any streamed bytes have reached the client, do not retry transparently: a second request can duplicate output or work. Retry only failures that occur before the first event, and apply bounded exponential backoff.
Common mistakes#
- Check for an empty
choicesarray before accessingchoices[0]. - Do not stop before reading the final usage chunk and
[DONE]. - Do not retry after the stream has started.
- Include
/v1in the OpenAI SDK base URL, but omit/v1from the Anthropic SDK base URL. - Run streams from your server, not browser JavaScript.
- Preserve full
author/model:freeandauthor/model:batchIDs. - Use
cf-raywhen tracing an inference request.
Find answers to common questions or diagnose a failed request.
Frequently asked questions →Troubleshoot errors →