> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: SMS destination and spending blocks

> Resolve 422 SMS_BLOCKED_DESTINATION, 422 CHANNEL_BLOCKED_DESTINATION, 429 SMS_RATE_LIMITED, and 429 SMS_DAILY_SPEND_CAP pre-send rejects — map each code to the guard layer that fired and the fix you own.

# Troubleshooting: SMS destination and spending blocks

A pre-send destination block rejects an outbound SMS before it is routed
to any carrier — no sender, route, or provider change will clear it, and
a blind retry replays the same check. The reject comes in one of four
codes, and each one belongs to a specific guard layer.

This page maps every code to its layer and the fix you own. It is the
messaging mirror of
[Troubleshooting: voice destination and emergency blocks](/troubleshooting/voice-destination-blocks)
— same triage shape, different gates: where voice guards the caller-id
you present, SMS guards the destination prefix, the velocity, and the
daily spend.

## Decision matrix — which layer fired

Find the error code first, then jump to its section below. Each layer
takes one control you own — the tenant blocklist, the send pacing, or a
scoped test campaign — so triage ends in a small set of places.

| Error code                          | Layer that fired                                                                                                                        | Control you own                                                                     | Go to                                                         |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `SMS_BLOCKED_DESTINATION` (422)     | The destination prefix matches a platform or per-organization blocklist entry, or the number is a NANP +1 555-NXX fictional test number | **Destination choice** — send to a real subscriber on an allowed prefix             | [Destination-prefix blocklist](#sms-blocked-destination)      |
| `CHANNEL_BLOCKED_DESTINATION` (422) | The exact destination is on your own tenant blocklist                                                                                   | **Tenant blocklist** (Messages → Blocklist) — remove the entry or stop targeting it | [Tenant self-service blocklist](#channel-blocked-destination) |
| `SMS_RATE_LIMITED` (429)            | The per-minute sliding-window send cap tripped                                                                                          | **Send pacing** — spread the burst                                                  | [Per-minute rate window](#sms-rate-limited)                   |
| `SMS_DAILY_SPEND_CAP` (429)         | The estimated daily spend ceiling tripped                                                                                               | **Campaign scope** — pace or stop today's sends, retry tomorrow                     | [Daily spend ceiling](#sms-daily-spend-cap)                   |

If your reject is `FRAUD_SHIELD_BLOCKED` (403) instead, that is your own
tenant-configured Fraud Shield, not these platform baselines — decode it
on [Troubleshoot FRAUD\_SHIELD\_BLOCKED](/troubleshooting/fraud-shield-blocked).

## Destination prefix blocked<a id="sms-blocked-destination" />

`422 SMS_BLOCKED_DESTINATION` fires when the destination matches a
prefix on the platform destination blocklist — the premium-rate and
pumped-route prefixes that account for the most expensive SMS abuse — or
on your own organization's prefix blocklist. The same code also fires
when the destination is a NANP **+1 555-NXX** number: carriers silently
accept submissions to that reserved fictional range but never deliver,
so the platform rejects it at send time instead of paying for an attempt
with no delivery receipt.

The 422 body names what matched — `details.prefix` for a blocklist
match, `details.reason: "nanp_555_test_range"` for the fictional range —
so branch on it before you touch anything.

**Fix it by changing the destination, not by working around the gate:**

1. Read `details` on the 422 body. For a prefix match, compare the
   prefix against the segment of the destination you sent.
2. **Fictional test range.** If `reason` is `nanp_555_test_range`,
   replace the placeholder with a real subscriber number — or use the
   sandbox magic numbers (`+1 500 555 000X`), which pass in test mode
   because no real carrier attempt exists.
3. **Platform blocklist prefix.** If the block came from the platform
   list, the route class is premium-rate or pumping-prone; the gate
   exists to stop that spend. Reroute to the subscriber's real number or
   accept the destination as unsendable — there is no tenant-level
   toggle that re-opens a platform-blocked prefix.
4. **Your organization's prefix blocklist.** If your own organization
   added the prefix (an operator throttling a hot route for one tenant,
   or an automated SMS-pumping scorer marking it), remove that prefix
   from the organization's fraud settings to re-open it. Until you do,
   the block applies to every sender in the organization.

A 422 in this class is not recoverable by retrying — the same prefix
check re-fires on every attempt. It is also deliberately *sticky*: a
blocked attempt is recorded as a blocked rejection rather than silently
dropped, so your send analytics show the refusal instead of reading it
as normal traffic.

## Tenant self-service blocklist<a id="channel-blocked-destination" />

`422 CHANNEL_BLOCKED_DESTINATION` with `details.reason: "tenant_blocklist"`
means the exact destination is on **your own** outbound blocklist —
the operator-managed list at **Messages → Blocklist** in the dashboard
(or the `POST /api/v1/messages/blocklist` API). The match is verbatim,
not a prefix, so the listed number is blocked exactly as entered. This
check runs before the prefix layers, so your entry takes precedence over
the broader rules — and it applies to every channel at once, not just
SMS.

**Fix it at the blocklist:**

1. Check **Messages → Blocklist** for the destination; if it is listed,
   remove the entry and the destination becomes send-eligible
   immediately.
2. If the entry is intentional (an abuse case, a bad-actor number), stop
   targeting that destination — the block is doing exactly what it was
   written to do.
3. Audit who blocked it and why: every entry carries a free-text reason
   and removals are soft, so the history answers "when was this
   destination un-blocked."

For the full list surface, read
[Messages Blocklist](/guides/messages-blocklist). Reach for opt-outs
instead of the blocklist when the *recipient* initiated the stop —
[opt-out and suppression lists](/compliance/opt-out-suppression) are the
consent record regulators expect you to honor.

## Per-minute rate window<a id="sms-rate-limited" />

`429 SMS_RATE_LIMITED` fires when your account's outbound SMS exceeds
the per-minute cap over a sliding 60-second window. The guard weights
the current minute and the tail of the previous minute, so a burst
concentrated at a minute rollover trips it even when each single send
looked fine.

The 429 body names the limit, e.g.
`{ "limit": 60, "window": "1m" }`.

**Fix it by smoothing the send, not by retrying harder:**

* The window **slides** rather than hard-blocks, so pacing the bulk send
  clears it without any configuration change.
* A campaign that holds the cap pinned re-trips on every attempt —
  distribute the batch over minutes instead of firing it in one burst.
* Where your organization runs a custom per-minute override, the lower
  value wins; an active automatic anti-fraud throttle can also clamp the
  cap down for a limited window, and it reverts on its own.

## Daily spend ceiling<a id="sms-daily-spend-cap" />

`429 SMS_DAILY_SPEND_CAP` fires when the day's estimated SMS spend
reaches the daily ceiling. The estimate is computed from the number of
segments sent at a conservative per-segment price — deliberately
pessimistic so the cap engages before real spend does — and it resets at
the day boundary.

The 429 body names both sides of the check, e.g.
`{ "estimated_spent_cents": 5000, "cap_cents": 5000 }`.

**Fix it by scoping the campaign:**

* Pace or stop today's sends and retry after the day rolls over — the
  counter resets.
* If the reject surprised you, review which campaign consumed the day's
  spend; a compromised API key pumping premium destinations is exactly
  what this ceiling exists to cut off.
* Where your organization runs a custom daily-spend override, the lower
  value wins — the ceiling engages at whichever bound you configured.

## What to capture before escalating

Work the matrix above first. If a block still misreads — the destination
is a real subscriber on a prefix that should be open, or the rate window
keeps tripping well under its named limit — open a ticket with:

1. **The full error body** — the code, message, and the `details`
   object (the `prefix`, `reason`, or `limit` fields above).
2. **The destination number**, E.164 normalized.
3. **The send path** — single API send, batch send, or campaign.
4. **Your organization ID** (Settings → Organization, or
   `organizationId` from `GET /api/v1/me`).

## What not to do

* **Do not retry in a loop.** Every pre-send gate re-fires on every
  attempt; only the rate and spend windows clear on their own.
* **Do not reconfigure the sender or route.** The block fires before the
  message reaches any carrier.
* **Do not treat a blocked attempt as delivered traffic.** Blocked sends
  record as rejections in your analytics, so a spike in
  `SMS_BLOCKED_DESTINATION` rejections reads as refusals, not deliveries.
* **Do not reclassify a Fraud Shield 403 as one of these codes.**
  `FRAUD_SHIELD_BLOCKED` is your own tenant policy — decode it on
  [Troubleshoot FRAUD\_SHIELD\_BLOCKED](/troubleshooting/fraud-shield-blocked).

## See also

* [Troubleshooting: voice destination and emergency blocks](/troubleshooting/voice-destination-blocks) —
  the same triage shape on the voice side, guarding the caller-id you
  present rather than the destination prefix.
* [Troubleshoot FRAUD\_SHIELD\_BLOCKED](/troubleshooting/fraud-shield-blocked) —
  your tenant-configured Fraud Shield when it rejects sends in
  enforcement mode.
* [Troubleshoot sender ID rejected](/troubleshooting/sender-id-not-registered) —
  the sender-identity registration gates that reject before these
  destination layers are consulted.
* [Messages Blocklist](/guides/messages-blocklist) — the tenant-owned
  destination ban this page's `CHANNEL_BLOCKED_DESTINATION` section
  triages.
* [Rate-limit and cooldown taxonomy](/concepts/rate-limit-and-cooldown-taxonomy) —
  where `SMS_BLOCKED_DESTINATION` sits among the platform's limiter
  families.
* [References: error codes](/reference/error-codes) — the error catalog
  this page triages.
