Errors
Every error has the same shape, whatever went wrong. A client that can parse one can parse all of them.
{
"error": {
"type": "invalid_request",
"code": "invalid_phone_number",
"message": "That number could not be read as a real number.",
"param": "phone_number",
"doc_url": "https://docs.textmast.com/errors/invalid_phone_number",
"request_id": "req_01j8xk2p7n4qc3m9v0wz5bt6ay"
}
}The fields
| Field | Use it for |
|---|---|
type | Deciding how to react in general: authentication means re-authenticate, rate_limit means back off, invalid_request means fix the request. |
code | Branching on a specific case. Stable — a code never changes meaning. New ones get added. |
message | Showing a human. Not stable; do not match on it. |
param | Pointing at the field at fault, when one field is at fault. |
doc_url | The page you are on. Every error links to its own explanation. |
request_id | Quoting to us. Log it on every failure — it is the difference between a one-query answer and a guess. |
Branch on code, never on message. Messages are written for people and get reworded when they turn out to be confusing. Codes are a contract.
Delivery failures are not errors
A message that the API accepted and a carrier later refused does not produce an error response — the request succeeded. The reason arrives on the message as afailure code, which is a different and smaller vocabulary.
Every code
| Code | HTTP | Means |
|---|---|---|
malformed_request | 400 | The request could not be read at all, for example a query string nested more deeply than the server allows. |
no_account_context | 400 | The credential is valid but is not bound to an account. |
invalid_api_key | 401 | Well formed, but not a key we recognise. |
invalid_credentials | 401 | That email and password combination was not accepted. |
invalid_refresh_token | 401 | The refresh token was unknown, already used, or belongs to a family that has been revoked. |
invalid_second_factor | 401 | The authenticator code or recovery code was wrong, already used, or expired. |
malformed_api_key | 401 | The value is not shaped like a Textmast key at all. |
missing_api_key | 401 | The request carried no `Authorization` header we could read. |
revoked_api_key | 401 | The key was real. It is not usable any more. |
unauthenticated | 401 | No credential was presented, or the one presented is not valid. |
insufficient_credit | 402 | The campaign, or the first month of a rented number, would cost more than the balance on the account. |
account_closed | 403 | This account has been closed. |
account_not_available | 403 | The account exists but is suspended, closed, or otherwise not able to send. |
account_suspended | 403 | Sending is stopped on this account. |
insufficient_role | 403 | You are signed in, but your role on this account does not allow this. |
insufficient_scope | 403 | The key is valid but does not carry the scope this endpoint needs. The message names it. |
invalid_signature | 403 | A callback arrived whose signature did not verify. |
no_accounts | 403 | This user is not a member of any account. |
not_a_member | 403 | Your sign-in is valid, but you are not (or are no longer) a member of the account this request is for. |
second_factor_required | 403 | The password was right, but the platform console needs your authenticator code as well. |
account_not_found | 404 | No account with that id, or not one you can reach. |
analytics_not_connected | 404 | There is nothing to disconnect. |
api_key_not_found | 404 | No key with that id on this account. |
automation_not_found | 404 | No automation with that id on this account. |
campaign_not_found | 404 | No campaign with that id on this account. |
conversation_not_found | 404 | No conversation with that id on this account. |
invite_not_found | 404 | No invite with that id on this account. |
invite_not_valid | 404 | The invitation has been used, revoked, has expired, or never existed. |
member_not_found | 404 | That user is not a member of this account. |
message_not_found | 404 | No message with that id on this account. |
not_found | 404 | No such route, or no such resource on this account. |
rental_not_found | 404 | No number with that id on this account. |
segment_not_found | 404 | No segment with that id on this account. |
suppression_not_found | 404 | That number is not on your opt-out list. |
template_not_found | 404 | No template with that id on this account. |
unknown_provider | 404 | A carrier callback named a provider this platform does not have configured. |
webhook_not_found | 404 | No webhook endpoint with that id on this account. |
already_rented | 409 | You already have that number. |
brand_in_review | 409 | The brand has been submitted for vetting and cannot be edited yet. |
campaign_not_sendable | 409 | The campaign has already been sent, is sending now, or has been cancelled. |
campaign_not_stoppable | 409 | The campaign has finished, so there is nothing left to stop. |
idempotency_key_reused | 409 | That Idempotency-Key was already used for a different request: another recipient, body or mode. |
number_unavailable | 409 | Somebody took that number between your search and your request. |
price_changed | 409 | The monthly cost is not what you confirmed. |
second_factor_already_set | 409 | This account already has a confirmed authenticator. |
alphanumeric_not_allowed | 422 | That country does not permit alphanumeric sender IDs at all. |
already_a_member | 422 | That address already belongs to someone on this account. |
analytics_credentials_rejected | 422 | Google would not accept the Measurement ID and API secret you gave us. |
assignee_not_on_team | 422 | You tried to assign a conversation to somebody who is not a member of this account. |
automation_has_no_steps | 422 | You tried to activate an automation that would do nothing. |
brand_required | 422 | That country will not register a sender without a brand behind it. |
contact_not_found | 422 | No contact with that number on this account. |
invalid_phone_number | 422 | The destination could not be read as a real number. |
invalid_topup_amount | 422 | The amount is below the minimum or above the maximum for a single payment. |
last_owner | 422 | Removing or demoting this person would leave the account with nobody who can administer it. |
list_not_found | 422 | The `contact_list_id` does not match a list on this account. |
sender_not_found | 422 | The `sender_id` does not match an active sender available to this account. |
validation_failed | 422 | One or more fields were missing, the wrong type, or outside the allowed range. |
too_many_attempts | 429 | You have been rate limited. |
internal_error | 500 | Something broke at our end. It was not your request. |
sso_not_available | 501 | SAML sign-in is switched off for now. |
purchase_failed | 502 | We asked the carrier for that number and they would not sell it. |
provisioning_unavailable | 503 | No carrier on the platform can rent numbers at the moment. |