VanaAPI

← Escritos

Server-Sent Events: Stream Responses Step by Step

Formatos de comunicaçãoEN2026-10-25

A streaming integration needs more than a request flag. It needs a reader that understands event boundaries, a renderer that accepts partial output, and a clear distinction between completion and interruption. This walkthrough builds those pieces around OpenAI-compatible Chat Completions.

§ Step 1: Choose one protocol

Start with Vana API’s OpenAI-compatible interface and configure your SDK’s base URL to use the api.vanaapi.com host with the /v1 suffix over HTTPS. Vana API also provides native protocol entry points, but keep this first implementation on one interface rather than mixing request formats. ([vanaapi.com](https://vanaapi.com/))

Create a Vana API account, obtain your credentials, and keep the API key on your application server. Choose Gemini 3.1 Pro for this walkthrough, using its exact API model identifier from your account rather than assuming the display name is the request value. The model appears in Vana API’s published lineup. ([vanaapi.com](https://vanaapi.com/))

§ Step 2: Request a streaming response

Prepare a short prompt, such as “Explain database indexing in three sentences.” In the Chat Completions request, provide your model identifier and messages, then set stream to true. Consume the returned chunks incrementally instead of expecting one completed message object. ([platform.openai.com](https://platform.openai.com/docs/api-reference/chat-streaming))

For a raw HTTP implementation, use a POST request with your authorization header and JSON body. Read the response body as a stream rather than calling response.json(), which expects a complete JSON document. Check response.ok before beginning the streaming reader. Fetch supports both request configuration and incremental response consumption. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch?utm_source=openai))

§ Step 3: Parse complete SSE events

Server-sent events use UTF-8 text with the text/event-stream media type. A blank line separates events. Within an event, data: introduces payload text; multiple data lines are joined with newline characters. Lines beginning with a colon are comments, not model output. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events?utm_source=openai))

If your SDK handles SSE framing, use its iterator. Otherwise, implement a buffered parser with these responsibilities:

  • Decode incoming bytes incrementally so split UTF-8 characters survive.
  • Retain unfinished text between network reads.
  • Recognize SSE line endings and extract complete events.
  • Join data fields before interpreting their payload.

Do not treat each network read as an event. The response body exposes transport chunks, while SSE defines its own message boundaries. Keep decoding and event parsing as separate stages. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch?utm_source=openai))

§ Step 4: Assemble the assistant’s output

For Chat Completions chunks, append text from choices[0].delta.content when present. Do not expect every chunk to contain printable text: deltas can carry role information or tool-call fragments, and a usage chunk can have an empty choices array. ([platform.openai.com](https://platform.openai.com/docs/api-reference/chat-streaming))

Maintain one accumulated answer and render incremental updates from it. For the initial test, display plain text. Keep tool-call assembly separate from visible prose, and validate completed arguments before executing any tool. The API represents streamed tool calls through indexed delta fields. ([platform.openai.com](https://platform.openai.com/docs/api-reference/chat-streaming))

§ Step 5: Handle completion and interruption

In the OpenAI Chat Completions convention, data: [DONE] terminates the stream. Check for that sentinel before JSON parsing. Also inspect finish_reason: a length-limited answer is not equivalent to a natural stop. These are protocol-specific signals, not universal SSE rules. ([platform.openai.com](https://platform.openai.com/docs/api-reference/chat-streaming))

Add a Stop control using AbortController for your fetch request. Calling abort() can terminate the request and response-body consumption. Treat that action as cancellation in your interface, not as successful completion. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/AbortController))

If a connection ends unexpectedly, preserve the partial answer and label it incomplete. Avoid silently retrying and appending a second generation to the first. Make retry an explicit application decision.

§ Step 6: Verify before deployment

Run the same prompt through your deployed application, not only a local client. Use this acceptance checklist:

  • Text becomes visible before generation finishes.
  • Split events and multibyte characters parse correctly.
  • Cancellation leaves a clearly labeled partial answer.
  • Unexpected disconnections never appear as successful completion.
  • Empty or metadata-only chunks do not crash rendering.

If your selected route supports stream_options.include_usage, request it and record the final usage chunk separately. An interrupted stream may never deliver that chunk, so missing usage must remain unknown rather than becoming zero. ([platform.openai.com](https://platform.openai.com/docs/api-reference/chat-streaming))