Error shape
An error response body always looks like this:
{
"error": {
"message": "A human-readable sentence you can show or log as-is.",
"code": "unpriced_destination"
}
}code is a short machine-readable reason, and it's only there when the failure has one. Build your error handling around the HTTP status first, and use code for the specific cases you want to handle differently.
HTTP status codes
| Status | Meaning |
|---|---|
400 |
The request is missing a required field or malformed. |
401 |
The API key is missing, invalid, or has been revoked. |
402 |
Your balance doesn't cover the request (a call, a number check, or the next minute of a conversation). |
403 |
The destination or caller ID is on the safety list, or the two are the same number. |
404 |
Nothing with that id belongs to your account. |
409 |
The conversation has ended, so nothing more can be added to it. |
422 |
There's no rate configured for that destination yet. |
429 |
Too many requests. See rate limits below. |
502 |
The call was accepted and billed, then failed to place. The connection fee is refunded automatically. |
503 |
A number check couldn't run just now. You're not charged; try again in a minute. |
A 400/402/403/422 rejection never touches your balance. Nothing is charged unless a call is actually placed, a number check actually runs, or a conversation is actually scored.
Rate limits
120 requests per minute per API key. Scoring a conversation with fraud detection sends a request per line, so everything about conversations has its own, higher limit: 1,200 a minute per key. A number check counts toward the usual 120.
Every response carries the standard rate-limit headers:
RateLimit-Limit: 120
RateLimit-Remaining: 114
RateLimit-Reset: 37Going over the limit gets a 429 with code: "rate_limited". If a legitimate integration needs a higher ceiling, contact support with what you're building and the volume you expect.