Per-campaign quiet hours: override the window on a campaign row
The org fallback on Settings → Campaign limits sets one quiet-hours posture for a group of campaigns. When one campaign needs a different window, a tighter one for a sensitive list or a shifted one for a regionally concentrated audience, set the window on the campaign row itself with three fields:quiet_hours_enabled, quiet_hours_start,
and quiet_hours_end, accepted on campaign create and update.
The row window is a negative filter: do not send during these
recipient-local hours. This guide covers what the three fields mean,
where to set them in the dashboard and over the API, how they resolve
against the org fallback and the platform default, how they combine
with a send window, which sends read them, and how to verify what each
recipient will actually receive.
The control
Semantics to plan around:
- Default off. While the fields are absent the campaign carries no row-level window, so nothing defers at row level; the send resolves against the org fallback and the platform default like any other campaign. Absent means “no row-level deferral”, not “no quiet hours anywhere”.
enabled: falseversus absent. Passingquiet_hours_enabled: falsepersists an explicit decision on the campaign: a later update that omits the quiet-hours fields leaves the stored value untouched, so the explicit off survives partial updates. At send timefalseand absent behave the same way (no row window, resolution continues to the fallback), and neither suppresses the always-on platform default.- Whole hours only. Hours are integers 0–23; the API rejects non-integer or out-of-range values at the boundary.
- Cross-midnight windows.
quiet_hours_startgreater thanquiet_hours_endwraps overnight:21→7is quiet from 21:00 through 06:59 recipient-local and reopens at 07:00. - End-exclusive. The window includes the start hour and stops
before the end hour: with
21→9, a send at 08:xx local defers and a send at 09:xx goes. startequal toendreads as quiet at every hour and defers every send. Treat it as a misconfiguration.
Where to configure it
Dashboard
Two surfaces show the row window where you plan a launch:- Cross-schedule planner (Campaigns → Spread sends). The planner’s quiet-hours toggle and start/end inputs take a window alongside the shared hourly cap, and a chip on the input row names the time zone those hours are entered in. The planner is advisory: it shapes the recommended schedule, and the note under the inputs says it plainly: at send time, each recipient’s own local quiet hours still apply.
- Launch preview. The campaign’s launch preview shows a
Quiet-hours deferred tile: an estimate of how many sampled
recipients would defer inside the window that resolves for this
campaign, with the sample size underneath (
quiet_hours.skipped_estimatein the preview payload). When no window applies, the tile says so.
API
The same three fields are accepted on create and on update. Arm a 21:00 → 09:00 window on an existing campaign:GET /api/v1/campaigns/$CAMPAIGN_ID to
confirm the stored window before launch, and switch the row filter off
with "quiet_hours_enabled": false.
Resolution order
When a campaign send is evaluated, exactly one window applies, resolved in this order:- Campaign row —
quiet_hours_start/quiet_hours_endon the row, when the row filter is enabled, wins for that campaign only. - Org fallback — Settings → Campaign limits → Default quiet
hours, or
GET/PUT /api/v1/campaigns/quiet-hours/settings. Every row without its own window inherits this. - Platform default — 21:00 → 09:00 recipient-local. This is the floor; the fallback and any row override can only narrow it.
GET on the
fallback echoes platform_default_start / platform_default_end, so
you can always see which regime a silent row will resolve to.
Quiet hours versus send_window
A campaign can also carry a send window
(send_window.start_local_hour / send_window.end_local_hour), the
positive twin of this control: only send during these recipient-local
hours. Quiet hours say when not to send; a send window says when to
send.
When both are set, a send must satisfy both, so the tighter bound wins
in practice. Worked example:
send_window 9 → 17 with a row quiet
window 12 → 14.
Pick by what you know: use a send window when you know the good hours
(local business hours for a B2B list), quiet hours when you know the
bad ones (evenings and early mornings for a consumer list). For
send-window tuning, see
Send-window optimization.
Which sends read the row window
- Campaign and journey sends. Sends that originate from a campaign or a journey resolve to the marketing lane, so the row window applies to them: blasts, drips, and journey steps alike.
- Direct API transactional sends. A message sent directly over the API without a campaign never reads a campaign row; the row window cannot defer it. Transactional sends stay governed by the org channel gate and the compliance rails, not by campaign posture.
- Voice. The row window narrows marketing send timing only. It never relaxes the always-on federal dialing-window guard for US campaign and dialer voice; that guard is platform-owned and no tenant setting touches it.
Verify and debug
Read the window the way the send path will, before launch:- Launch preview. The Quiet-hours deferred tile estimates the deferred share of the sampled audience for the window that resolves on this campaign. A surprising number here is almost always a wrong window on the row or a fallback you forgot about.
- Preview endpoint.
GET /api/v1/compliance/quiet-hours/preview?phone=…&channel=…returns the decision for one recipient without sending: whether the send would hold, the window that applied, andnext_allowed_at, the recipient-local instant the gate reopens. Pass&timezone_override=<iana-name>when your CRM knows the recipient’s zone better than the area code does. - The held record. A deferred send carries a
quiet_hoursblock with the reason, the window edges in recipient-local time, andnext_allowed_at; the preview returns the same fields, so you can match any deferral back to the layer that applied.
next_allowed_at to re-queue
against. When a block looks wrong, the recipient should have been in
allowed hours, work the layer table in
Troubleshooting quiet-hours false positives;
for the decision model behind the three layers see
Quiet hours FAQ.
Group posture playbook
Setting the row window on every campaign does not scale, and most orgs do not need to. The resolution order is designed for one posture per group:- Set the org fallback once to the group’s window on Settings → Campaign limits → Default quiet hours.
- Leave the rows silent so they inherit it.
- Override only the one or two outlier rows that genuinely differ: the sensitive list that needs 20:00 → 08:00, the regional blast that can run later.
allowed_days), not on the campaign, and
minutes-level precision does not exist at any quiet-hours layer.
See also
- Campaign limits: audience cap and default quiet hours: the org fallback this row window overrides.
- Quiet hours configuration: every surface that reads your quiet-hours posture.
- Quiet hours FAQ: the resolution order and the one-posture-per-group model.
- Troubleshooting quiet-hours false positives: when a block looks wrong.
- Send-window optimization: the positive twin of this control.