Endpoints
Streaming
Stream model output token by token with server-sent events by setting stream to true, and read the chunks in your app as they arrive.
Try it in the playgroundSet stream: true on Chat completions, Responses or Completions to receive tokens as they are generated. The response uses server-sent events (Content-Type: text/event-stream). api14 passes the upstream bytes through to you as they arrive and does not buffer them.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api14.com/api/v1",
apiKey: process.env.API14_API_KEY,
});
const stream = await client.chat.completions.create({
"model": "openai/gpt-5-mini",
"messages": [
{
"role": "user",
"content": "Explain vector databases in two sentences."
}
],
"stream": true
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
Event format
Each event is a data: line holding a JSON chunk. The stream ends with data: [DONE].
data: {"id":"gen-1760000000-abc","object":"chat.completion.chunk","model":"openai/gpt-5-mini","choices":[{"index":0,"delta":{"role":"assistant","content":"Hel"}}]}
data: {"id":"gen-1760000000-abc","object":"chat.completion.chunk","model":"openai/gpt-5-mini","choices":[{"index":0,"delta":{"content":"lo!"}}]}
data: {"id":"gen-1760000000-abc","object":"chat.completion.chunk","model":"openai/gpt-5-mini","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":3,"total_tokens":13,"cost":0.0000085}}
data: [DONE]
- The last chunk before
[DONE]carriesusage, includingcostin USD. You don't needstream_options.include_usage. Usage reporting is always on. - The
idis the same in every chunk. It is the generation id you can pass to Generation lookup. - Some providers send SSE comment lines (lines starting with
:) to keep the connection alive. SSE clients and the OpenAI SDKs ignore them. If you parse the stream yourself, skip lines that start with:.
Billing for streams
The gateway reads the final usage chunk while forwarding the stream and debits your balance once the stream closes.
Disconnecting does not cancel the bill. If you close the connection before the stream finishes, the upstream provider may keep generating and still charge for it. In that case api14 reads the cost from the generation record. To limit the cost, set max_tokens.
Errors during a stream
Errors before the first byte, such as an invalid key, a low balance or an unknown model, return a normal JSON error with a 4xx or 5xx status. See Errors. If a provider fails mid-stream, the stream may end with a chunk that contains an error object and finish_reason: "error":
{ "error": { "code": 502, "message": "Provider disconnected" }, "choices": [{ "delta": { "content": "" }, "finish_reason": "error" }] }
Always check finish_reason on the last chunk.
Tips
- Proxies and serverless platforms sometimes buffer responses. Disable response buffering (e.g.
X-Accel-Buffering: noon nginx) if you relay the stream to browsers. - Tool calls stream as
delta.tool_callsfragments. Join theargumentsstrings byindexbefore parsing them. See Tool calling. - Reasoning models stream their reasoning in
delta.reasoningbefore the answer. See Reasoning.