Skip to main content

Quiet Hours FAQ: Org Gate vs. Campaign Fallback vs. Preview

Operators hit the troubleshooting pages TCPA window blocked calls and voice window sentinel breadcrumbs one issue at a time. This page consolidates the questions that generate that volume. Read this first; run the runbook at the bottom when a send is already blocked. The deep runbook lives in Quiet hours: org gates vs. the campaign fallback. This page answers; that page explains.

The four surfaces

Four surfaces read or explain your quiet-hours posture, and confusing them is the source of nearly every “why was this held?” ticket:
  1. The org-wide channel gate — per-channel toggles written through PATCH /api/v1/settings/compliance/quiet-hours. This gates every send on an enabled channel: dashboard, API, flows, and campaign dispatch alike. All channels ship off; a flips-on posture is additive.
  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 answer to “would this send to this recipient go through right now?” Its channel-by-channel semantics are mapped on Quiet-Hours Preview.
  4. The event-triggered survey dispatcher — auto-CSAT and auto-NPS sends apply the tenant’s TCPA posture when the dispatcher is ready to send. This is a deferral, not a terminal block: SMS-class channels wait for the recipient-local 08:00–21:00 window, while email is exempt from this survey hold.

Event-triggered survey hold: deferral, not deletion

When a conversation closes, the auto-CSAT/NPS dispatcher leaves the survey pending if an sms, whatsapp, rcs, or viber recipient is outside the 08:00–21:00 recipient-local window. It does not return a blocking error or drop the survey. The sweep checks pending rows every 60 seconds and dispatches at the next window opening, normally 08:00 recipient-local; the worst-case nightly hold is about 13 hours, so the deferral is bounded and self-clearing. This differs from the org gate’s request-path park-and-release behavior: the survey dispatcher owns the retry timing and does not require your caller to retry a failed request. It applies the tenant’s configured compliance posture to event-triggered sends; it is not a new legal requirement. Email is exempt from this survey hold because CAN-SPAM has no nightly send window. Tenant email quiet hours remain a separate, optional control; see why email has no federal window. The survey check fails open for non-US numbers and for numbers whose timezone cannot be resolved, so those surveys are not held by this dispatcher. Keep contact timezones current when you need recipient-local holding; compare the consent override behavior before treating an allowed off-hours send as a defect.

Which layer answers first?

None of them “answers first” — the org gate and the campaign path are separate layers, both evaluated at the send site:
  • 1:1 and ad-hoc traffic (dashboard send, API call, flow step): only the org channel gate applies, and only for channels you have enabled.
  • Campaign / drip / journey traffic: the campaign-path window resolves first — the campaign row’s own quiet_hours_start / quiet_hours_end, then the org fallback window, then the platform default 21:00 → 09:00 recipient-local. If you have also enabled that channel on the org gate, the send must clear both layers.
  • Pass-throughs on an enabled channel: two reasons admit a non-voice send even inside a closed window — the recipient’s explicit-consent record (consent_override) and the transactional traffic lane (transactional_lane_exempt). If your gate is on and a send still went, read My org gate is enabled but a send still went through — why?.
Either layer can only narrow the envelope, never widen it. The full layering table is in Quiet hours configuration.

Is the org-wide gate or the campaign fallback blocking my send?

The most-asked question, per troubleshooting volume. Read the organization → settings → quiet_hours document and the campaign fallback window together:
  • A 1:1 send that was held is always the org channel gate — the fallback window never touches ad-hoc traffic.
  • A campaign send that was held is whichever layer failed: the campaign row window, or the fallback, or the platform default — plus the org gate when that channel is enabled.
  • The 422 QUIET_HOURS_BLOCKED voice variant TCPA_DIALING_WINDOW_BLOCKED or preview reason tells you which window closed; the dashboard readback (GET the settings document with jq on the resolved map, as in the runbook) shows you why.
When in doubt, preview the recipient before blaming a layer: GET /api/v1/compliance/quiet-hours/preview?phone=<E.164>&channel=<channel> returns the exact window and reason the send path would apply.

How is next_allowed_at computed?

next_allowed_at is the earliest UTC timestamp at which the resolving recipient’s window reopens, computed recipient-local through the full resolution chain (explicit recipientTimezone hint, US area code, E.164 country code, org default for email, else the org’s unknown_timezone_policy). It is a DST-safe ISO timestamp — pass it straight to your scheduler instead of retrying in a loop. For a layering of multiple windows (campaign window + org gate), the timestamp is the first instant both layers admit. Holds are per-recipient and burn no quota, so re-submitting at next_allowed_at re-admits cleanly. The exact payload shape is on Quiet-Hours Preview.

Where do DST cutovers land?

