> ## 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.

# Outbound send gating: the tenant-owned controls that decide whether a message dispatches

> How the wallet pause, opt-out and suppression lists, quiet hours, duplicate-content suppression, frequency caps, and throughput caps compose into one admission model — in the order a send actually walks them — and what each blocked outcome looks like to your integration.

# 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](/guides/quiet-hours-configuration) covers that carve-out
in its voice section.

| Gate                                                                             | Question it answers                                                                                 | Default                                                                                                    | Surface                                                                                                        |
| -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Wallet pause / billing gate**                                                  | Is outbound allowed for my org at all — is there balance, a billing-alert pause, or a dunning hold? | Open. An empty wallet auto-pauses; alerts and actions are yours to configure.                              | [Wallets, credits, and charges](/concepts/wallets-credits-and-charges) · [Billing overview](/billing/overview) |
| **Recipient block lists** (opt-out, suppression lists, duplicate-content policy) | Has this recipient told me to stop — or did this exact body already reach them?                     | Opt-out lists are the standard posture; the duplicate-content policy is opt-in.                            | [Opt-out suppression](/compliance/opt-out-suppression) · [Message suppression](/guides/message-suppression)    |
| **Quiet hours**                                                                  | Is it allowed right now, recipient-local, on this channel — per my window?                          | Off per channel. Campaign voice to US recipients stays hard-blocked outside the federal window regardless. | [Quiet hours configuration](/guides/quiet-hours-configuration)                                                 |
| **Frequency caps**                                                               | Has this contact already received too many sends of this kind inside my window?                     | Off — no cap until you create one.                                                                         | [Frequency caps](/guides/frequency-caps)                                                                       |
| **Throughput caps** (per-service / per-number MPS, API rate limits)              | Am I sending faster than the ceiling I set?                                                         | API rate limits apply to everyone; MPS caps are off until set.                                             | [Throughput](/guides/voice-messaging-pricing-throughput)                                                       |

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.

1. **Outbox admission.** The API validates the request, resolves the sender,
   and opens an outbox/inbox-visibility ledger entry for the send attempt.
2. **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.
3. **Outbound-flags fast path (wallet/billing).** The org's `outbound_paused`
   / `outbound_blocked` gate is consulted next. A paused org is refused with
   `402 SENDING_PAUSED`; free channels (WhatsApp, Telegram, …) bypass a
   balance-driven pause but stay subject to account-lifecycle holds.
4. **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).
5. **Frequency-cap slot claim.** `consumeSlot` test-and-increments
   atomically; over the cap, direct sends get `429 FREQUENCY_CAP_EXCEEDED`,
   campaign sends skip with reason `frequency_capped`.
6. **Throughput caps.** The per-messaging-service MPS counter, then the
   per-number MPS counter (independent of each other), each return `429`
   with `Retry-After: 1` when the current second's budget is exhausted.
7. **Provider dispatch.** The send reaches the carrier/provider; the row
   advances into the [delivery lifecycle](/concepts/delivery-lifecycle).
   From here the outcome is the network's, not a gate's.

The resilience posture differs per gate — worth knowing when you model worst
cases: the quiet-hours evaluator fails **closed** for marketing traffic (a
`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_at` send 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
with `status: "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](/concepts/operational-sentinels) — 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

| Signal                                                                                        | Meaning                                                                                                  | Handling                                                                                                              |
| --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `402 SENDING_PAUSED` / `402 SENDING_BLOCKED`                                                  | Wallet empty, billing-alert pause fired, dunning hold, or suspension.                                    | Stop, poll `GET /billing/balance` until `outbound_paused` flips false, then resume. Never hot-loop.                   |
| `429 FREQUENCY_CAP_EXCEEDED`                                                                  | This recipient is over a cap you set.                                                                    | Honor `retry_after_seconds`; skip the contact this window. Campaign sends skip automatically with `frequency_capped`. |
| `429 RATE_LIMITED` (API key)                                                                  | Too many requests per minute.                                                                            | Honor `retry_after`; back off.                                                                                        |
| `429` + `Retry-After: 1` (MPS caps)                                                           | Over a per-service or per-number MPS ceiling.                                                            | Wait the second; the throttle resets every second.                                                                    |
| `422 RECIPIENT_OPTED_OUT`                                                                     | Recipient is on the channel's opt-out list.                                                              | Remove them from your audience until they re-consent.                                                                 |
| `422 QUIET_HOURS_BLOCKED`                                                                     | Outside your quiet-hours window.                                                                         | Schedule at `next_allowed_at` instead of retrying.                                                                    |
| `422 QUIET_HOURS_TIMEZONE_UNKNOWN` (`TCPA_TIMEZONE_UNKNOWN` on voice)                         | Gate couldn't resolve the recipient's timezone under a `deny` policy.                                    | Supply `recipientTimezone`, or change `unknown_timezone_policy` to `skip`/`enforce_utc`.                              |
| `503 INTERNAL_COMPLIANCE_ERROR`                                                               | The quiet-hours evaluator itself failed on a marketing send (fail-closed).                               | Retry shortly — this is a gate error, not a verdict.                                                                  |
| `status: "skipped"` (`duplicate_content`, `opted_out`, `frequency_capped`, `erasure_pending`) | A gate dropped this send but the batch continues.                                                        | Treat as a per-recipient no-op, not an error.                                                                         |
| `status: "suppressed"` sentinel                                                               | On channels that persist the blocked attempt, the settled row proves the duplicate/opt-out was absorbed. | Exclude from delivery-rate math; never count as a failure.                                                            |

## 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](/concepts/wallets-credits-and-charges) — the prepaid ledger, the pause flags, and 402 semantics
* [Operational sentinels](/concepts/operational-sentinels) — the settled-but-not-delivery statuses suppression writes
* [Delivery lifecycle](/concepts/delivery-lifecycle) — what happens after every gate says yes
* [Quiet hours configuration](/guides/quiet-hours-configuration) — the two knobs, timezone resolution, and the voice carve-outs
* [Frequency caps](/guides/frequency-caps) — rolling-window per-contact limits
* [Message suppression](/guides/message-suppression) — the duplicate-content content-hash policy
* [Opt-out suppression](/compliance/opt-out-suppression) — per-channel recipient block lists
* [Send gates](/compliance/send-gates) — the preview endpoint and the rest of the gate stack
* [Voice & messaging pricing and throughput](/guides/voice-messaging-pricing-throughput) — the MPS and rate-limit controls
* [Rate limits](/guides/rate-limits) — per-endpoint API request limits and retry patterns
