Two error lanes, one ambiguous code string
A failed 10DLC workflow surfaces one string of code and leaves you to decide where it came from. Get that wrong and you pay for it twice — a delivery error filed as a brand re-submission burns a TCR vetting fee you never needed to pay, and a registry rejection retried as a resend just fails again. There are two independent error systems, and they never intersect:
Overlap confuses readers because both lanes share a numeric family: the
registry’s
30883 (content violation, caught at filing) and the delivery
lane’s 30007 (carrier violation, caught at send time) are cousins, not
twins. The check is always the same: does the code live on a brand or
campaign, or on a message?
The lookup matrix — where to paste a code
- Code arrived on a brand or campaign record, with a
FAILED/REJECTEDregistration status. It is a registry rejection. Decode it with the rejection decoder and follow the fix card — see 10DLC rejections, re-vetting, and the post-approval lifecycle for the full amend-and-resubmit loop. - Code arrived on a failed message (
GET /messages/:id, amessage.failedwebhook, or the message detail panel). It is a delivery error. The message detail panel already resolves it through the carrier-error dictionary; for batch analysis,GET /api/v1/analytics/messaging-insightsgroups all failed codes over a window by category with resolved names and descriptions (worked example B below). There is no single-code API for delivery errors because no per-code action is needed beyond what the resolved description states.
error_code) but the remedy is the registry lane: complete the
registration, and the sends clear with it.
Worked example A — 40016, a registry rejection
The 10DLC wizard shows a brand stuck at REJECTED:
Worked example B — 30007, a delivery error
A campaign is approved and sending, but individual messages fail:
30007 resolves in
the carrier-error dictionary to Carrier violation — message content or
sender violated carrier policies, category carrier_filter. That
category is non-retryable: resending the unchanged message fails again.
The fix is message-side — clean the content (drop the blocked URL, remove
SHAFT-class wording, shorten the risky phrase) — then resend. The brand
stays untouched and no vetting fee moves.
For a fleet-wide view, the same resolution runs as a histogram:
error_code comes back with a resolved name, description, and
category (carrier_filter / content / opt_out / rate_limit /
network / invalid_destination / unknown), so you can tell in one
glance whether filtering, content, or opt-outs dominate — this endpoint is
owner/admin scoped for that reason.
Anti-pattern: re-registering a delivery error
When operators see “carrier violation” on failed messages, a common escalation is to re-file or re-vet the brand. That is the wrong lane:30007 (and delivery codes generally) target one message payload, and no
amount of brand-side work rewrites your sample sends. The costs of the
mistake are concrete — TCR charges a new vetting fee per re-submission and
per re-vet, and every resubmission restarts a 1–5 business-day review
during which nothing changes about the failing sends. Route delivery codes
through payload fixes; route registration codes through the decoder. When
a registry code arrives with resubmit_allowed: false (e.g.
BRAND-DCA-FAIL), even the registry lane says start a fresh registration
rather than amend — the verdict on the fix card is the authority for both
lanes.
See also
- 10DLC rejections, re-vetting, and the post-approval lifecycle — the full fix-card loop: decode, amend, resubmit, re-vet, throughput tiers
- Troubleshooting: 10DLC campaign rejected — the static symptom-to-cause matrix the rejection decoder automates
- Delivery lifecycle — what each message
status means, including where
error_codeattaches to a failed row - Message status map — the four owners of the outbound state machine, for reading webhook statuses