Outbound send gating
Every outbound send on Orbit — API, flow, campaign, drip, journey, or a 1:1 send from the dashboard — is admitted through the same chain of gates before it is handed to a provider. Each gate is a control you configured (or chose to leave off): your wallet posture, your quiet-hours window, your frequency caps, your duplicate-content policy, your throughput ceilings. When a gate says no, the send stops there and reports the reason through a documented error code or a skipped status. This page is the map the individual guides assume: which gates exist, the order a send walks them, and what to branch on in your integration — so “when will my send actually leave” is one page, not four.The gate layers — each one tenant-owned
Four families of controls shape whether a send leaves, and all of them are your configuration, not platform mandates. Compliance posture belongs to the tenant: Orbit carries the settings and evaluates them at send time. The only gate the platform owns and cannot be disabled is the TCPA federal voice dialing-window guard for US recipients (no tenant toggle, fail-closed on an unresolvable recipient timezone) — the quiet-hours guide covers that carve-out in its voice section.
They stack independently. A contact who never opted out can still be caught
by a frequency cap; a send inside your quiet-hours window still respects
your duplicate-content policy.
Admission order — the chain a send actually walks
A single send is evaluated in the order below. The first gate that refuses ends the attempt — later gates are never reached, so a duplicate never burns a frequency-cap slot and an opted-out recipient never reaches either check.- Outbox admission. The API validates the request, resolves the sender, and opens an outbox/inbox-visibility ledger entry for the send attempt.
- Pre-approval: quiet hours + duplicate-content claim.
The quiet-hours evaluator runs against recipient-local time; a blocked
send reports
next_allowed_at. The message-suppression policy claims a content hash for<channel, recipient, body>inside your window — a second identical body in that window drops here. - Outbound-flags fast path (wallet/billing). The org’s
outbound_paused/outbound_blockedgate is consulted next. A paused org is refused with402 SENDING_PAUSED; free channels (WhatsApp, Telegram, …) bypass a balance-driven pause but stay subject to account-lifecycle holds. - Per-recipient block lists. Opt-out and suppression-list membership is
checked; a blocked recipient is refused with
422 RECIPIENT_OPTED_OUT(direct sends) or skipped (campaign sends). - Frequency-cap slot claim.
consumeSlottest-and-increments atomically; over the cap, direct sends get429 FREQUENCY_CAP_EXCEEDED, campaign sends skip with reasonfrequency_capped. - Throughput caps. The per-messaging-service MPS counter, then the
per-number MPS counter (independent of each other), each return
429withRetry-After: 1when the current second’s budget is exhausted. - Provider dispatch. The send reaches the carrier/provider; the row advances into the delivery lifecycle. From here the outcome is the network’s, not a gate’s.
503 INTERNAL_COMPLIANCE_ERROR you can retry explicitly) and open for
transactional, while billing-flag, frequency-cap, suppression, and MPS
checks fail open so an infra blip never silently black-holes your
outbound.
Where each gate fires
Gates attach at different points in the send pipeline:- At send admission, before a segment is counted or any quota slot is held: quiet hours, the wallet/billing flags, block lists, duplicate suppression, frequency caps. A refusal here means no ledger debit and no provider call.
- At the pre-dispatch claim stage: the duplicate-content hash and the frequency-cap slot are claimed, not just checked — concurrent senders can’t both pass by racing a read.
- At throughput admission: the per-service and per-number MPS counters run at the messaging-service / number resolution step, so a burst throttles where the ceiling is defined.
- At dispatch time, not request time: a
scheduled_atsend bypasses quiet hours at request time and is re-evaluated when the scheduler fires — a send accepted today is not grandfathered into a window that closed by dispatch time. Gates always evaluate now, against your current settings.
Suppression and skipping vs. pausing — two different “no”s
The gates resolve to two superficially similar but semantically different outcomes, and your integration should branch them distinctly: A suppressed or skipped send reached a gate that says “this send, this recipient, this body — no.” The pipeline returns a success-shaped result withstatus: "skipped" and a reason (duplicate_content, opted_out,
frequency_capped, erasure_pending), so a campaign batch keeps moving
through the rest of its recipient list. Depending on the channel and gate,
a suppressed row can also persist as an
operational sentinel — a settled,
non-delivery status operators can see in the timeline and that your
reporting must exclude from delivery-rate math. Skipped/suppressed sends
refund any quota slot the pipeline pre-claimed — you never lose an
allowance for a message that was never handed to a provider.
A paused send never got a body-level answer at all. The wallet/billing
gate refuses the entire send with 402 SENDING_PAUSED (or
SENDING_BLOCKED); no message row is created, and nothing is queued. There
is no skipped status to poll — the send simply does not exist until you
resolve the pause and resubmit. Read the pause state and its reason
(outbound_paused, outbound_block_reason, payment_failure_count) off
GET /billing/balance; treat 402 as terminal for that send rather than
retrying in a hot loop.
In short: suppression is per-message and usually recoverable for the rest of
a batch; a pause is org-wide and recoverable only by resuming the org.
What to branch on
Model it once, truth it everywhere
If you need one sentence to take away: a send leaves only after every gate you enabled says yes, in admission order — and each rejection is surfaced as a specific signal you can branch on. You own every posture in this chain; turning a gate off is your call, and the defaults above are the starting point.See also
- Wallets, credits, and charges — the prepaid ledger, the pause flags, and 402 semantics
- Operational sentinels — the settled-but-not-delivery statuses suppression writes
- Delivery lifecycle — what happens after every gate says yes
- Quiet hours configuration — the two knobs, timezone resolution, and the voice carve-outs
- Frequency caps — rolling-window per-contact limits
- Message suppression — the duplicate-content content-hash policy
- Opt-out suppression — per-channel recipient block lists
- Send gates — the preview endpoint and the rest of the gate stack
- Voice & messaging pricing and throughput — the MPS and rate-limit controls
- Rate limits — per-endpoint API request limits and retry patterns