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

# Quiet hours: org-wide channel gates vs. the campaign fallback window

> Choose your quiet-hours posture: the per-channel organization gate, the drip/journey fallback window, and how the two knobs interact for public 1:1 sends versus campaign traffic.

# Quiet hours: org-wide channel gates vs. the campaign fallback window

Orbit's quiet-hours gate is tenant-owned: everything on this page is a
control **you** configure (or choose to leave off). The only exception is
the TCPA federal voice window for US recipients, covered in its own
section below. Opting into quiet hours is your call — nothing here is
required by CAN-SPAM or GDPR.

This page is the operator runbook for that gate. Three surfaces compose
your posture:

1. **The org-wide channel gate** — per-channel toggles in organization
   settings (`settings → quiet_hours.<channel>.enabled`), written through
   `PUT /api/v1/settings/general` and mirrored in the dashboard org
   settings (see also [Compliance posture](/compliance/posture-overview)).
2. **The campaign fallback window** — a single org-wide start/end pair
   for drip and journey sends whose campaign row carries no explicit
   window. In the dashboard: **Settings → Campaign limits → Default quiet
   hours**; over the API: `GET`/`PUT /api/v1/campaigns/quiet-hours/settings`.
3. **The preview endpoint** — `GET /api/v1/compliance/quiet-hours/preview`,
   a read-only check that answers "would this send to this recipient go
   through right now?" Run it before every rollout; it's worked through in
   the runbook below.

## The two windows

| Knob                                                             | Covers                                                                                                              | Configured where                                                                                   |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Org-wide channel gate (`organizations → settings → quiet_hours`) | Every send on each channel you enable: dashboard, API, flows, campaign dispatch                                     | The `quiet_hours` block in organization settings (see below)                                       |
| Campaign fallback window                                         | Drip + journey sends only, and only when the campaign row has no `quiet_hours_start` / `quiet_hours_end` of its own | Settings → Campaign limits → Default quiet hours, or `campaigns/quiet-hours/settings` over the API |

The campaign fallback is exactly what its name says — a fallback, not a
second gate. Resolution order for a campaign send: the campaign row's own
window, then the org fallback, then the platform default 21:00 → 09:00
(quiet hours run 9 PM to 9 AM recipient-local).

The two knobs can disagree. A campaign-dispatched send evaluates the
campaign path's window as one layer; the org channel gate — when you've
enabled that channel — is a separate layer evaluated at the send site.
Treat the org gate as the posture for 1:1 traffic and the campaign
fallback as the default regime for bulk traffic. A blocked send reports
`next_allowed_at` — schedule around the window rather than retrying.

The fallbacks you can set at either layer can only ever **narrow** the
envelope; they never widen a channel gate you've enabled.

## Org-wide per-channel gate

The channel gate is opt-in per channel. Each per-channel entry supports:

| Field          | Meaning                                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
| `enabled`      | Whether the gate applies to this channel. All channels default to `false`.                                         |
| `start_hour`   | Inclusive 24h start hour (0–23), e.g. `8` for 8 AM recipient-local.                                                |
| `end_hour`     | Exclusive 24h end hour (0–23), e.g. `21` for 9 PM recipient-local. `start_hour > end_hour` is an overnight window. |
| `allowed_days` | Optional list of allowed weekdays, `0` = Sunday … `6` = Saturday. Omit to allow every day.                         |

Org-level keys (apply to all channels together):

| Key                             | Meaning                                                                                                                                                                    |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `default`                       | A partial window that fills in fields a per-channel entry didn't set.                                                                                                      |
| `unknown_timezone_policy`       | `skip` (default), `enforce_utc`, or `deny` — see the timezone section below.                                                                                               |
| `consent_overrides_quiet_hours` | When `true` (default), a recipient with an explicit-consent record passes through the gate — the TCPA "prior express consent" carve-out. Works on non-voice channels only. |

### Default posture per channel

Until you enable a channel, nothing is held. When you flip a channel on
without specifying hours, the platform hours kick in:

| Channels                                                       | Default window (recipient-local) |
| -------------------------------------------------------------- | -------------------------------- |
| `sms`, `mms`, `rcs`, `viber`, `telegram`, `voice`              | 08:00–21:00                      |
| `whatsapp`, `instagram`, `messenger`, `apple_messages`, `line` | 09:00–21:00                      |
| `email`, `fax`, `push`, `web_chat`                             | 08:00–21:00 when enabled         |

The full channel set accepted by the gate: `sms`, `mms`, `whatsapp`, `rcs`,
`viber`, `telegram`, `voice`, `email`, `instagram`, `messenger`, `line`,
`apple_messages`, `fax`, `push`, `web_chat`.

### Two carve-outs that keep essential traffic flowing

* **Prior express consent** — with `consent_overrides_quiet_hours` true
  (the default), a recipient with an explicit-consent record passes through
  on any non-voice channel. Voice never takes this carve-out.
* **Transactional traffic lane** — sends the caller tags as transactional
  (OTPs, alerts, account notifications) are exempt from the gate even on an
  enabled channel. Voice never takes this carve-out either.

