Troubleshoot a blocked send
A send that returns a blocked-class error was refused by a
pre-dispatch compliance gate before it reached the carrier. Each
code names the gate family that fired; the fix lives on a different,
deeper page that owns the full lifecycle of that gate. This page is
the single routing surface between the two — read the code here, then
drop one hop into the page that owns the control.
Every control on this page is tenant-owned — you enable the gate,
record the consent, widen the window, enable the scrub, or execute
the BAA. The one platform-owned control (the US TCPA federal voice
window) is called out where it applies. Orbit enforces the gates;
approvals always come from the carrier or regulator reviewing your
packet.
1. Map the code to the gate
Sort the envelope’serror.code by the gate family. The “Go to” link
is the page that owns the gate’s full lifecycle; the rest of this page
is the one-paragraph diagnosis for each code.
A
422 means a posture change is owed — retrying the same request
burns rate-limit budget without moving the state. A 403 on
DNC_SYNC_NOT_ENABLED is the opt-in you owe before the pre-flight
serves. A 5xx-shaped code is transient and is not on this page —
retry with backoff first.
2. SUPPRESSION_BLOCKED — opt-out suppression
What fired. The recipient’s address sits on your suppression
list — they replied STOP, unsubscribed through the Preference Center,
were recorded as opt_in: false through the Consent API, bounced, or
filed a complaint. A suppressed address is dropped before dispatch on
every regulated channel regardless of campaign, contact import, or
API call.
Channel scopes. Each suppression row carries a scope, and the send
gate honours the scope that covers the channel you sent on. The full
scope set is: all, sms, voice, whatsapp, email, push,
telegram, messenger, rcs.
allblocks every channel reachable on that address — the scope the Consent API and the Preference Center always write, and the default for phone/WhatsApp rows on a bulk CSV import.emailblocks email only — the default for email rows on a bulk CSV import unless achannelcolumn overrides it.- A per-channel scope (
sms,voice,whatsapp, …) blocks only that channel.
opt_in: true) on
Opt-Out & Suppression Lists, which
revokes the all plus matching per-channel rows without deleting the
audit trail.
Re-check the posture. Confirm the address is no longer suppressed:
SUPPRESSION_BLOCKED.
3. CONSENT_FALSE — no active opt-in
What fired. The send requires a positive consent grant and none is
on file for this (contact, channel) pair — the latest consent row is
opted_out, expired, pending (an unconfirmed double opt-in), or
absent altogether. Marketing sends fail closed by default: outbound is
eligible only on a live, unexpired opted_in grant.
Tenant fix. Record an opt-in through the Consent API with the
channels the send targets, and supply the GDPR evidence fields a
consent-based grant requires — lawful_basis, purpose, and
consent_text_version (the disclosure version the recipient agreed
to). A re-confirmation in a jurisdiction that treats a stale grant as
lapsed is an ordinary opt-in POST, optionally with a fresh validity
window. The full shape is on
Consent Management & Receipts.
marketing_eligible: true (equivalently status: "opted_in") is the
only state the send gate treats as eligible. expired or pending
means the send is correctly blocked — re-confirm first.
Escalate. Never owed for a genuinely missing or lapsed grant — the
fix is the opt-in. Open a ticket only if lookup returns opted_in
but the send still returns CONSENT_FALSE.
4. Quiet hours — advisory vs. enforced
What fired. The send landed outside the recipient-local calling or messaging window. The same gate family returns several codes, and the fix depends on which layer owned the block.QUIET_HOURS_BLOCKED— the messaging quiet-hours gate (tenant window) refused the send.TCPA_QUIET_HOURS/TCPA_DIALING_WINDOW_BLOCKED— the voice quiet-hours gate (tenant window) refused the send.TCPA_FEDERAL_DIALING_WINDOW_BLOCKED— the sole platform-owned federal guard refused a US voice send outside 8 AM–9 PM recipient-local. No tenant toggle widens it; the statutory exposure is not yours to waive.TCPA_STATE_DIALING_WINDOW_BLOCKED— a stricter state overlay (Florida’s Sunday ban, Mississippi’s early close, and the OK / LA / AL / AR / WV windows) sits on top of the federal rail on a most-restrictive-wins rule.QUIET_HOURS_TIMEZONE_UNKNOWN/TCPA_TIMEZONE_UNKNOWN— the recipient’s timezone could not be resolved; voice fails closed by default, messaging defaults to fail open unless you setdeny.
GET /compliance/quiet-hours/preview
endpoint is advisory — it answers “would this send be held, and
until when?” without performing it. The send-time gate is
enforced — it refuses the dispatch and returns the codes above.
A blocked preview is not a hard block from the preview itself; it is a
prediction of the enforcement that follows. Schedule at the returned
next_allowed_at instead of polling.
Tenant fix. For your own tenant window, widen, narrow, or disable
it under Settings → Timezone Policy. For the federal and state guards,
schedule inside the window — no toggle exists. For an unresolved
timezone, set the org-level unknown_timezone_policy knob (skip to
allow unresolved recipients, deny to fail closed) or correct the
recipient number so it resolves.
Re-check the posture. Preview the resolved window per destination
before a rollout:
next_allowed_at that contradicts the window you
configured, or a real E.164 number that fails to resolve, is the only
ticket class — open it with the destination and the meta.request_id
from the envelope. The full enforcement forks are on
Quiet-Hours Preview.
5. DNC / RND pre-flight
DNC_CONTACT / DNC_NUMBER — 422. The recipient’s contact row
carries dnc=true, or the number sits in a scrubbed DNC source. This
gate fires only once you opt in (dnc_sync_enabled) — otherwise
the DNC scrub is not in the path. The fix is to lift the recipient
from the DNC list with a documented reason, or do not send. Sources,
freshness, and the check endpoint are on
DNC Scrubbing.
DNC_SYNC_NOT_ENABLED — 403. The pre-flight GET /dnc/check or
POST /dnc/scrub refused because the org never enabled the scrub or
the sync feed has not yet synced. Enable dnc_sync_enabled; a synced
snapshot retires the gate.
RND_CONTACT / RND_REASSIGNED — 422. The number was scrubbed
against the FCC Reassigned Numbers Database and matched a reassigned
line — the prior owner’s consent does not transfer to the new
subscriber. The gate is opt-in per the RND flag; the lifecycle,
single-number check, and batch pre-campaign flow are on
RND Scrub.
Re-check the posture. Run the pre-flight read the send path
enforces, without performing a send:
federal_feeds_synced and
intl_feeds_synced so you see the live feed state — when either is
true the check serves directly; when both are false the per-org
opt-in is required first.
Escalate. Never owed for a genuine DNC or RND match — the fix is
the list lift or do not send. If the feed stays synced: false past a
re-enable, open a ticket with the check response payload.
6. HIPAA_BAA_REQUIRED — the BAA lifecycle 422
What fired. HIPAA mode is opted-in and the send’s audience or
content matched PHI, so the workspace refused PHI-bearing traffic
until your Business Associate Agreement is executed and in-term.
This is the one 422 that is owed by a lifecycle step rather than a
per-recipient gate — the BAA state machine gates every PHI send until
the agreement is current.
Tenant fix. Execute the BAA flow — attest PHI scope, preview, and
e-sign by typing the name — on BAA. HIPAA mode itself
stays off until the BAA reads executed, so the gate is not just
“re-send later”; the agreement is the prerequisite.
Re-check the posture.
executed means no current agreement, and the send stays
blocked. The full posture, PHI vocabulary, and the checklist runbook are
on HIPAA and
HIPAA checklist runbook.
Escalate. For a workspace-role block on the BAA flow itself — a
403 on the execute endpoint rather than the 422 on the send — the
escalation path is on
Compliance send-gate error codes.
A 5xx-shaped HIPAA_BAA_GATE_DB_FAIL is transient: retry with
backoff, then open a ticket with meta.request_id if it persists.
Worked flows
1. SMS to a recent STOP reply.422 SUPPRESSION_BLOCKED — the
recipient replied STOP last week, which wrote a scope all row.
Honour it and do not send, or reverse the suppression through the
Consent API on
Opt-Out & Suppression Lists if they
re-opted in.
2. Marketing send, no consent on file. 422 CONSENT_FALSE — the
contact has no consent row for the channel. Record an opt-in through the
Consent API with the GDPR evidence fields, re-check with
GET /compliance/consent/lookup, then re-send.
3. Voice campaign at 10 PM recipient-local.
422 TCPA_DIALING_WINDOW_BLOCKED (no FEDERAL in the code) — this is
your own tenant window. Reschedule at the next_allowed_at from a
preview, or widen the window. A code carrying FEDERAL is the one
platform-owned guard: schedule, no toggle.
4. DNC scrub gated before a campaign. 403 DNC_SYNC_NOT_ENABLED
on GET /dnc/check — enable dnc_sync_enabled in compliance settings;
once a feed snapshot is synced the check serves directly. A subsequent
DNC_CONTACT on the send means a matched number: lift with a
documented reason or exclude it.
5. PHI campaign, BAA pending. 422 HIPAA_BAA_REQUIRED — the
campaign audience is PHI-adjacent and the BAA reads pending. Execute
the BAA flow, re-read it with GET /compliance/baa, then relaunch.
When nothing fits
If a422 persists past the posture fix above, or the code does not
appear in the table, open a ticket carrying the code, the HTTP status,
the meta.request_id from the envelope, the referencing asset id
(sender id / campaign id / contact id), and the destination country.
The full send-gate error-code routing surface — including the
sender-identity, regional, policy-scan, and compliance-profile codes
that are not blocked-class — is on
Compliance send-gate error codes.
Cross-reference map
Each per-code topic here links out to the page that owns the gate’s full lifecycle:- Opt-Out & Suppression Lists — suppression entry points, channel scopes, bulk CSV import, and the re-opt-in.
- Consent Management & Receipts — the consent record, the lookup status states, double opt-in, and the GDPR evidence fields.
- Quiet-Hours Preview — advisory
vs. enforced, the voice enforcement forks, and the
next_allowed_atsemantics. - DNC Scrubbing — sources, freshness, the check endpoint, and the fail-open caveat.
- RND Scrub — the FCC Reassigned Numbers Database, the opt-in flag, and the batch pre-campaign flow.
- HIPAA and BAA — the BAA state machine, the e-sign flow, and the PHI vocabulary.
- Send Gates — the canonical pre-send gate inventory.