Skip to content

Streaming events

SSE event formats for the three protocols with stream: true, the keepalive comments HopBase inserts, and how errors are delivered mid-stream.

With "stream": true in the request body, Create chat completion, Create response and Create message return text/event-stream (SSE) instead. Event formats follow each protocol's official definition, so the streaming interfaces of the official SDKs work directly; HopBase only inserts keepalive comments and does not change event content.

POST/v1/chat/completionsPOST/v1/responsesPOST/v1/messages

Keepalive comments

While streaming, HopBase writes an SSE comment line between events about every 10 seconds, so intermediate proxies do not treat the connection as idle and drop it during long reasoning:

: hopbase-keepalive

Lines starting with a colon are comments in the SSE spec, and the official SDKs and standard SSE parsers ignore them. If you parse lines yourself, skip lines starting with : instead of parsing them as JSON. If the model produces no output for a long time (about 90–150 seconds, depending on the model), the gateway treats it as stalled and retries or returns an error; see Concurrency, timeouts, and billing.

Chat Completions

Each event is a single data: line containing a chat.completion.chunk object, with text in choices[0].delta.content; the stream ends with data: [DONE].

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[{"index":0,"delta":{"role":"assistant","content":"I am"},"finish_reason":null}]}

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":52,"total_tokens":66}}

data: [DONE]
FieldDescription
choices[].delta.contentText in this chunk
choices[].delta.tool_callsTool call arguments arrive in pieces; concatenate function.arguments by index
choices[].finish_reasonNon-null in the last chunk: stop / length / tool_calls
usageSent only if the request set stream_options.include_usage: true, in a final event with empty choices; omitting it does not affect billing

Responses

Each event consists of an event: line and a data: line; the type in data matches the event name.

event: response.created
data: {"type":"response.created","response":{"id":"resp_EXAMPLE","status":"in_progress"}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_EXAMPLE","output_index":0,"content_index":0,"delta":"I am"}

event: response.completed
data: {"type":"response.completed","response":{"id":"resp_EXAMPLE","status":"completed","usage":{"input_tokens":14,"output_tokens":58,"total_tokens":72}}}
EventDescription
response.createdThe response has started
response.output_text.deltaA piece of output text, in delta
response.output_text.doneA content part has finished; text holds the full text
response.completedFinished successfully; response.usage holds usage
response.failedFailed midway; the reason is in response.error.code: rate_limit_exceeded / server_error / invalid_prompt

Anthropic Messages

Event order: message_start → for each content block content_block_start / content_block_delta / content_block_stop → message_delta (with stop_reason and output usage) → message_stop.

event: message_start
data: {"type":"message_start","message":{"id":"msg_EXAMPLE","role":"assistant","model":"claude-sonnet-5","content":[],"usage":{"input_tokens":9,"output_tokens":1}}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello!"}}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":14}}

event: message_stop
data: {"type":"message_stop"}

Errors mid-stream

Once a stream starts producing output, the HTTP status is already 200. Later errors are delivered as events, and the status code never changes:

Chat Completions   data: {"error": {…}}      (no event: line)
Responses          event: response.failed
Anthropic          event: error

If a Claude stream breaks midway, HopBase sends one Anthropic error event and then ends the stream:

event: error
data: {"type":"error","error":{"type":"api_error","message":"Response stream interrupted, please retry"}}

Handle error events inside your read loop. Partial output cannot be resumed; reissue the whole request. Output produced before the interruption is billed by usage. For retry policy, see Error codes and retries.