The shape
An error carries a code to branch on, a message describing what happened, and a fix describing the way out. The HTTP status matches the class of problem.
The fix exists because most callers are not sitting at a terminal. An agent that receives one has its next step named for it.
Ones you will meet
unauthenticated — no valid key. spending_cap_reached — the send would cross the cap and nothing was queued. missing_variables — the template references variables the call did not supply, and names them. sms_too_long — the body exceeds the segment limit, with the count and the encoding that decided it.
invalid_input names the field. not_found names the thing.
A success is not always a delivery
This is the one worth reading twice. sms.send can answer 200 with status: "suppressed" and a blocked object — the message was accepted and stored, and has not left.
Today that is what a new project gets, because no carrier registration has been filed. Check blocked before reporting a message as delivered; a status that cannot change yet is not one to wait on.
Last modified on September 13, 2026