Errors
HTTP errors return a JSON body with a code field. Retry only what is marked retryable.
HTTP errors
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | API key missing, malformed, or revoked. |
INVALID_INPUT | 400 | Malformed request body. |
INSUFFICIENT_BALANCE | 402 | Not enough balance to open a stream. |
CONCURRENCY_LIMIT | 429 | Account-wide limit (all keys share it), the global cap, or a regional pool share. There is no per-key cap. |
NOT_FOUND | 404 | Recording or stream does not exist for this user. |
ADMISSION_DISABLED | 503 | API admission is off on this deployment. |
REGION_UNAVAILABLE | 503 | No healthy node in the requested region. When region is omitted, every region was unavailable. |
WebSocket close codes
Every retryable close code resolves the same way: call connect again and open a new stream. There is no reconnect path that preserves a stream.
| Code | Meaning | What to do |
|---|---|---|
4001 | Token invalid or expired | Call connect again for a fresh token. |
4003 | sessionId mismatch | Do not retry. Fix the client. |
4004 | Session is not on this node | Call connect again for a fresh url. |
4010 | Balance exhausted | Top up, then call connect again. |
4011 | Concurrency limit reached | Back off, then call connect again. |
1003 | Protocol error | Do not retry. Fix the client. |
1012 | Gateway restarting | Call connect again for a fresh url. |
4012 | Max duration (4 hours) | Call connect again for a new stream. |
4013 | Idle timeout: 60 seconds with no audio. Ping does not reset it. | Send audio, or call connect again. |
4014 | Billing was not confirmed | Call connect again after the account can be charged. |
4015 | API key revoked | Create a new key, then call connect again. |
4016 | Client reads too slowly | Call connect again for a new stream. |
Each stream is rounded up to whole minutes of accepted audio at settlement. A reconnect creates a separately billed stream. No accepted audio means no charge.