Messages API streaming
Set "stream": true on POST /v1/messages to receive a standard
Anthropic Server-Sent Events stream. Existing Anthropic SDK
consumers work unchanged.
Request
curl -N https://api.kindo.ai/v1/messages \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $KINDO_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-5-20250929", "max_tokens": 512, "stream": true, "messages": [ { "role": "user", "content": "Write a haiku about observability." } ] }'Kindo returns Content-Type: text/event-stream and emits
Anthropic’s event sequence verbatim.
Event types
| Event | Meaning |
|---|---|
message_start | Initial message metadata. |
content_block_start | Start of a streamed content block. |
content_block_delta | Incremental content chunk. |
content_block_stop | End of a content block. |
message_delta | Updated usage or stop-reason data. |
message_stop | End of the stream. |
error | Stream interruption after the stream has started. |
ping | Keepalive heartbeat; safe to ignore. |
Example stream
event: message_startdata: {"type":"message_start","message":{"id":"msg_01","type":"message","role":"assistant","content":[],"model":"claude-sonnet-4-5-20250929","stop_reason":null,"usage":{"input_tokens":12,"output_tokens":1}}}
event: content_block_startdata: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_deltadata: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Logs flow through"}}
event: content_block_deltadata: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the gate;"}}
event: content_block_stopdata: {"type":"content_block_stop","index":0}
event: message_deltadata: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":32}}
event: message_stopdata: {"type":"message_stop"}SDK consumption
import osfrom anthropic import Anthropic
client = Anthropic(base_url="https://api.kindo.ai", api_key=os.environ["KINDO_API_KEY"])
with client.messages.stream( model="claude-sonnet-4-5-20250929", max_tokens=512, messages=[{"role": "user", "content": "Write a haiku."}],) as stream: for text in stream.text_stream: print(text, end="", flush=True)import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({ baseURL: 'https://api.kindo.ai', apiKey: process.env.KINDO_API_KEY});
const stream = await client.messages.stream({ model: 'claude-sonnet-4-5-20250929', max_tokens: 512, messages: [{ role: 'user', content: 'Write a haiku.' }]});
for await (const event of stream) { if ( event.type === 'content_block_delta' && event.delta.type === 'text_delta' ) { process.stdout.write(event.delta.text); }}Pre-stream errors
If the upstream request fails before streaming begins, Kindo returns a normal HTTP error response with Anthropic’s JSON envelope — no SSE switch. See Errors.
Mid-stream errors
Once the SSE has started, the outer HTTP status is committed at
200. Stream errors arrive as an event: error SSE frame
in place of message_stop:
event: errordata: {"type":"error","error":{"type":"overloaded_error","message":"upstream overloaded"}}Treat any error SSE event as terminal — no message_stop
follows and the response will not resume.
See also
- Quickstart — non-streaming round trip.
- Request shape — every field Kindo honors.
- Tool use — streaming tool-call events.
- Errors — pre-stream error envelopes.