Error handling
API errors use a consistent JSON format with one of the HTTP status codes documented below. An unknown path or unsupported method returns plain text instead, as described in the next section.
Error Response Format
An enveloped error response follows this structure:
Two responses are not JSON. If the path you requested does not exist, or exists but does not accept the method you used, you get a plain-text 404 Not Found or 405 Method Not Allowed instead of the envelope below — so do not assume every error body parses as JSON. A 404 about a resource, such as Session not found or Room not found, does use the envelope.
error— a human-readable, English-only message whose phrasing may change. Use it for display and diagnostics.code— a stable, machine-readable class from a small closed set (see Error Codes). Branch on this. New codes are only added with a documented API change.
Successful responses omit the error and code body fields and use the response shape documented for the endpoint. Depending on the endpoint, a 2xx response includes "success": true or uses a bare result shape. Determine success from the HTTP status code, not the success field.
Error Codes
The code field is the stable contract for programmatic error handling. The closed set contains twelve classes, mapped to the HTTP status code(s) below.
The set is closed. These twelve codes are the complete list. Branch on code for programmatic handling and fall back to the HTTP status class for anything you do not special-case; do not pattern-match the error string.
W3C Trace Context
The API supports the W3C Trace Context traceparent and tracestate request headers. The gateway validates their W3C shape and ignores malformed values.
A valid incoming context is linked to a new server-owned trace with its own trace identifier.
Every response carries the server-owned traceparent. Log that response header with your request context and quote it when reporting a problem. The same trace is propagated through gateway commands and webhook delivery.
Transport. The Voice API is machine-to-machine (M2M), server-to-server HTTP/JSON: there is no CORS support and the gateway is not callable from a browser. Send Content-Type: application/json on requests with a JSON body. Request-body limits are documented under 413 Payload Too Large.
HTTP Status Codes
400 Bad Request
The request is malformed or contains invalid parameters. This includes a missing
or malformed Authorization credential; a syntactically valid credential with
an invalid API key returns 401 Unauthorized instead.
401 Unauthorized
Authentication credentials are missing or invalid.
403 Forbidden
You are authenticated, but the action is not permitted. A 403 indicates a policy or resource limit on a resource your application owns. A resource owned by another application returns 404 (see 404 Not Found).
404 Not Found
The requested resource does not exist. Sessions and rooms owned by another application also return 404.
409 Conflict
The request conflicts with the current state of the resource.
422 Unprocessable Entity
The request was well-formed but could not be processed. It is produced when an Idempotency-Key is reused with a different request body.
413 Payload Too Large
Two distinct conditions return 413, each with its own code. payload_too_large means the request body is too big; result_set_too_large means the response a list endpoint would return is too big. Branch on the code field to tell them apart.
For payload_too_large: the request body exceeds the per-route size limit. The default limit is 1 MiB; the per-session command route (POST /v1/sessions/{uuid}/{command}) has a 64 KiB limit.
For result_set_too_large: list endpoints (sessions, rooms, members) return all matching items by default. A full matched set above 50,000 items returns this error. A smaller limit does not avoid the check because it applies to the full matched set first. Narrow a sessions query with its filters. Room and member list endpoints have no narrowing filter.
415 Unsupported Media Type
The request was sent without a Content-Type header, or the header value is not application/json. Routes that decode a JSON body require the header on every request that carries a body. Action endpoints that take no body (e.g. DELETE /rooms/{room_id}/members/{uuid}, /rooms/{room_id}/playback/stop) do not require it.
429 Too Many Requests
You have exceeded the rate limit. See Rate Limits for details.
500 Internal Server Error
An unexpected error occurred on the server.
502 Bad Gateway
The gateway could not prepare an upstream media source for room playback. The response uses code: unavailable, so treat it as transient.
503 Service Unavailable
503 covers the capacity, dependency, and configuration conditions below.
Follow the recovery action documented for the condition you receive;
Recording service not available requires support-managed configuration and must not
be retried.
529 Site Overloaded
The gateway has no outbound capacity. Retry this response as described below. 529 is a non-standard status code for overload.
Best Practices
- Always check the HTTP status code first. A 2xx status means the request was accepted. Any other status indicates an error.
- Branch on the
codefield, not the message. Thecodeis a stable closed enum; theerrorstring is human-readable and may change. - Capture the response
traceparent. Log the server-owned response value alongside your request context and quote it when reporting a problem to support. - Propagate W3C trace context. Send a valid
traceparentwith the request and preservetracestatewhen present. - Parse the
errorfield for display only. Error messages are designed to be human-readable and actionable, but are not part of the programmatic contract. - Handle 429 with exponential backoff. When rate-limited, wait before retrying. Do not retry continuously without a delay.
- Retry only documented transient 5xx conditions. Use backoff for overload and temporary dependency failures. Do not loop on support-managed configuration errors such as
Recording service not available; contact support.