The gate evaluates recipient-local wall time, so a DST transition shifts when your window opens relative to UTC — not relative to the recipient’s clock. The crossover-night runbook (Arizona, Hawaii, ambiguous windows) lives in Quiet hours across DST. Run the preview endpoint against a sample of recipients before the spring-forward and fall-back weekends and confirm the resolved local_timezone on the response. For USPS-recipient voice the hold never resolves to a timezone: the federal window blocks fail-closed with 422 TCPA_TIMEZONE_UNKNOWN — DST never comes into it. For non-voice channels the org’s unknown_timezone_policy (skip default / enforce_utc / deny) decides; see the resolution chain above and Number timezone and state resolution.

Do state mini-TCPA overlays touch the same layers?

Yes — state overlays (Florida’s Sunday ban, Oklahoma/Mississippi windows, and the rest) compose on top of whichever layers carry the send, as most-restrictive-wins. A campaign voice send must clear the federal window, the campaign-path window, the org gate (if the voice channel is enabled), and every applicable state overlay. Voice blocks report outside_state_window or state_blocked_day so a state hold is separable from a federal one. The state-by-state table is on US calling windows: federal TCPA + state overlays, with the posture composition in TCPA posture guide.

Worked runbook: a blocked send carrying next_allowed_at

  1. Capture the hold: your worker receives 422 QUIET_HOURS_BLOCKED (or TCPA_DIALING_WINDOW_BLOCKED on voice) and reads next_allowed_at out of the error details.
  2. Identify the layer: compare the error’s window_start_local / window_end_local against your stored org document (GET /api/v1/settings/compliance/quiet-hours) and the campaign fallback (GET /api/v1/campaigns/quiet-hours/settings) — the values match exactly one of the stored windows.
  3. Park the recipient: schedule the retry for next_allowed_at; do not burn attempts polling. Holds consume no quota and no slot reservation.
  4. Reverify before rollout-scale sends: preview a sample through GET /compliance/quiet-hours/preview, one per distinct timezone in the list, and confirm allowed_now: true.
  5. If the window is wrong: decide which layer owns the correction — the campaign row, the fallback, or the org gate — and fix it there. Writes propagate to every send site within about a minute, then reads confirm immediately.

Layered composition — the cross-layer questions

The either/or questions above cover one layer at a time. The tickets that escalate ask about two layers at once: a campaign that carries its own window AND inherits the fallback, a voice send that clears the campaign path but trips the federal guard, a contact whose CRM timezone disagrees with the area-code resolution. This section answers the composition questions — how the layers stack, which one wrote the audit entry, and how to prove the verdict after the send.

Which gates even run on this send?

The gates that evaluate depend on the traffic path, not on the channel alone. Two shapes cover every send:
A 1:1 send never touches the campaign path: it sees only the org channel gate, and only for channels you have enabled. A campaign send resolves the campaign-path window first (row → fallback → platform default, most-restrictive survives), then ALSO clears the org channel gate for every channel you enabled on it. The org gate and the campaign path are separate layers evaluated at the same send site — neither “answers first.” The full gate inventory is on Send gates; the campaign-path resolution order is on Quiet-Hours Preview.

A dual-qualified campaign was blocked — were both layers responsible?

Yes, and. A campaign send to a channel you enabled on the org gate must clear BOTH the campaign-path window and the org gate. When the send is held, the error names the layer that closed first — it does not name every layer that would have closed. Read it as “this is the layer that rejected the send,” not “this is the only layer that cared.” To tell which layer wrote the audit entry, match the error shape:
  • 422 QUIET_HOURS_BLOCKED with reason: outside_window or wrong_day — the campaign-path window, or the org gate if the send was 1:1. The window_start_local / window_end_local values identify which: compare them against your campaign row, then your fallback, then the platform default.
  • 422 TCPA_DIALING_WINDOW_BLOCKED — the federal voice guard, a separate platform rail that composes on top of the campaign path for US voice. This one has no tenant toggle.
  • 422 TCPA_FEDERAL_DIALING_WINDOW_BLOCKED — same federal rail, on the campaign/dialer voice path specifically.
When two layers would both reject, the audit entry records the first one that closed; fixing that layer and re-sending re-evaluates the remaining layers. Do not assume a single fix clears every hold — preview the recipient again after the change.

How do I prove after the fact which window applied to a specific send?

