- Concurrent streams: how many synthesis requests can be in flight at once.
- Requests per second (rps): how many public API requests the workspace can make in each one-second window.
Limits by plan
Enterprise contracts can set different limits. The
RateLimit-Policy header (below) always shows
the limits that apply to your workspace.
What counts as a stream
A concurrent-stream slot is held for the whole life of one synthesis:POST /voices/{id}/speak: until the audio has been returned.POST /voices/{id}/stream: until the event stream ends.- The OpenAI-compatible
POST /openai/audio/speech: until the audio has been returned. - Realtime WebSocket: from the handshake until the socket closes, however many contexts it runs. Run several contexts on one socket rather than opening more sockets.
When you hit a limit
The request is refused with429 Too Many Requests, a Retry-After header (seconds), and the
standard error envelope with a code:
A refused request is not billed. On the WebSocket, a refused handshake gets the same
429 and body
before the upgrade, so the socket never opens.
503 with code upstream_busy is different: it means the synthesis service itself is at
capacity, not that you are over your plan. Back off and retry it the same way.Rate limit headers
Responses from the public API carry the IETF RateLimit header fields:RateLimit-Policylists your limits:qis the quota,qu="concurrent-requests"marks the concurrency limit, andw=1is the one-second rps window. A policy appears only when your plan has that limit.RateLimitreports what is left:ris the remaining quota andtthe seconds until the rps window resets. Theconcurrencyitem appears on synthesis requests and WebSocket handshakes, and counts the slots still free after this request took one.
Retry-After and X-Request-Id.
Backing off
- On
429, wait at least theRetry-Afterseconds before retrying. - Retry with exponential backoff plus jitter (for example about 1s, 2s, 4s) and stop after a few attempts.
- Watch
RateLimitand slow down whenrreaches0, instead of waiting for a429. - Cap your own concurrency at your plan’s concurrent-streams limit, for example with a small worker pool or semaphore, and queue the rest.
- For realtime use, keep one WebSocket open and run several contexts on it.

