Skip to main content
Outbound calling is regulated. These controls let you record the legal basis for every call, keep calls inside permitted hours on the callee’s clock, refuse numbers that must never be dialled, watch your abandon rate, and export an audit trail. Most of them are configured on the agent with contactPolicy through the Agents API, and enforced when a call is triggered. None of them is on by default: an agent with no contactPolicy requires nothing and refuses nothing.
Unknown keys are rejected with 400, so a misspelt control is an error rather than a setting that silently does nothing. Send contactPolicy: null to clear the whole policy.
This is a different object from a retry policy’s contact_policy, which holds per-number attempt caps. Caps answer how often may we redial this number; this answers under what basis may we dial at all.
With require_consent_basis: true, every call triggered for the agent must state the legal basis it is placed under, or it is refused with 400 consent_required: consent_reference is a free-text identifier (up to 200 characters) for where the consent is recorded: a CRM id, a form submission id. It is stored, never validated, and lands in the audit export.

Calling hours

calling_windows keeps calls inside a daily window evaluated on the callee’s clock. start_local is inclusive and end_local exclusive, both HH:MM 24-hour, and a window cannot wrap midnight. timezone_source chooses the clock:
  • callee_npanxx — inferred from the destination’s area code. Area-code granularity: an area code that spans two zones resolves to the dominant one.
  • agent_timezone — the agent’s own timezone.
  • explicit — the timezone field, which is then required.
A callee_timezone on the trigger request overrides all three for that call, for ported numbers or people who have moved. A call triggered outside the window is refused with 409 out_of_window, unless the call’s retry policy has Reschedule out-of-window calls on, in which case it is accepted with 202, status scheduled, and a next_attempt_at at the start of the next window.

Suppression list

The Outbound Suppression List is an organization-level do-not-call list. Every outbound call is checked against it before it is placed, and a listed number is refused with 409 suppressed. Entries are matched exactly against the dialled E.164 number.
  • Dashboard: Account Settings → Suppression List (shown once the organization has an outbound agent). Pick the organization, add a number with a reason (opt_out, manual, complaint, litigation, other) and optional notes, or remove one. Who added or removed each entry is recorded.
  • Connect App: the Outbound Suppression List button on the agents page, with the same controls.
  • API: list and add and remove entries. Adding a number already on the list succeeds rather than erroring.
The list is per organization: a number suppressed in one organization can still be dialled by a sibling organization under the same account. An opt-out detected on a call cancels that number’s pending retries but does not add it here.

Abandon rate

GET /v1/metrics reports an FCC-style abandon rate over rolling 24-hour, 7-day and 30-day windows, for the organization and per agent, with a breached flag when a window is above the threshold. The default threshold is 3%; contactPolicy.abandon_rate_alert_threshold sets a different one per agent (an explicit 0 flags any abandoned call). The denominator counts only calls that Answering Machine Detection classified as answered by a person. A window with no such calls reports null, not 0, so an agent without AMD is never mistaken for a compliant one.

Audit export

GET /v1/outbound-calls/export returns every dialled number in a date range — including attempts that were never answered — with its consent basis and reference, attempt number, answer type, whether a voicemail was left, opt-out, callee timezone and cancel reason, as CSV or JSON. Filter by agent, status, or campaign. To group calls by campaign, put a campaign_id (1–200 characters) in the metadata you send when triggering each call. It is the one reserved metadata key: it is trimmed and indexed so the export’s campaign_id filter matches it exactly.