Each quiet-hours hold writes a structured audit entry keyed by the recipient and the send attempt. The lookup keys are the message_id (or call_id for voice) and the recipient’s E.164 phone; the entry carries the resolved local_timezone, the window_start_local / window_end_local that applied, the reason, and the next_allowed_at the scheduler consumed. To reconstruct a held send:
  1. Read the message or call record by message_id / call_id — its quiet_hours block carries reason, window_start_local, window_end_local, and next_allowed_at.
  2. Match the window values against your stored layers: the campaign row (GET /api/v1/campaigns/{id}), the fallback (GET /api/v1/campaigns/quiet-hours/settings), and the org gate (GET /api/v1/settings/compliance/quiet-hours). Exactly one stored window matches the values in the audit entry — that is the layer that applied.
  3. For voice, also read the federal block separately: the federal guard writes its own entry (the reason carries the federal code) independent of the campaign path.
The preview endpoint returns the same fields a held send would record, so GET /api/v1/compliance/quiet-hours/preview?phone=…&channel=… reproduces the decision without re-sending. Run it with the recipient’s stored timezone_override when your CRM knows better than the area code.

One posture per campaign group, not per campaign row

Setting quiet_hours_start / quiet_hours_end on every campaign row does not scale, and most operators do not need to. The resolution order is designed so a group of campaigns inherits a single posture from the org fallback unless a row overrides it:
  1. Campaign row override — quiet_hours_start / quiet_hours_end on the campaign row, when present, wins for that campaign only. Use it for the one campaign that needs a tighter window than its group.
  2. Org campaign fallback — Settings → Campaign limits → Default quiet hours, or GET/PUT /api/v1/campaigns/quiet-hours/settings. Every campaign row without its own window inherits this. Set it once per group posture and leave the rows silent.
  3. Platform default — 21:00 → 09:00 recipient-local when the fallback is disabled. This is the floor; the fallback and any row override can only narrow it.
So a group posture is: set the org fallback to the group’s window, leave the campaign rows without quiet_hours_start, and override on the one or two rows that need to differ. The GET on the fallback echoes platform_default_start / platform_default_end so you can confirm which regime a silent row will actually resolve to. For where the row window is configured and what its three fields mean, see Per-campaign quiet hours.

My source-of-truth timezone differs from the area-code resolution

Number portability means a 305 (Miami) number can belong to someone in Oregon — the area code reflects where the number was assigned, not where the subscriber lives. The resolver precedence is explicit hint → NANP area-code inventory → country-prefix fallback → fail posture, and the hint always wins. When your CRM knows the recipient’s real local timezone, pass it as timezone_override on the preview call and store it on the contact record so the send path consumes it. The full resolver chain, the area-code inventory, the split-NPA edge cases (Canadian NPAs that resolve a timezone but no US state, the Kansas/Missouri corridor that resolves a timezone but no state yet), and the fail posture per surface are on Number timezone and state resolution. The preview’s local_timezone field shows you exactly which branch resolved, so a mismatch between the CRM timezone and the area-code zone is visible before you send — re-preview with the timezone_override to confirm the corrected resolution.

Restarting tomorrow’s window after quiet-hours close

next_allowed_at is the DST-safe ISO instant the gate reopens, computed recipient-local through the full resolution chain. It handles three compositions that surprise operators:
  • DST — a 23- or 25-hour night in the recipient’s zone does not drift the schedule; the ISO instant is derived through ICU/Intl rules, so never re-derive hours in your own scheduler arithmetic. The crossover-night verification runbook is Quiet hours across DST.
  • Weekends and day masks — when the window’s allowed_days excludes the current weekday, next_allowed_at jumps to the next allowed day at window open, not to the next calendar hour. A Sunday-blocked window reopens Monday at window_start_local.
  • The federal guard on US voice — the 8 AM–9 PM recipient-local federal window composes on top of the campaign path for US voice and has no tenant toggle. next_allowed_at on a federal block is the next instant the federal window opens, intersected with any state mini-TCPA overlay; the tenant-owned toggles on this page do not move it. The overlay table is on US calling windows; the tenant-owned control map is on TCPA quiet hours and windows.
When next_allowed_at reads “now” but allowed_now is false, the hold is a timezone-resolution failure (unknown_timezone_deny), not a window close — scheduling cannot fix it; pass a timezone_override or fix the contact record and re-preview.

The federal guard and the tenant-owned layers, side by side

The US federal voice dialing window is the one rail the platform owns: 8 AM–9 PM recipient-local, no tenant toggle, no consent carve-out, fail-closed when the recipient timezone cannot resolve. Every other quiet-hours control on this page is yours — the org channel gate, the campaign fallback, the campaign row override, the platform default, the unknown_timezone_policy. The federal guard composes most-restrictive-wins on top of whichever layers carry a US voice send: a campaign voice call must clear the federal window, the campaign-path window, the org voice gate (if enabled), and every applicable state overlay. Tightening the tenant-owned layers never relaxes the federal rail; the two stacks are independent.

