Skip to navigation

Errors

Every error response has the same shape, for every endpoint:

{
"detail": "No outbound route matches that number",
"code": "unprocessable",
"support_id": "b2c4d6e8"
}
FieldMeaning
detailA message for a person who reads your logs. It can change at any time
codeA stable key for a program. Branch on this field
support_idA short id that the server also writes to its log. Quote it when you contact support
errorsA list of field errors. It is present only for validation failures

A validation failure adds a list of field errors:

{
"detail": "Validation failed",
"code": "validation_error",
"support_id": "7f3a9c21",
"errors": [
{ "field": "to", "message": "Field required", "type": "missing" }
]
}

field is the dotted path into the request body. You can map it to a form field. type is a stable kind of error. You can use it as a localization key.

Codes

codeStatusMeaning
validation_error422The request body or query failed validation. The body has errors
bad_request400The request is malformed
unauthorized401The key is missing, revoked, expired, or not a developer key
forbidden403The key is valid but does not have the scope that the endpoint needs
not_found404The resource does not exist in this account
duplicate_value422The request breaks a uniqueness rule, for example a webhook name that is already in use
conflict409The resource exists but is not ready, for example a recording that the system has not finished merging, or a transcript that is in progress
unprocessable422The request is well formed but the system cannot carry it out, for example a number that no route matches
rate_limited429The request exceeded a limit. Retry-After gives the time when the window ends
service_unavailable503A required service is not available, for example no call server can take a call. Try again later
internal_error500A failure on the Hams side. detail is generic on purpose. Quote the support_id

Hams adds new codes without a new API version. Treat a code that you do not know as a generic failure.

A 404 never means forbidden

A resource that belongs to another account returns the same 404 and the same generic message as a resource that does not exist. The API does not show whether an id is valid in another account. A 404 on an id that you received always means that the id is not in your account.

A transcript that does not exist also returns 404. This includes a transcript that failed. See Call history and recordings.

A 401 and the dashboard endpoints

A developer key works only under /api/developer/v1. If you send a key to any other path, the API rejects the request as not authenticated. This includes the paths that the dashboard uses. A dashboard session also does not open the developer endpoints. The 2 credentials do not overlap.

A 429 and the limits

By default, each key can make 10 requests each second across the API. The limit for a key is a fixed window. It resets at the window boundary. Calls that you place also have a limit for each account each second. That limit counts the requests in a window that moves with time. It does not count the requests that it refuses. Both limits answer 429 with the standard body and a Retry-After header.

Wait until the time in the header. Then try again.

A 503 means try again

A 503 with the code service_unavailable on a call placement means that no call server can take the call now. The system did not place the call. Try again with a longer delay each time. The key and the request are correct.