> ## 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 Preview: Channel-by-Channel Semantics

> Read the GET /compliance/quiet-hours/preview response correctly per channel — the fields it returns, how voice forks between campaign hard block and ad-hoc advisory, how email resolves a timezone without a phone number, which consumers act on the verdict, worked examples per channel, and the edge cases that decide your plan.

# Quiet-Hours Preview: Channel-by-Channel Semantics

`GET /api/v1/compliance/quiet-hours/preview` answers "would this send
to this recipient, on this channel, dispatch right now?" — as a
read-only check. This page walks the response field by field, then
per channel: where **voice** splits between the always-hard campaign
path and the advisory ad-hoc path, how **email** picks a timezone
when the recipient is an address rather than a phone number, and the
stable SMS and Meta-channel defaults. The worked calls and the edge
cases at the end cover the conditions that decide what you do with a
blocked verdict.

All examples are rooted at
`https://api.orbit.devotel.io/api/v1/compliance`.

## 1. The preview response

Send `phone` (E.164) and `channel` (required), plus an optional
`timezone_override` (IANA name) when your CRM knows better than the
area code. The response is a decision snapshot — nothing is sent,
logged to the recipient, or suppressed.

| Field                                     | Meaning                                                                                                                                                                                                        |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowed_now`                             | `true` when the send would dispatch at evaluation time.                                                                                                                                                        |
| `local_hour`                              | Recipient-local hour (0–23) the decision evaluated, when computable. `null` for a pass-through channel.                                                                                                        |
| `local_timezone`                          | IANA timezone resolved for the recipient: your `timezone_override` hint, the NANP area-code lookup, the country-prefix map, or UTC fallback. `null` for a pass-through channel.                                |
| `window_start_local` / `window_end_local` | The window applied, in `HH:MM`; the end is exclusive (a 21:00 end means the last minute is 20:59).                                                                                                             |
| `next_allowed_at`                         | DST-safe ISO instant the gate reopens. When `allowed_now` is `false` this is the instant to schedule to; when `allowed_now` is `true` it echoes the evaluation time so you never special-case an absent field. |
| `reason`                                  | One of the enum below — read it before planning, because a predictable-window block and a denied-unknown-timezone block call for different actions.                                                            |
| `channel`                                 | Echoes the channel evaluated, for log correlation.                                                                                                                                                             |

The `reason` enum:

| `reason`                    | Reads as                                             | Your plan                                                                                                                                                              |
| --------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowed`                   | Inside the window                                    | Dispatch now                                                                                                                                                           |
| `channel_disabled`          | The gate is off for this channel on your org         | Dispatch now (no window applied)                                                                                                                                       |
| `consent_override`          | The recipient's consent record passed the gate       | Dispatch now                                                                                                                                                           |
| `transactional_lane_exempt` | Non-voice transactional traffic flows 24/7           | Dispatch now                                                                                                                                                           |
| `unknown_timezone_skip`     | Unresolved timezone, non-voice default policy `skip` | Dispatch now; the org default is fail-open                                                                                                                             |
| `outside_window`            | Local hour outside the window                        | Schedule to `next_allowed_at`                                                                                                                                          |
| `wrong_day`                 | Local weekday banned by the window                   | Schedule to `next_allowed_at`                                                                                                                                          |
| `unknown_timezone_deny`     | Unresolved timezone, policy `deny`                   | Fail-closed for campaign/dialer voice to US recipients worldwide; otherwise only when you set org policy `deny` — pass `timezone_override` or fix the contact timezone |

The blocked trio at the bottom is the set that needs a retry plan.
`allowed_now` is `true` on every allowed reason.

## 2. Voice — the two enforcement forks

Voice is the only channel where the *owner of the verdict* changes by
path. The preview returns the window evaluation; reading `false`
differently per path is the whole point of this section.

**Campaigns and dialers: hard block, always.** US (+1) recipients on
campaign or dialer traffic — predictive, progressive, preview, and
agentless modes, scheduled callbacks — are refused outside the window
regardless of your tenant settings. There is no org opt-out on this
path; your quiet-hours toggle neither relaxes nor replaces it. When
`allowed_now` reads `false`, `next_allowed_at` is the instant your
campaign scheduler waits for.

