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

FieldUse it for
typeDeciding how to react in general: authentication means re-authenticate, rate_limit means back off, invalid_request means fix the request.
codeBranching on a specific case. Stable — a code never changes meaning. New ones get added.
messageShowing a human. Not stable; do not match on it.
paramPointing at the field at fault, when one field is at fault.
doc_urlThe page you are on. Every error links to its own explanation.
request_idQuoting 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

CodeHTTPMeans
malformed_request400The request could not be read at all, for example a query string nested more deeply than the server allows.
no_account_context400The credential is valid but is not bound to an account.
invalid_api_key401Well formed, but not a key we recognise.
invalid_credentials401That email and password combination was not accepted.
invalid_refresh_token401The refresh token was unknown, already used, or belongs to a family that has been revoked.
invalid_second_factor401The authenticator code or recovery code was wrong, already used, or expired.
malformed_api_key401The value is not shaped like a Textmast key at all.
missing_api_key401The request carried no `Authorization` header we could read.
revoked_api_key401The key was real. It is not usable any more.
unauthenticated401No credential was presented, or the one presented is not valid.
insufficient_credit402The campaign, or the first month of a rented number, would cost more than the balance on the account.
account_closed403This account has been closed.
account_not_available403The account exists but is suspended, closed, or otherwise not able to send.
account_suspended403Sending is stopped on this account.
insufficient_role403You are signed in, but your role on this account does not allow this.
insufficient_scope403The key is valid but does not carry the scope this endpoint needs. The message names it.
invalid_signature403A callback arrived whose signature did not verify.
no_accounts403This user is not a member of any account.
not_a_member403Your sign-in is valid, but you are not (or are no longer) a member of the account this request is for.
second_factor_required403The password was right, but the platform console needs your authenticator code as well.
account_not_found404No account with that id, or not one you can reach.
analytics_not_connected404There is nothing to disconnect.
api_key_not_found404No key with that id on this account.
automation_not_found404No automation with that id on this account.
campaign_not_found404No campaign with that id on this account.
conversation_not_found404No conversation with that id on this account.
invite_not_found404No invite with that id on this account.
invite_not_valid404The invitation has been used, revoked, has expired, or never existed.
member_not_found404That user is not a member of this account.
message_not_found404No message with that id on this account.
not_found404No such route, or no such resource on this account.
rental_not_found404No number with that id on this account.
segment_not_found404No segment with that id on this account.
suppression_not_found404That number is not on your opt-out list.
template_not_found404No template with that id on this account.
unknown_provider404A carrier callback named a provider this platform does not have configured.
webhook_not_found404No webhook endpoint with that id on this account.
already_rented409You already have that number.
brand_in_review409The brand has been submitted for vetting and cannot be edited yet.
campaign_not_sendable409The campaign has already been sent, is sending now, or has been cancelled.
campaign_not_stoppable409The campaign has finished, so there is nothing left to stop.
idempotency_key_reused409That Idempotency-Key was already used for a different request: another recipient, body or mode.
number_unavailable409Somebody took that number between your search and your request.
price_changed409The monthly cost is not what you confirmed.
second_factor_already_set409This account already has a confirmed authenticator.
alphanumeric_not_allowed422That country does not permit alphanumeric sender IDs at all.
already_a_member422That address already belongs to someone on this account.
analytics_credentials_rejected422Google would not accept the Measurement ID and API secret you gave us.
assignee_not_on_team422You tried to assign a conversation to somebody who is not a member of this account.
automation_has_no_steps422You tried to activate an automation that would do nothing.
brand_required422That country will not register a sender without a brand behind it.
contact_not_found422No contact with that number on this account.
invalid_phone_number422The destination could not be read as a real number.
invalid_topup_amount422The amount is below the minimum or above the maximum for a single payment.
last_owner422Removing or demoting this person would leave the account with nobody who can administer it.
list_not_found422The `contact_list_id` does not match a list on this account.
sender_not_found422The `sender_id` does not match an active sender available to this account.
validation_failed422One or more fields were missing, the wrong type, or outside the allowed range.
too_many_attempts429You have been rate limited.
internal_error500Something broke at our end. It was not your request.
sso_not_available501SAML sign-in is switched off for now.
purchase_failed502We asked the carrier for that number and they would not sell it.
provisioning_unavailable503No carrier on the platform can rent numbers at the moment.