Skip to content

Error handling

All API errors return a consistent JSON format with an appropriate HTTP status code.

Every error response follows this structure:

{
"success": false,
"error": "Human-readable error message"
}

Successful responses omit the error field and include the relevant data directly. Some successful responses include "success": true (notably the admin API), but most 2xx responses use a bare result shape and do not wrap data in a success envelope. Treat the presence or absence of success: true on success bodies as not load-bearing; rely on the HTTP status code.

The request is malformed or contains invalid parameters.

Error messageCauseFix
Missing X-App-ID headerThe X-App-ID header was not provided.Include X-App-ID: your-app-id in every API request.
Invalid X-App-ID formatApp ID contains disallowed characters or exceeds 64 characters.Use only alphanumeric, underscores, hyphens. Max 64 chars.
Invalid request bodyThe JSON body could not be parsed.Ensure valid JSON with Content-Type: application/json.
Invalid commandThe command path in the URL is not recognized.Check the command path, e.g. answer, playback/start, record/stop.
urls is requiredA playback or play_and_get_digits command is missing urls/prompt_files.Include an array of HTTP/HTTPS URLs in the request body.
Invalid command_uid formatThe command_uid field contains disallowed characters.Use only alphanumeric, dots, hyphens, underscores. Max 128 chars.

Authentication credentials are missing or invalid.

Error messageCauseFix
Missing API keyThe X-API-Key header was not provided.Include X-API-Key: your-api-key in every request.
Invalid API keyThe provided API key does not match the configured key for this app.Verify the key matches the one set via POST /admin/apps/{app_id}.
Missing X-Admin-API-Key headerAn admin endpoint was called without the admin key header.Include X-Admin-API-Key: your-admin-key for admin endpoints.
Invalid admin API keyThe admin API key does not match the server’s ADMIN_API_KEY.Verify the key matches the ADMIN_API_KEY env var on the server.

You are authenticated but not authorized to access this resource.

Error messageCauseFix
Session belongs to a different applicationYour app ID does not match the session’s owning app.Sessions are bound to the app that receives them. You can only control your own sessions.
Room belongs to a different applicationYour app ID does not match the conference room’s owning app.Conference rooms are scoped to the app that created them.

The requested resource does not exist.

Error messageCauseFix
Session not foundNo active session exists with the given UUID.Verify the session UUID. The session may have already ended.
Room not foundNo conference room exists with the given room_id.Verify the room_id. The room may have been destroyed.

The request conflicts with the current state of the resource.

Error messageCauseFix
Conference name already takenA conference with the same name already exists for your app. The response includes the existing room_id.Use a different name or use the returned room_id.
Session is already in a different conference roomThe session is in another conference.Call conference/leave before joining a different room.
Session is already muted / unmutedThe mute state is already what you requested.Check the current mute state before toggling. This is an idempotency guard.

The request body exceeds the per-route size limit. The default limit is 1 MiB; the per-session command route (POST /api/v1/sessions/{uuid}/commands/{command}) uses a tighter 64 KiB limit because command payloads are small by design.

Error messageCauseFix
Request body too largeThe body exceeds the route’s maximum size (1 MiB default; 64 KiB on session command routes).Reduce the payload. Command payloads should contain only small fields. Do not embed audio or other large data inline.

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. conference/leave, /conferences/{room_id}/stop) do not require it.

Error messageCauseFix
Content-Type must be application/jsonThe request omits Content-Type or sets it to a non-JSON value (charset parameters like application/json; charset=utf-8 are accepted).Set Content-Type: application/json on every request that carries a JSON body.

You have exceeded the rate limit. See Rate limits for details.

Error messageCauseFix
Rate limit exceededToo many requests from this app/IP within the rate window.Back off and retry. Check your per-app rate_limit configuration.
Command rate limitedA command was sent too quickly after a previous command in the same rate group.Wait for the cooldown before sending the next command.

An unexpected error occurred on the server.

Error messageCauseFix
Internal error validating API keyThe server could not look up the app configuration (e.g. Redis unavailable).Server-side issue. Retry after a short delay.
Internal server errorAn unexpected condition occurred.Retry. If it persists, contact the gateway administrator.

The server is not ready to handle the request.

Error messageCauseFix
Admin API not configuredThe ADMIN_API_KEY environment variable is not set.Server configuration issue. The administrator must set ADMIN_API_KEY.
Recording not availableRecording is not enabled on this gateway.Operator configuration issue. Contact the operator to enable the recording service.
  • Always check the HTTP status code first. A 2xx status means the request was accepted. Any other status indicates an error.
  • Parse the error field for details. Error messages are designed to be human-readable and actionable.
  • Handle 429 with exponential backoff. When rate-limited, wait before retrying. Do not retry in a tight loop.
  • Treat 5xx errors as transient. Retry with backoff. If the error persists, escalate to the gateway administrator.
  • Do not rely on error message text for programmatic logic. Use HTTP status codes for branching. Error messages may change.