Turning it on
Add "stream": true to the body of a request to POST /api/v1/responses. Everything else about the request stays the same. The response comes back as text/event-stream rather than JSON.
curl -N https://evaesi.dev/api/v1/responses \ -H "Authorization: Bearer $EVAESI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "instant", "prompt": "Explain rungs in two sentences.", "stream": true }'Events
Two event types are sent. Each carries a JSON payload with the text so far in content and a done flag.
| Event | Meaning |
|---|---|
response.output_text.delta | A new piece of the answer. Append it to what you have. |
response.completed | The answer is finished. No further events follow. |
event: response.output_text.deltadata: {"content":"Rungs are bytes","done":false}event: response.output_text.deltadata: {"content":". You are billed for","done":false}event: response.completeddata: {"content":"","done":true}Treat response.completed as the only signal that the answer is whole. A connection that closes without it was cut short, and the text you have is partial.
Headers
Headers are sent when the stream opens, before any content exists. That means the output and total rung counts cannot be included: they are not known yet. You get the input cost and your rate limit position up front.
| Header | Meaning |
|---|---|
x-evaesi-input-rungs | Rungs charged for the prompt. |
x-evaesi-region-count | Regions activated, when region reporting was requested. |
x-ratelimit-limit | Requests allowed in the current window. |
x-ratelimit-remaining | Requests left in the current window. |
Errors mid stream
A request that fails before the stream opens returns a normal HTTP error, documented on the errors page. A failure after the stream has opened cannot change the status code, because 200 has already been sent. It arrives as an error frame instead.
event: error
data: {"error":{"code":"EVA_UNAVAILABLE","message":"Model unavailable."}}This is the case most integrations forget. A stream that fails halfway looks like a successful request to any client that only checks the status code, so handle the error frame explicitly.
Billing
Streaming costs the same as not streaming. You are billed for the rungs you sent and the rungs that came back, whether they arrived in one piece or many. A stream you disconnect from early still bills for what the model produced before you left.
Example
The samples above open a stream and print each frame as it lands. For anything real you will want to parse the data: lines as JSON and accumulate content, stopping when you see response.completed.