Skip to main content
Every error body is JSON and carries a request_id. Include it when you contact support — it is what lets us find your call in our logs.

Retry only what retrying fixes

400 and 401 are deterministic — the same request will fail identically forever. Read the message instead of looping. 502 and 5xx are worth retrying, with backoff.

A 403 that is not from us

A 403 whose body is not JSON did not come from the API. It is a request filter reacting to your HTTP client’s default User-Agent — not an authentication problem, though it reads like one and sends people hunting a bad key.Our errors are always JSON with a request_id. Setting any User-Agent clears it:
This affects a few libraries’ defaults, notably Python’s stdlib urllib. requests, curl, node-fetch, axios, okhttp and Go’s net/http are unaffected.

Check the status before you write the body

On any error the body is JSON, not audio — and curl --output, wget -O or a naive open(f,"wb").write(r.content) will happily write that JSON into your .pcm file. Converting it yields a silent 0-second clip, so a 400 shows up as “the audio came back empty” and sends you debugging the wrong thing.

On the WebSocket

Errors arrive as frames and the socket stays open — correct the frame and send it again: