> ## Documentation Index
> Fetch the complete documentation index at: https://dev-docs.altrum.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming

> Stream replies from the AI Gateway as server-sent events, and handle an error that arrives after the stream has started.

Every format streams as it does with the provider directly. Ask for a stream the way the API you call expects, and the events arrive in that API's format.

| Format | How to ask | How it ends |
| - | - | - |
| OpenAI | `"stream": true` in the body | `data: [DONE]` |
| Anthropic | `"stream": true` in the body | a `message_stop` event |
| Gemini | call `:streamGenerateContent` | the last chunk |

```bash theme={null}
curl -N https://api.altrum.ai/v1/chat/completions \
  -H "Authorization: Bearer $ALTRUM_VIRTUAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-4o-mini", "stream": true, "messages": [{"role": "user", "content": "Count to three."}]}'
```

```text theme={null}
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"One"}}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":", two, three."}}]}

data: [DONE]
```

## Errors in a stream

An error found before the first event comes back as an ordinary JSON error with its real status, so your SDK raises it as usual. See [Errors](/api-reference/errors).

An error after the stream has started cannot change the status, which was already sent. It arrives as an `error` event, with the same body an ordinary error would have:

```text theme={null}
event: error
data: {"type":"guardrail_check_failed","is_gateway_error":true,"status_code":503,"error":{"type":"guardrail_check_failed","code":"upstream_unavailable","message":"..."},"request_id":"..."}
```

The official SDKs raise this as an error mid-stream. If you read the stream yourself, watch for `event: error` and stop.

## Guardrails on replies

When a guardrail on replies can block or mask, Altrum holds the stream until the whole reply has been checked, then sends it. The first words arrive later, and unchecked text never reaches your application. When every guardrail on replies only logs, the reply streams as the model writes it and the last event waits for the check. See [Guardrails at runtime](/guardrails/at-runtime#streaming).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.