**Ad-hoc 1:1 dials: advisory until you opt in.** A dashboard or
softphone dial outside the window dispatches with the decision logged.
`allowed_now: false` here is a caution you can override at the
dialer — unless you enabled the `voice` channel on your org gate via
[quiet hours configuration](/guides/quiet-hours-configuration), in
which case every outside-window dial holds until `next_allowed_at`.

**US recipients get the federal window — intersected with state
overlays.** The binding hour range is eight-to-nine recipient-local
intersected with any mini-TCPA overlay the area code maps to, e.g. a
Florida recipient closes at 8 PM and never dials on Sunday. The
non-US recipient skips the federal wire entirely; they hit your org
gate if opted in, or pass through. The overlay table and the
decision's gate order are on
[US state calling windows](/compliance/state-calling-windows).

## 3. SMS and Meta messaging channels — the stable semantics

SMS, MMS, RCS, Viber, and Telegram default to 08:00–21:00 once you
enable each channel; WhatsApp and the Meta channels (Instagram,
Messenger, Apple Messages, LINE) default to 09:00–21:00. The window
applies only when you enabled the channel on your org gate — a
disabled channel returns `reason: channel_disabled` and dispatches.

SMS also reads the campaign fallback window when the recipient is in a
campaign: the campaign row's own window, then the org default fallback
window, then the platform defaults. Fallbacks only ever narrow the
channel window. Full mechanism on
[quiet hours configuration](/guides/quiet-hours-configuration) and
[TCPA posture across SMS and voice](/guides/tcpa-quiet-hours-and-windows).

## 4. Email — DST-correct evaluation without a phone number

Email recipients are addresses, so the timezone resolution differs:
your `timezone_override` hint, then the org default timezone, then the
org `unknown_timezone_policy` fallback — `skip` (default, fail-open),
`enforce_utc`, or `deny`.

The window applied is recipient-local hour math resolving to a UTC
instant. The detail of `next_allowed_at` — DST-gap straddles,
Arizona and Hawaii non-observance, integer-hour traps — lives on the
[quiet-hours DST crossover walkthrough](/guides/quiet-hours-dst-crossover).
Schedule to that field; never re-derive hours in your own scheduler.

## 5. Where the preview result flows

**Campaign pre-flight.** Before a launch, pre-flight previews the
recipient set per channel. A blocked preview pushes the launch to the
smallest `next_allowed_at`; the per-channel reasons tell you whether
to reschedule the whole campaign or hold the specific channels that
are blocked.

**Schedule workers.** Workers that fan a queue send against
recipient-local time poll the preview and hold until
`next_allowed_at`; the DST-safe ISO means a queue survives a 23- or
25-hour night without drifting (see the
[DST crossover guide](/guides/quiet-hours-dst-crossover) for the
allowed-hour math).

**Dialer pacing.** A pacing loop that batches recipient time zones
splits the queue into "dispatch now" and "hold" buckets on the verdict;
a per-bucket `next_allowed_at` sets re-poll instead of a fixed delay.

Dashboard and agent surfaces use the same read for a "would this go
through now" indicator, without burning a real send.

## 6. Worked calls

Assume `ORBIT_API_KEY` holds a live API key.

### SMS — enabled, in window

```bash theme={null}
curl -G "https://api.orbit.devotel.io/api/v1/compliance/quiet-hours/preview" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  --data-urlencode "phone=+14155550101" \
  --data-urlencode "channel=sms"
```

```json theme={null}
{
  "allowed_now": true,
  "local_hour": 14,
  "local_timezone": "America/Los_Angeles",
  "window_start_local": "08:00",
  "window_end_local": "21:00",
  "next_allowed_at": "2026-06-09T22:51:00.000Z",
  "reason": "allowed",
  "channel": "sms"
}
```

### SMS — enabled, blocked on hour

Same call at 22:00 local:

```json theme={null}
{
  "allowed_now": false,
  "local_hour": 22,
  "local_timezone": "America/Los_Angeles",
  "window_start_local": "08:00",
  "window_end_local": "21:00",
  "next_allowed_at": "2026-06-10T15:00:00.000Z",
  "reason": "outside_window",
  "channel": "sms"
}
```

### Voice — campaign path hard block (state overlay)

```bash theme={null}
curl -G "https://api.orbit.devotel.io/api/v1/compliance/quiet-hours/preview" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  --data-urlencode "phone=+13055550101" \
  --data-urlencode "channel=voice"
```

