Resources

Error codes

What each code means, and whether the message was billed.

The column most references leave out is the last one. A message refused before it reaches an operator costs nothing; one the operator accepted and then failed to deliver is billed, because the operator charges us for it either way. Knowing which is which is the difference between a bug and an invoice question.

API errors

Returned synchronously when you call the API. None of these are billed — the message never existed.

HTTPCodeMeaningBilled
401UNAUTHORIZEDThe key is unknown, revoked, missing from the Authorization header, or lacks the scope for this endpoint.No
403ACCOUNT_NOT_ACTIVEThe account is suspended or closed. Keys keep working the moment it is reactivated.No
403IP_NOT_ALLOWEDYour account has a source allowlist and this request came from outside it. An empty allowlist accepts any address.No
413PAYLOAD_TOO_LARGEThe request body exceeded the limit. A single send is small.No
429RATE_LIMIT_EXCEEDEDAbove your account TPS. The Retry-After header says how long to wait.No
402INSUFFICIENT_BALANCEPrepaid balance below the cost of this send.No
422INVALID_NUMBERNot a valid Indian mobile number after normalisation. +91, 91 and leading zeroes are all handled.No
422VAR_COUNT_MISMATCHThe number of values in vars does not match the {#var#} slots in the template.No
422VAR_TOO_LONGA variable exceeds the length the template was registered with.No
422SUPPRESSEDThe number is on your own opt-out list or the platform blacklist.No
400INVALID_MESSAGE_IDThe message id in the path is empty or implausibly long.No
404MESSAGE_NOT_FOUNDNo message with that id on your account. An id belonging to another account returns this too, deliberately.No
502NO_GATEWAYNo vendor could carry it — none eligible, or every eligible one refused. The reason names the vendors considered. Nothing was sent.No

DLT validation

Checked in order — entity, chain, sender ID, template, content — and the first failure is the one reported. The later checks usually fail as a consequence of the earlier ones, so fixing the reported code is the right place to start. None of these are billed.

CodeMeaningWhat to do
DLT-201PE not verifiedNo Principal Entity is registered for the account, or it is not verified. Indian traffic cannot be enabled without one.
DLT-202Chain not verifiedThe PE-TM chain is missing, pending, rejected or stale for the selected route.
DLT-203Header invalidThe sender ID is not registered on this account, is not approved, or has not been re-confirmed with the operator recently.
DLT-204Template invalidThe template is not registered, not approved, not mapped to this sender ID, or has not been re-confirmed recently.
DLT-205Content mismatchThe message does not match the approved template. Fixed wording must be identical; only the variable parts may differ.
DLT-206Category or policyHeader and template categories disagree, or a policy check failed.
DLT-207Upstream rejectedThe operator refused it. The raw provider code is preserved alongside ours — ask us for it if you are disputing a charge.

Delivery outcomes

These arrive on the delivery receipt, after the message reached an operator. Every one of them is billed — charging happens on submission, and the outcome does not change the price. The vocabulary is ours and it is small on purpose: carriers each number their failures differently, so a report built on one carrier’s numbering breaks the day we route you through another. We keep the carrier’s original alongside it, so a disputed charge can be traced to exactly what they said.

error_codeMeaningWhat it tells you
INVALID_NUMBERNumber not in serviceThe number is unallocated, disconnected or malformed. Remove it from the list.
HANDSET_UNREACHABLEHandset unreachableSwitched off, out of coverage, memory full or roaming-barred at the time.
NETWORKOperator network errorA fault on the operator side. Usually transient — a resend later often lands.
EXPIREDValidity expiredThe operator held it past its validity period without delivering it.
SUPPRESSEDOn your suppression listYou have suppressed this number, so it was never sent.
CONTENT_REJECTEDContent or sender not acceptedThe content or sender ID did not match what is registered. Check the template.
OPERATOR_REJECTEDDeclined by the operatorThe operator did not accept the message for this subscriber.
UNDELIVEREDNot deliveredThe operator returned no usable reason.

The interim codes are the ones that catch people out

Several operator codes look like failures and are not — the operator has simply not finished. Treating them as final marks live messages dead and produces a delivery rate that is wrong in your favour, which is worse than one that is wrong against you: it hides a real problem. We hold them as in-flight until a terminal receipt arrives, which is why a small number of messages stay SUBMITTED for a while.

A code you cannot find

Operators add codes without notice, and a code we do not recognise is reported as UNKNOWN_REASON with the original preserved rather than being guessed at. If you are seeing one, send us the message id and we will tell you what the operator actually returned.