> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telzino.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Outbound Compliance

> Consent tracking, calling hours, a do-not-call list, abandon-rate monitoring and an audit export for outbound calling

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](/api-reference/agents/create), and enforced when a call is [triggered](/api-reference/outbound-calls/create). None of them is on by default: an agent with no `contactPolicy` requires nothing and refuses nothing.

```json theme={null}
{
  "contactPolicy": {
    "require_consent_basis": true,
    "calling_windows": {
      "start_local": "08:00",
      "end_local": "21:00",
      "timezone_source": "callee_npanxx"
    },
    "abandon_rate_alert_threshold": 0.03
  }
}
```

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.

<Note>
  This is a different object from a [retry policy](/functions/retry-policies)'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*.
</Note>

## Consent basis

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_basis` | Use for |
| - | - |
| `express_written` | The callee gave express written consent |
| `ebr` | An established business relationship |
| `informational_exempt` | Purely informational calls that are exempt from consent rules, such as appointment reminders |
| `other` | Anything else — pair it with a `consent_reference` |

`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](/functions/retry-policies) 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](/api-reference/suppression-list/list-add) and [remove](/api-reference/suppression-list/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](/functions/retry-policies#stopping-retries) cancels that number's pending retries but does not add it here.

## Abandon rate

[`GET /v1/metrics`](/api-reference/metrics#abandonrate) 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](/functions/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`](/api-reference/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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.