Guides
Streaming compression
How the SSE streaming endpoint behaves today, how the SDK iterators consume it, and when to use plain compress instead.
Use compress_stream / compressStream to consume /api/compress/question-specific/stream as an iterator. The endpoint returns Server-Sent Events: data: frames only, no event:, id:, or retry: lines.
What streaming does today: the server compresses the full input, then sends the complete output as one final event. There is no token-by-token delivery yet, so streaming has no time-to-first-token advantage over the plain compress call. The iterator interface exists for forward-compatibility: if incremental delivery ships, code written against it won't need to change.
The wire protocol
On success the server sends one content event, then closes the connection:
If compression fails or exceeds the 120-second server-side budget after the stream opens, the server sends an error event, then closes:
Failures before the stream opens (bad key, validation, rate limit) arrive as normal HTTP error responses with the standard error envelope.
Consuming the stream
Iterate, concatenate content across chunks, and stop on done. Both SDKs yield each content event as {content, done: false}, then a final synthetic {content: "", done: true} when the stream closes. That pattern keeps working whether the output arrives in one event (today) or many (future).
The stream carries text only. For the token-accounting metadata (original_tokens, compressed_tokens, tokens_saved, actual_compression_ratio, duration_ms), use the non-streaming compress endpoint.
Handling errors
Handle errors by when they happen:
- Before the stream opens. The SDK's initial status check maps
4xx/5xxresponses to typed errors (RateLimitError,AuthenticationError,CompresrError, ...). Catch these to back off or re-auth. - After the stream opens. A server-side failure arrives as an
errorevent on the wire. The current SDK iterators skip events without acontentfield. So a mid-stream server error ends the iteration with whatever content arrived, possibly none, instead of raising. If an empty result is unacceptable, treat an empty buffer as a failure and retry. Transport-level drops do raise:httpx.HTTPErrorin Python,ConnectionErrorin TypeScript. - Retries.
RetryConfigapplies only to the initial connect, never to a mid-stream failure.retry_after/retryAfteris nullable; guard the sleep.
SDK caveats
- Python is sync-only.
compress_streamreturns aGenerator, not anAsyncGenerator. There is nocompress_stream_async. On FastAPI or asyncio, offload the loop withasyncio.to_thread, or use the TypeScript SDK, which is async-native. - The TypeScript timeout covers the whole stream. The client arms one
AbortControllerfortimeoutms from connect. It is not idle-based. Long compressions may need a largertimeoutat client construction. - Agent-layer streaming is not wired up.
client.messages.stream(...)andclient.chat.completions.stream(...)on the TS agent interfaces throwCompresrError('streaming not yet implemented', code: 'not_implemented'). The Python interfaces don't expose.stream(...)at all.compress_stream/compressStreamis the working streaming path.
When to use it
Use the plain compress call for almost everything today. It returns the same output plus the token-accounting metadata, and it works fully with typed errors and RetryConfig. Use the streaming endpoint only if you're deliberately writing against the iterator interface for forward-compatibility. Use compress_batch when you have many contexts to send at once.