Set `consent_overrides_quiet_hours` to `false` only if you want stopped
sends with no consent exceptions.

## Campaign fallback window

Any authenticated caller reads it; only owner/admin writes it.

Read the current fallback window:

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/campaigns/quiet-hours/settings \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

```json theme={null}
{
  "enabled": false,
  "start_hour": null,
  "end_hour": null,
  "platform_default_start": 21,
  "platform_default_end": 9
}
```

`platform_default_start` / `platform_default_end` echo the hours drip and
journey sends use while the override is off — inherit them or replace them,
your choice. In the dashboard this form is **Settings → Campaign limits →
Default quiet hours**. Set your own window (both hours are required when
`enabled` is true):

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/campaigns/quiet-hours/settings \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "start_hour": 22, "end_hour": 7 }'
```

Clear back to the platform default:

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/campaigns/quiet-hours/settings \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'
```

Overnight windows (e.g. start `22`, end `7`) are accepted at both layers —
a `start > end` pair wraps around midnight.

## Recipient timezone resolution

The gate works in *recipient-local* time. Timezone resolution follows this
chain:

1. An explicit `recipientTimezone` hint from the caller, when supplied.
2. US area code → IANA timezone, for +1 numbers.
3. E.164 country code → a representative IANA timezone (Europe, Asia, the
   Americas, and common operator markets).
4. For email recipients, the organization's default timezone.
5. When none of the above resolves — the org's `unknown_timezone_policy`
   (also configurable in the dashboard at **Settings → Voice**):

| Policy                                                       | Behaviour                                                                           |
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `skip` (default for every channel except US-recipient voice) | Allow — fail open for recipients outside US jurisdiction.                           |
| `deny` (default only for US-recipient voice)                 | Block. Returns `422 QUIET_HOURS_TIMEZONE_UNKNOWN` (voice: `TCPA_TIMEZONE_UNKNOWN`). |
| `enforce_utc`                                                | Evaluate against UTC — a deterministic window regardless of the recipient.          |

If the recipient does resolve to a timezone, an ordinary enabled-channel
block returns `422 QUIET_HOURS_BLOCKED` (voice: `TCPA_DIALING_WINDOW_BLOCKED`)
with the window and `next_allowed_at` in the error details.

## TCPA federal voice carve-out

Campaign and dialer voice to **US recipients** is hard-blocked outside the
8 AM–9 PM recipient-local federal window — no org gate, fallback window, or
consent flag relaxes it, and a US recipient whose timezone can't be
resolved is blocked fail-closed. This is the one knob the platform owns;
it applies to campaign and dialer voice only, not to 1:1 ad-hoc calls or
any messaging channel.

Non-US recipients play by the ordinary gate: the fail-open `skip` policy
applies to recipients outside US jurisdiction, and your own voice channel
gate (if enabled) layers on top. You can always tighten past the federal
window — e.g. a voice gate of 09:00–20:00 recipient-local — but you can
never widen it.

Ad-hoc 1:1 voice from the dashboard outside the federal window dials
through with an advisory log unless you've enabled the `voice` channel on
the org gate, which makes it a hard hold (`422 TCPA_DIALING_WINDOW_BLOCKED`).

## Consent overrides quiet hours

With `consent_overrides_quiet_hours: true` (the default), a recipient you
hold explicit-consent for passes the gate on **non-voice** channels — the
TCPA "prior express consent" carve-out. A permitted recipient stays
reachable inside your closed hours; a contact without a consent record is
held until the window opens.

Set it to `false` when consent must never relax your window. The gate
ignores the flag entirely on the `voice` channel — voice hinges on the
federal window and state overlays, not the consent carve-out.

## State mini-TCPA overlays

Some US states layer a stricter calling window or day-of-week ban on top
of the federal hours (Florida's Sunday ban, Oklahoma/Mississippi windows,
and others). Overlays compose as **most-restrictive-wins**: a send must
clear the federal window *and* every applicable state overlay; the overlay
can tighten but never widen. Voice blocks trace back with these failure
reasons:

* `outside_state_window` — a state overlay tightened the window and this
  hour fell outside it.
* `state_blocked_day` — the overlay bans dialing on this weekday entirely.

The full state-by-state table and which recipient states resolve into each
overlay live in [US state calling windows](/compliance/state-calling-windows).

## Operational runbook

**Rollout checklist.** Before you flip a channel on or push a broad list:

1. Preview a sample of recipients with
   `GET /api/v1/compliance/quiet-hours/preview?phone=<E.164>&channel=<channel>`,
   adding `timezone_override=<IANA>` only when your CRM carries a better
   hint than the number resolves to.
2. Confirm the org gate block: `GET /api/v1/settings/general` and read the
   `quiet_hours` tree before `PUT` — writes merge at the top level, but the
   `quiet_hours` key itself is replaced wholesale (see the write section
   below).
3. For bulk rollouts, watch `GET /api/v1/settings/compliance-health` — its
   warnings rank the worst offender (most-held sender, error clusters) so
   you fix the noisiest lane first.