State overlays on top of the layered composition

State mini-TCPA overlays (Florida’s Sunday ban, Oklahoma/Mississippi windows, and the rest) compose on top of the layered posture as most-restrictive-wins, exactly as they compose on top of the federal window. A US voice send that clears the campaign window and the org gate can still trip a state overlay; a non-voice send does not. Voice blocks report outside_state_window or state_blocked_day so a state hold is separable from a federal one and from a campaign-path one. Read the resolved local_timezone and state on the preview response to see which overlay applied; the per-state table and the gate order are on US calling windows.

My org gate is enabled but a send still went through — why?

Two reasons pass a non-voice send through an enabled channel gate while your window is closed. A held send reports a closed window, but these two admit the send — and the gate records which one applied, so an allowed send at 03:00 is diagnosable rather than mysterious:
  • consent_override — the recipient carries an explicit-consent record, and your org keeps consent_overrides_quiet_hours at its default true. The TCPA “prior express consent” carve-out, honoured on every non-voice channel.
  • transactional_lane_exempt — the send was resolved to the transactional traffic lane. OTPs, alerts, and account notifications flow 24/7 on enabled channels, because quiet hours restrict telemarketing traffic, not essential traffic.
Voice never takes either carve-out. The federal dialing window governs US voice with no tenant toggle and no consent exception — see The federal TCPA dialing window, explained. Worked example. An OTP dispatched at 03:00 recipient-local on an sms-enabled org: the gate is on and the hour is inside your window, yet the send clears it with transactional_lane_exempt, and a marketing send to a consented recipient at the same instant clears it with consent_override. A campaign send to either recipient still faces the campaign-path window as a second layer — these reasons exempt the org gate only. Reading the reason. The preview response and the audit entry on a send carry the gate’s reason exactly as the preview page tables it: consent_override reads as “the recipient’s consent record passed the gate,” transactional_lane_exempt as “non-voice transactional traffic flows 24/7.” Fetch GET /api/v1/compliance/quiet-hours/preview?phone=<E.164>&channel=<channel> to reproduce the verdict before sending; the held or allowed send’s record carries the same field after the fact. Closing the consent carve-out. One switch removes it: consent_overrides_quiet_hours: false on PATCH /api/v1/settings/compliance/quiet-hours. With it off, explicit consent no longer passes the gate — only the transactional lane still does; there is no per-send toggle for that lane. The mechanics, defaults, and the config table for both carve-outs live in Two carve-outs that keep essential traffic flowing.

FAQ

I enabled the org gate on sms — do my drip campaigns inherit it? They clear it as a separate layer, plus the campaign-path window. The fallback (Settings → Campaign limits → Default quiet hours) still applies to any campaign without its own window; the org gate adds the ad-hoc-style hold on the same channel. Tighten at either layer; the two compose most-restrictive-wins. Can the fallback window relax the org gate? No. Fallbacks narrow the envelope, never widen it. The same asymmetry applies to the consent carve-out: consent_overrides_quiet_hours relaxes non-voice channels only, and voice ignores the flag entirely. Why did a blocked send say the window was the platform default when I set a fallback? PATH resolution order is campaign row → fallback → platform default. A campaign with its own empty quiet_hours_start uses the fallback; if your GET on the fallback reads enabled: false, the platform default 21:00 → 09:00 applies. Verify with GET /api/v1/campaigns/quiet-hours/settings — it echoes platform_default_start / platform_default_end so you see which regime would actually apply. Does the preview endpoint hold anything? No — it is read-only, the same rule as the compliance-health scores. It reports what the gate would do at this instant; run it freely in pre-flight. Is US campaign voice affected by any of these toggles? No. Campaign and dialer voice to US recipients is hard-blocked outside the federal 8 AM–9 PM recipient-local window with no tenant toggle, no org gate required, and no consent carve-out. This is the one rail the platform owns; everything else on this page is yours to configure. A customer closed a chat at 23:00 and the survey arrived at 08:0x — is that a bug? No. The auto-CSAT/auto-NPS dispatcher held the event-triggered survey: outside 08:00–21:00 recipient-local it keeps the survey pending on an SMS-class channel (sms, whatsapp, rcs, viber) instead of waking the customer. The 60s sweep re-evaluates the hold each minute and dispatches as soon as the window opens, usually 08:00 recipient-local; the survey is never dropped, and the nightly hold is bounded at ~13 hours. This is the platform applying your TCPA posture to event-triggered sends, not a legal mandate. Email never takes the survey hold.
Tenant-owned controls, not legal advice. Which laws apply to your traffic depends on your jurisdiction, your recipients, and what you send — confirm with qualified counsel before you rely on the wording here.

See also