Reference
Errors
One shape, always. The code is stable and meant to be switched on; the message is for a human reading a log and may change.
{
"error": {
"code": "bad_request",
"message": "recipient must not be empty"
}
}| Status | What it means |
|---|---|
| 400 | The request is wrong in a way you can fix. The message says how. invalid_recipient: the recipient is written as a phone number nobody can have — a +1 number without ten digits, an area code or exchange starting with 0 or 1, an N11 service code, or a fictional 555-0100 to 555-0199. Nothing was written or sent; fix the number. |
| 401 | No key, an unknown key, or a revoked one. |
| 404 | No such thing — or one your key may not see. We do not distinguish, because doing so would confirm it exists. |
| 409 | duplicate_send: the same text went to the same person moments ago — pass allow_duplicate if you meant it. agent_offline: the number is temporarily unavailable for a live action (a reaction, an edit, an unsend, a typing indicator); nothing was done, so retry shortly. conflict: a message you asked to cancel is already on its way. |
| 413 | The upload is over the size limit. |
| 422 | The JSON parsed but a required field was missing or the wrong type. recipient_undeliverable: the number cannot get texts — its carrier said it is a landline or not in service, or the check before a first text found a landline or no such number — so your text-message numbers do not text it again unless it writes in. reason says which: landline, not_in_service, invalid or other. Fix the number on the contact rather than retrying. |
| 429 | Over 600 requests a minute. Retry-After says how long, in seconds. |
| 503 | agent_busy: the number is busy right now. Nothing was done; retry in a moment. |
| 504 | command_timeout or command_unconfirmed: the number did not confirm in time. It may still have happened — check before repeating it. |
Sending while a number is unavailable
Not an error. A send to a number that is temporarily unavailable is accepted and queued: 201, status pending, queued: true, and a notice whose code is number_unavailable. It goes out automatically as soon as the number is back, so do not send it again. Until it goes, you can call it off with POST /v1/messages/{id}/cancel.
{
"id": "0b5ed7e8-f7a1-4f6e-9c2a-2a1f0d9e8b77",
"status": "pending",
"queued": true,
"notice": {
"code": "number_unavailable",
"message": "This number is temporarily unavailable. Your message is queued and will be sent automatically as soon as it's back."
}
}A notice of send_retrying means the send was turned down for now and will be tried again automatically. Each number says whether it can send in its availability, so you can tell before you send.
What to retry
429, 503, and 409 agent_offline, after a delay. Never a 504 blindly: the number may already have done it. A 4xx otherwise will fail the same way forever — the request is the problem, and repeating it only uses your rate limit.
Any other 5xx is ours and safe to retry. If you can make one happen with a request that is not obviously nonsense, we would like to know: that is a bug, not a limit. We fuzz the API for exactly this, and the last one it found was a null byte in a text field, which Postgres cannot store — it came back as 500 when it should always have been 400.
Not here yet
Listed so you find out now rather than halfway through building.
The remaining Messages controls
Expressive text styles and effects, editing a sent message, and leaving a group are not supported customer API operations yet. They will appear here only after their readback and failure states are reliable.
Provisioning numbers
Numbers are provisioned by a person, usually within 48–72 hours of purchase. There is no self-serve API for it, because there is no self-serve process behind it to expose.