**Holds are per-recipient, not per-tenant.** One contact held at 21:05
recipient-local blocks only that contact's sends; the rest of your batch
keeps admitting in parallel. A held 1:1 send throws `422 QUIET_HOURS_BLOCKED`
with `next_allowed_at` in the error details — schedule at that timestamp
instead of retrying in a loop. A held send never consumes a quota or slot
reservation, so retries re-admit cleanly once the window opens.

**Writes take up to about a minute to reach every send site** — org
settings are cached briefly in the send path. Reads are immediate; verify
the merged posture back with a `GET` before rolling out.

## Worked examples

### Bulk rollout at 21:05 — hold-queue behaviour

You push a 1,000-recipient list through the API at a moment when a slice
of your list sits outside your 08:00–21:00 org gate recipient-local. Each
recipient resolves independently against your enabled `sms` gate:

* In-window recipients admit immediately.
* Held recipients get a `422` with `next_allowed_at`; your worker parks
  them and continues the batch. The batch itself isn't paused — holds are
  per-recipient.
* When each recipient's window reopens, re-submit the parked row; no slot
  was burned while held.

Double-check a specific recipient without burning the attempt:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/compliance/quiet-hours/preview?phone=%2B14155551234&channel=sms" \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

```json theme={null}
{
  "allowed_now": false,
  "local_hour": 21,
  "local_timezone": "America/New_York",
  "window_start_local": "08:00",
  "window_end_local": "21:00",
  "next_allowed_at": "2026-08-26T12:00:00Z",
  "reason": "outside_window",
  "channel": "sms"
}
```

`next_allowed_at` is a DST-safe ISO timestamp — pass it straight to your
scheduler.

### Timezone-unresolved US voice recipient — fail-closed

A campaign voice dial to `+15551234567` where the area code resolves no
timezone runs into the federal guard's fail-closed posture: the dial is
refused with `422 TCPA_TIMEZONE_UNKNOWN` before any window math. Fix the
data — set the contact's timezone on the record or pass
`recipientTimezone` — then requeue.

The same unresolved input on the `sms` channel with
`unknown_timezone_policy: "deny"` ends in `422 QUIET_HOURS_TIMEZONE_UNKNOWN`;
with the default `skip` policy it passes fail-open. The `deny` policy is
only the default for US-recipient voice, per the federal carve-out above.

### Consent override inside the window

Two contacts, `sms` gate enabled, 22:30 recipient-local (outside your
window):

```text theme={null}
contact a — consent record on file      → allowed (reason: consent_override)
contact b — no consent record           → held (422 QUIET_HOURS_BLOCKED)
```

With `consent_overrides_quiet_hours: false`, both hold until 08:00
recipient-local. On `voice`, the flag doesn't apply at all — every voice
attempt is gated on window math alone.

## Enable a channel via the organization settings API

There is no dedicated quiet-hours write endpoint for the channel gate; it
lives inside the organization settings store, and every send reads it.
Update it through `PUT /api/v1/settings/general` (owner/admin):

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/settings/general \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "quiet_hours": {
        "sms": { "enabled": true },
        "whatsapp": { "enabled": true, "start_hour": 9, "end_hour": 21 },
        "unknown_timezone_policy": "skip",
        "consent_overrides_quiet_hours": true
      }
    }
  }'
```

Read the current posture back with `GET /api/v1/settings/general` and look
at the `quiet_hours` block in the returned `settings`.

<Warning>
  Merge-then-verify. `PUT /settings/general` merges settings at the top
  level, so a write that contains *only* `quiet_hours` keeps your other
  settings intact — but a write at whose root you place a full `quiet_hours`
  object REPLACES that key. If you mean to keep existing entries (for
  example a `default` window or the campaign fallback's stored leaf keys),
  read the current block first and merge before writing.
</Warning>

Writes take up to about a minute to reach every send site — org settings
are cached briefly in the send path.

## Choose a posture

1. **Leave everything off (default)** if you operate outside quiet-hours
   jurisdictions, or you handle limits elsewhere. One caveat: US campaign
   and dialer voice stays hard-blocked — that one can't be turned off.
2. **US marketing operator** — enable `sms` (and voice if you dial ad-hoc)
   on the org gate; platform hours 08:00–21:00 recipient-local apply
   immediately. The consent carve-out keeps permitted recipients reachable.
3. **EU/APAC operator with drip campaigns** — set the campaign fallback to
   your local window (e.g. 22:00 → 07:00) in Settings → Campaign limits so
   every drip and journey that lacks its own window sends inside your
   regime. Add the org gate per channel if you also want 1:1 traffic held.

## See also

* [Send gates](/compliance/send-gates) — the preview endpoint and the full
  gate stack (DNC, RND, emergency stop).
* [US state calling windows](/compliance/state-calling-windows) — which
  states carry a stricter mini-TCPA overlay and how the block traces back
  to a statute.
* [API Reference → Compliance](/api-reference/endpoints/compliance) — full
  request/response schemas.
* [Campaign A/B testing](/guides/campaign-ab-testing) — how winner-picking
  and hold-out experiments route through this gate and per-contact
  [frequency caps](/guides/frequency-caps).
