Your first streamGenerateContent lap
A streaming response lets your application show generated text while the model is still working. Instead of waiting for one complete answer, you receive a sequence of smaller updates. For Gemini’s native API, streamGenerateContent requests that streaming behavior, and the alt=sse query parameter asks for the response in server-sent events format.
The two pieces do different jobs: streamGenerateContent selects the streaming operation; alt=sse selects the event format. Understanding that distinction makes the request easier to build and the response easier to debug.
The request shape before the green light
A native Gemini streaming request uses POST and a route shaped like /v1beta/models/MODEL_ID:streamGenerateContent?alt=sse. Replace MODEL_ID with the exact model identifier supported by your provider. Gemini 2.5 Flash is a useful model to look for in the provider’s model list; copy its API identifier rather than assuming the display name belongs in the URL.
The request body supplies the conversation content. For a first test, keep it small: {"contents":[{"role":"user","parts":[{"text":"Explain a rainbow in three short sentences."}]}]}. Send it with Content-Type: application/json. You can also request Accept: text/event-stream, but that header does not replace alt=sse.
Authentication depends on the service receiving the request. Direct Google credentials and relay credentials are not interchangeable. Keep your key on your server, follow your provider’s authentication instructions, and avoid putting secrets into browser code, screenshots, or shared logs.
Putting SwiftRelay on the request route
SwiftRelay is a practical option when you want pay-as-you-go access to Gemini alongside other model families, with billing per token. Its API host is https://api.fastapirelay.com. Sign up for SwiftRelay to try the flow with the small gift credit provided to new accounts.
For a native Gemini request, confirm the supported model identifier, native route, and authentication requirements in SwiftRelay’s current documentation. Do not assume an OpenAI-compatible chat endpoint accepts streamGenerateContent. OpenAI-compatible SDKs use the host with /v1, while Gemini CLI takes the bare host; those configuration conventions do not make the two API formats interchangeable.
Reading the data events without guessing
A successful SSE response normally has Content-Type: text/event-stream. Its body is text containing events separated by blank lines. An event can carry a data: field whose value is a JSON response object. The data: prefix belongs to SSE framing; it is not part of the JSON.
- Collect a complete event first. A network read can contain half an event, several events, or even part of a character. Use a streaming text decoder and an SSE parser.
- Parse the event payload. Join multiple data fields according to SSE rules, then parse the assembled payload as JSON.
- Extract text carefully. Text commonly appears under candidates[].content.parts[].text. Check that each level exists, and handle non-text parts separately.
- Append text for the selected candidate. Do not mix alternative candidates together, and do not expect each event to contain a complete sentence.
For a terminal smoke test, curl’s --no-buffer option helps avoid output buffering by the client. It does not parse events or guarantee that every displayed chunk corresponds to one model token.
Finishing the stream without losing state
Inspect candidate finish reasons and any available usage metadata, not just the text. Some responses contain metadata without printable content. Safety-related outcomes may also leave you with little or no generated text, so your interface needs a clear empty-result state.
Do not assume Gemini sends the OpenAI-style [DONE] marker. Follow the native response format and track stream completion. A disconnected connection is not proof that generation finished successfully; preserve partial output and label interrupted responses clearly.
The streamGenerateContent launch checklist
Before shipping, test an ordinary answer, an empty response, an invalid key, and an interrupted connection. Check HTTP status before parsing SSE, because errors may arrive as ordinary JSON. If you retry after displaying partial text, replace or separate the new attempt rather than silently appending a restarted answer. Finally, remember that streaming changes delivery, not token accounting: displayed fragments are not a reliable usage meter.