Envelope
Success
{ "data": … }
data is an object or an array, depending on the endpoint. It is wrapped rather
than returned bare so that adding a sibling key later — paging cursors,
rate-limit state — is additive for you instead of breaking. A bare array leaves
nowhere to put those.
Error
{ "error": { "type": "insufficient_scope", "message": "…", "scope": "sms:send" } }
Branch on error.type. See Errors for the catalog.
Status codes
| Status | When |
|---|---|
200 | Success with a body |
201 | Something was created. A Location header points at it, where one exists. |
204 | Success with no body — deletes |
4xx | Rejected. Nothing was created and nothing was charged. |
5xx | Failed on our side. Nothing was charged — which is what makes a retry safe. |
Arrays are never null
An empty list is []. Every list field on every response follows this, including
nested ones like userIds and skipped. A null where you expect an array is a
routine cause of integration crashes, so this API does not produce one.
Note that [] can carry meaning: an empty userIds on an SMS line means
everyone, not nobody.
Unknown fields are rejected
A request body with a field this API does not recognize is a 400:
{ "error": { "type": "invalid_request", "message": "malformed request body: json: unknown field \"mesage\"" } }
Silently ignoring "mesage" would leave you debugging a request the server
considered perfectly fine. This is deliberate, and it applies to every write.
No customerId anywhere
The credential already determines the account. Nothing echoes an account id back at you, and nothing accepts one — so there is no field to get wrong, and no way to accidentally address someone else's data.