Successful responses wrap the payload in data, with request details in meta. Errors return an error object and a non-2xx HTTP status:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"errors": [{ "field": "To", "message": "This field is required" }]
}
}
}
details appears only when there's more to say. For validation errors it holds errors, a list of { field, message }. Branch on code and the HTTP status, not on message, which can change.
General codes#
| HTTP | code |
Meaning | What to do |
|---|---|---|---|
| 400 | VALIDATION_ERROR |
A field is missing or invalid | Fix the fields listed in details |
| 401 | UNAUTHORIZED |
API key missing, malformed or revoked | Send Authorization: Bearer vp_…; see Authentication |
| 402 | INSUFFICIENT_BALANCE |
Wallet balance is too low | Top up in the portal |
| 403 | FORBIDDEN |
The resource belongs to another account | Check the account SID or ID in the path |
| 403 | NUMBER_NOT_OWNED |
The caller-ID isn't on your account | Use a number you own and have registered |
| 404 | NOT_FOUND |
No such resource on your account | Check the ID |
| 409 | NUMBER_NOT_OWNED |
(number purchase) Someone else just bought it | Pick another number |
| 409 | QUOTE_STALE |
The price changed during purchase | Fetch the price again and retry |
| 409 | CALL_ENDED |
The call has already ended | Nothing to hang up |
| 503 | SERVICE_UNAVAILABLE |
No carrier capacity right now | Retry with exponential backoff |
| 500 | INTERNAL_ERROR |
Unexpected server error | Retry; contact support if it persists |
Number wiring codes#
The wiring endpoints on Phone Numbers (/telephony, /carrier, /inbound) use lowercase codes in the same envelope:
| HTTP | code |
Meaning |
|---|---|---|
| 400 | validation |
Invalid :id or body |
| 400 | bind_failed |
The inbound binding was rejected; check the target fields |
| 404 | not_found |
The number doesn't exist or isn't yours |
| 409 | inbound_conflict |
Inbound is bound elsewhere; retry with "force": true |
| 409 | inbound_bound |
Inbound is still bound; unbind first or pass force=true |
| 503 | not_configured |
Provisioning is temporarily unavailable |
| 500 | internal_error |
Unexpected server error; retry |
Retrying safely#
- Retry
500and503with exponential backoff. Don't retry4xxwithout changing the request. POST /phone-numbers/:id/carrieris idempotent and safe to repeat.POST /callsis not idempotent. A retry after a timeout can place a second call, so checkGET /calls(or your status webhooks) first.