Skip to main content

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: false versus absent. Passing quiet_hours_enabled: false persists 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 time false and 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_start greater than quiet_hours_end wraps overnight: 21 → 7 is 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.
  • start equal to end reads 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_estimate in the preview payload). When no window applies, the tile says so.
The API below is where the three fields are written.

API

The same three fields are accepted on create and on update. Arm a 21:00 → 09:00 window on an existing campaign:
An EU-shaped overnight window, 22:00 → 07:00:
Read the campaign back with 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:
  1. Campaign row — quiet_hours_start / quiet_hours_end on the row, when the row filter is enabled, wins for that campaign only.
  2. 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.
  3. Platform default — 21:00 → 09:00 recipient-local. This is the floor; the fallback and any row override can only narrow it.
Whichever layer supplies the window, enforcement is recipient-local, hour-granular, and end-exclusive, as described above. The 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:
  1. 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.
  2. 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, and next_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.
  3. The held record. A deferred send carries a quiet_hours block with the reason, the window edges in recipient-local time, and next_allowed_at; the preview returns the same fields, so you can match any deferral back to the layer that applied.
How a deferral surfaces depends on the send type. A campaign or journey send is scheduled to the next open: the campaign stays live and resumes on its own when the window closes, per Campaign lifecycle. A one-shot message held by a gate reports blocked with 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:
  1. Set the org fallback once to the group’s window on Settings → Campaign limits → Default quiet hours.
  2. Leave the rows silent so they inherit it.
  3. 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.
State the limits of the row control honestly when you plan: hours only, in whole-hour steps, evaluated recipient-local. There is no day-of-week scoping on a campaign row; day-of-week control lives on the org channel gate (allowed_days), not on the campaign, and minutes-level precision does not exist at any quiet-hours layer.

See also