Miami recipient, Sunday, 8:30 PM:

```json theme={null}
{
  "allowed_now": false,
  "local_hour": 20,
  "local_timezone": "America/New_York",
  "window_start_local": "08:00",
  "window_end_local": "20:00",
  "next_allowed_at": "2026-06-10T13:00:00.000Z",
  "reason": "wrong_day",
  "channel": "voice"
}
```

The same verdict is a **hold** on the campaign path — schedule to
`next_allowed_at`. On an ad-hoc dial it is **advisory**: the dial
dispatches unless your `voice` gate is on.

### Email — enforced via org timezone

```bash theme={null}
curl -G "https://api.orbit.devotel.io/api/v1/compliance/quiet-hours/preview" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  --data-urlencode "phone=+12125550199" \
  --data-urlencode "channel=email"
```

Because the email preview carries a phone, it resolves the timezone
from the NANP area code just like SMS. On an actual email send the
recipient is an address, so the gate falls back to the org default
timezone, then the org `unknown_timezone_policy`. With the org default
set to `America/New_York`:

```json theme={null}
{
  "allowed_now": false,
  "local_hour": 23,
  "local_timezone": "America/New_York",
  "window_start_local": "08:00",
  "window_end_local": "21:00",
  "next_allowed_at": "2026-06-10T13:00:00.000Z",
  "reason": "outside_window",
  "channel": "email"
}
```

### Pass-through — email, fax, push, web\_chat not evaluated

```bash theme={null}
curl -G "https://api.orbit.devotel.io/api/v1/compliance/quiet-hours/preview" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  --data-urlencode "phone=+14155550101" \
  --data-urlencode "channel=push"
```

```json theme={null}
{
  "allowed_now": true,
  "local_hour": null,
  "local_timezone": null,
  "window_start_local": null,
  "window_end_local": null,
  "next_allowed_at": "2026-06-09T22:51:00.000Z",
  "reason": "channel_disabled",
  "channel": "push"
}
```

Read `local_timezone` before planning on push/fax/web\_chat — a `null`
means the pass-through, not a failed resolution. Email/fax/push/web\_chat
skipped because the platform considers them asynchronous surfaces whose
morning delivery doesn't interrupt the recipient — but once you enable
one, `channel_disabled` stops appearing and the full contract applies.

## 7. Edge cases

**Recipient timezone unresolved.** Campaign/dialer voice to a US
recipient is fail-closed worldwide — the reason is
`unknown_timezone_deny` and the plan is to pass `timezone_override` or
fix the contact's timezone. Every other channel, and ad-hoc voice to
non-US recipients, defaults the policy to `skip` (allowed, reason
`unknown_timezone_skip`). Set the org policy to `enforce_utc` to
evaluate against UTC where `UTC` is the resolved `local_timezone`, or
to `deny` to hold.

**Non-US recipient.** The federal wire is skipped — the channel gate
applies if opted in, or `channel_disabled` passes. The country-prefix
map supplies a capital-city timezone for well-known markets, so
`unknown_timezone_skip` usually stays empty. A +1 NANP number that
resolves to no mapped area code (Canadian, Caribbean) fires the
`unknown_timezone_deny` on the voice campaign path.

**Pass-through channels.** `channel_disabled` means no window was
applied; the send dispatches. Enable one of
`email`/`fax`/`push`/`web_chat` and the semantics shift to resolved in
the section above.

**Campaign fallback narrowing.** SMS fallback windows can provide a
stricter window than the channel default (e.g. 09:00–20:00 on a
campaign row). A blocked preview on a campaign recipient surfaces the
*campaign* window bounds in `window_start_local` / `window_end_local`
— check your campaign window before assuming the org gate.

## See also

* [Send gates](/compliance/send-gates) — the preview and the federal
  dialer asymmetry in the full gate stack
* [US state calling windows](/compliance/state-calling-windows) — the
  overlay table, gate order, and the voice reading of the decision
* [TCPA posture across SMS and voice](/guides/tcpa-quiet-hours-and-windows) —
  the tenant-owned control map and campaign fallback windows
* [Quiet hours configuration](/guides/quiet-hours-configuration) —
  enable per channel, set fallback windows, set the unknown-timezone policy
* [Quiet hours DST crossover](/guides/quiet-hours-dst-crossover) —
  the pre-launch preview procedure and the two zones that drift
