> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.ada.cx/docs/automation/proactive-outreach/voice/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server. # Voice Proactive Outreach ## Overview Voice Proactive Outreach lets your AI Agent call an end user by phone. Your systems start the call. When a person answers, the Agent runs the [Playbook](/docs/automation/playbooks) that you link. If you link no Playbook, the call starts with your [Greeting](/docs/automation/greetings). You can start a call in two ways: * **From your system, with the Conversations API.** Your system sends a request to Ada. Ada places the call over your own outbound SIP trunk, so your carrier dials the end user. * **From your contact center dialer, with a SIP INVITE.** Your dialer places the call. When a person is on the line, the dialer sends the call to Ada. Ada turns on Voice Proactive Outreach for each AI Agent after your organization signs a contract addendum. To get access, contact your Ada team. ## Limitations Voice Proactive Outreach has the following constraints: * **No voicemail.** If your AI Agent detects an answering machine, it will end the call and will not leave a voicemail. * **No retries.** Ada does not call again after a call fails or is not answered. * **One call for each trigger.** Each request or SIP INVITE starts one call. You cannot schedule calls or upload a list of phone numbers. * **The Conversations API option needs your own outbound SIP trunk.** Ada does not place these calls from an Ada phone number. Ada sets up the trunk with you. The dashboard has no setup screen for it. * **The dialer option works over SIP only.** Custom SIP headers cannot cross a phone network (PSTN) connection. A call that your dialer sends to an Ada phone number never carries them. * **Call status webhooks cover the Conversations API option only.** Ada only sends `v1.proactive_call` webhooks for calls triggered using the Conversations API. It does not provide these webhook events for calls triggered using your dialer. * **Handoffs on Conversations API calls go out over your trunk.** A Handoff to a phone number or a SIP address uses your trunk and its caller ID. A Dialpad Handoff does not work on these calls. UUI headers and phone extensions are not passed on. * **A conversation exists only after a person answers.** A call that fails, is not answered, or reaches an answering machine does not show in the Conversations view. ## Use cases The following scenarios show common applications for Voice Proactive Outreach: * Call an end user about an open support case. Pass the case ID, so the Playbook can look up the status of the case. * Call an end user about an order or a delivery. Pass the order ID and the delivery date, so the Agent can confirm the details. * Let your contact center dialer place outbound calls, and send each answered call to the AI Agent. ## Capabilities & configuration Each Voice Proactive Outreach holds the settings for one type of call. Your system or your dialer names it by its Proactive ID when it starts a call. ### Settings The settings of a Voice Proactive Outreach control how each call starts. | Setting | Description | | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Channel** | Select **Voice**. You cannot change the channel after you save. | | **Name** | The name of the item. Use up to 80 characters, with at least one letter or number. Each Proactive Outreach item needs a different name. | | **Default language** | The language of the call when the trigger does not specify one. The list shows your AI Agent's default language and the translated languages that Voice supports. | | **Playbook** | The Playbook that runs when a person answers. Only active Playbooks are listed. Select **None (Greeting)** to start the call with your Greeting. If the linked Playbook becomes inactive, calls start with your Greeting. | | **Proactive ID** | A read-only ID that Ada assigns when you save. Your system or your dialer sends it to start a call. | | **Compliance attestation** | A check box that you must select before the item can be active. | | **Active** toggle | Calls are placed only while the Voice Proactive Outreach is active. | ### Compliance responsibilities Your organization owns the legal side of every call. Your organization is responsible for making sure that every call complies with applicable laws and with your agreement with Ada. That includes: * Obtaining consent * Calling only during permitted hours * Honoring do-not-call (DNC) and suppression lists * Disclosing call recording * Disclosing that the caller is an AI * Honoring opt-out requests Ada does not provide a do-not-call list, suppression lists, calling-hours enforcement or opt-out processing. Check these in your own systems before you start each call. Ada is not responsible for deciding whether a specific call may be placed. Select the **Compliance attestation** check box before you enable the **Active** toggle. If you clear the check box, the Voice Proactive Outreach becomes inactive. The Conversations API also refuses a call for an item without the attestation. ### Trigger options The two trigger options differ in who dials the end user and in what Ada reports back. | | Conversations API | Contact center dialer | | :------------------------------ | :------------------------------------------- | :---------------------------------- | | **Who dials** | Your outbound SIP trunk, when Ada asks it to | Your dialer | | **Caller ID** | The caller ID that your trunk presents | The caller ID of your dialer | | **Answering machine detection** | Ada | Your dialer | | **How you pass context** | `metadata` in the request | `X-Ada-Metadata-` SIP headers | | **Call status webhooks** | Yes | No | | **What Ada sets up with you** | Your outbound SIP trunk | Your SIP connection to Ada | ## Quick start Create a Voice Proactive Outreach, then start a call with the Conversations API. Before you start, Ada must turn on Voice Proactive Outreach for your AI Agent and set up your outbound SIP trunk. For more detail, see [Implementation & usage](#implementation--usage). **To create a Voice Proactive Outreach and start a call:** Go to **Config > AI AGENT > Outreach**. Click **New Proactive Outreach**. If you have no Proactive Outreach items yet, click **Create a Voice Proactive Outreach**. In the **Channel** section, select **Voice**. Enter a **Name**. Optionally, select a **Default language** and a **Playbook**. In the **Compliance attestation** section, select the check box. Enable the **Active** toggle, then click **Save**. The Voice Proactive Outreach opens, and the **Proactive ID** field shows its ID. Send a `POST /v2/conversations/proactive/` request with the Proactive ID and the phone number of the end user. See [Start a call from your system](#start-a-call-from-your-system). ## Implementation & usage Set up the trigger option that you use, pass context to the Playbook, and track each call. ### Set up your outbound SIP trunk A call that you start with the Conversations API goes out over your own outbound SIP trunk. Your carrier dials the end user. Ada configures the trunk with you and places a test call before your calls start. Prepare the following on your trunk: * **A termination endpoint.** The trunk accepts INVITEs from Ada for `sip:+@`. A trunk that accepts inbound calls does not prove that outbound calls work, because trunks are directional. * **A way for the trunk to trust Ada.** Choose one: * **Digest credentials:** a username and a password for Ada. Use a password of 12 to 128 letters and digits. * **IP allowlist:** allow the Twilio SIP signaling ranges on UDP and TCP port 5060 and TLS port 5061: `54.172.60.0/30` (Virginia) and `54.244.51.0/30` (Oregon) in North America, `54.171.127.192/30` (Ireland) and `35.156.191.128/30` (Frankfurt) in Europe. Also allow the media range `168.86.128.0/18` on UDP ports 10000 to 60000. * **Outbound service** to the countries that you call. * **A caller ID that your trunk may present.** Ada presents it on each call. Your carrier decides what the end user sees. * **No route back to Ada.** Your trunk must not send calls for the recipient numbers back to your Ada SIP domain. * **A test phone number** that Ada can call. The trunk has these requirements: * The termination host is a public host name or IP address. A private IP address is not supported. * The trunk is not hosted by Twilio. Ada cannot place calls through a Twilio SIP domain (`*.sip.twilio.com`). * The transport is UDP, TCP or TLS. Secure media needs TLS. If your AI Agent sends text messages during calls over your trunk, Ada sets an SMS-capable Ada number as its SMS phone number during onboarding. To send these texts from your own number, use your own SMS channel. See [Send texts from your own SMS channel](/docs/channels/voice/voice-onboarding#send-texts-from-your-own-sms-channel). If no trunk is set up for your AI Agent, or the trunk is turned off, the request still returns `202`. The call then fails with the `client_configuration` reason. ### Start a call from your system Your system sends one request for each call. Authenticate with an [Ada API key](/reference/introduction/authentication). Replace `example.ada.support` with the domain of your AI Agent. ```http POST https://example.ada.support/api/v2/conversations/proactive/ Authorization: Bearer Idempotency-Key: Content-Type: application/json { "proactive_id": "", "channel": "voice", "recipient": { "phone_number": "+14155550123" }, "language": "en", "metadata": { "order_id": "ORD-1042", "delivery_date": "2026-10-14" } } ``` The request body has these fields: | Field | Required | Description | | :----------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `proactive_id` | Yes | The Proactive ID of an active Voice Proactive Outreach. | | `channel` | Yes | Must be `voice`. | | `recipient.phone_number` | Yes | The phone number of the end user in E.164 format, for example `+14155550123`. | | `language` | No | A language code that your AI Agent supports on Voice. If you omit it, the call uses the **Default language** of the Voice Proactive Outreach. If that is not set, the call uses the default language of your AI Agent. | | `metadata` | No | Key-value pairs that become metavariables when a person answers. See [Pass context to the Playbook](#pass-context-to-the-playbook). | Send an `Idempotency-Key` header of 1 to 255 characters to retry safely. If you send the same key again within 90 days, Ada returns the first attempt with the `Idempotent-Replayed: true` header and does not call again. A successful request returns `202 Accepted` with the queued Proactive Attempt. The attempt has an `id`, a `state` of `queued`, and the values from your request. The response does not report the outcome of the call. To follow the call, use [webhooks](#track-calls-with-webhooks). The end user's phone rings for about 60 seconds. If nobody answers, the call fails with the `no_answer` reason. The endpoint returns these errors: | Status | Cause | | :----- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `400` | An unknown field, a phone number that is not valid E.164, a `language` that your AI Agent does not support on Voice, or `metadata` that breaks the rules. | | `404` | No Voice Proactive Outreach with this `proactive_id` exists for your AI Agent, or Voice Proactive Outreach is not turned on for it. | | `409` | Another request with the same `Idempotency-Key` is in progress. Retry the request. | | `422` | The Voice Proactive Outreach is not active, has no compliance attestation, is not on the `voice` channel, or would use a language that your AI Agent no longer supports on Voice. | | `429` | The request exceeds a rate limit. See [Rate limits](/reference/conversations/overview#rate-limits). | ### Answering machine detection Ada detects who answers each call that you start with the Conversations API: * If a person answers, the conversation starts and the Playbook runs. * If a voicemail system, an answering machine or a fax answers, Ada ends the call. No conversation is created, and Ada sends the `v1.proactive_call.machine_detected` webhook. * If detection cannot decide, the call continues as if a person answered. ### Start a call from your contact center dialer Your dialer places the call and runs its own answering machine detection. When a person is on the line, the dialer sends a SIP INVITE to your Ada SIP domain. The AI Agent then runs the Playbook. Before you start, connect your SIP infrastructure to Ada. See [Contact center integration](/docs/channels/voice/contact-center-integration). Add these headers to the SIP INVITE: | Header | Required | Description | | :---------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `X-Ada-Proactive-Id` | Yes | The Proactive ID of an active Voice Proactive Outreach. | | `X-Ada-Language` | No | The language of the call. If you omit it, or it matches no Voice language of your AI Agent, the call uses the **Default language** of the Voice Proactive Outreach. | | `X-Ada-Metadata-` | No | One header for each value that you pass. Each header becomes a metavariable named ``. | ``` INVITE sip: SIP/2.0 X-Ada-Proactive-Id: X-Ada-Language: en X-Ada-Metadata-order_id: ORD-1042 ``` Send the phone number of the end user in the SIP UUI header, as for every SIP call to Ada. If the UUI header has no phone number, Ada reads the number from the From header. If neither has a valid number, Ada rejects the call. Use SIP from end to end. Custom headers cannot cross a phone network (PSTN) connection. If your dialer sends the call to an Ada phone number, the headers are lost and the call starts as an ordinary inbound call. Ada answers the INVITE in one of these ways: * If the call can start, Ada connects it and the AI Agent starts the conversation. * If the Voice Proactive Outreach cannot start the call, Ada rejects the INVITE with SIP `404`. For example, the item is inactive, has no compliance attestation, or the ID is not valid. Do not retry. * If Ada cannot take the call now, Ada answers with SIP `486 Busy Here`. For example, your AI Agent is at its concurrent call limit. Your dialer can retry. ### Pass context to the Playbook Pass the details that the Agent needs for the call. When a person answers, each value becomes a [metavariable](/docs/automation/variables/using-variables#metavariables) that the Playbook can use. * **Conversations API:** each `metadata` key becomes a metavariable with the same name. * **Contact center dialer:** each `X-Ada-Metadata-` header becomes a metavariable named ``. On both paths, the Agent also sets the `proactive_id` metavariable to the Proactive ID. The values follow these rules: | Rule | `metadata` in the request | `X-Ada-Metadata-` headers | | :----------------- | :---------------------------------------------------------------------------------------------------------- | :---------------------------------------------- | | **Maximum count** | 20 keys | 20 headers | | **Names** | 1 to 64 letters, digits or underscores | 1 to 64 letters, digits, underscores or hyphens | | **Values** | Strings, numbers or booleans, up to 4 KB in total. Ada stores each value as text, so `true` becomes `True`. | Text | | **Reserved names** | A name that Ada sets itself, such as `language`, `phone_number` or `email`, returns `400`. | A name that Ada sets itself is dropped. | To use more data than you pass, send an identifier, for example an order ID. At the start of the Playbook, add a [`RUN` step](/docs/automation/playbooks/step-reference#run) that runs an [API tool](/docs/automation/tools/api-tools) with that identifier. ### Track calls with webhooks Ada sends a webhook each time a call from the Conversations API reaches a new state. Add an endpoint in **Config > PLATFORM > Webhooks**. The `v1.proactive_call` events show there only for AI Agents that have Voice Proactive Outreach. For endpoint setup, see [Webhooks](/reference/webhooks/overview). | Event | Sent when | | :----------------------------------- | :------------------------------------------------------------------------------ | | `v1.proactive_call.queued` | Ada accepts the request and queues the call. | | `v1.proactive_call.initiated` | Ada places the call with the carrier. | | `v1.proactive_call.answered` | A person answers and the conversation exists. | | `v1.proactive_call.machine_detected` | A voicemail system or an answering machine answers. No conversation is created. | | `v1.proactive_call.failed` | The call ends without a person answering. | Each event has a `type`, a `timestamp` and a `data` object with these fields: | Field | Description | | :----------------------- | :------------------------------------------------------------------------------ | | `proactive_attempt_id` | The `id` that the Conversations API returned for the request. | | `proactive_id` | The Proactive ID. | | `channel` | Always `voice`. | | `state` | `queued`, `initiated`, `answered`, `machine_detected` or `failed`. | | `recipient.phone_number` | The phone number of the end user. | | `language` | The language of the call. | | `metadata` | The `metadata` from the request. | | `conversation_id` | The ID of the conversation. It is `null` until a person answers. | | `failure_reason` | Why the call failed. It is `null` unless `state` is `failed`. | | `created_at` | When Ada accepted the request. | | `updated_at` | When the call reached `state`. | | `ai_agent_domain` | The domain of the AI Agent that sent the event, for example `acme.ada.support`. | The `failure_reason` field has one of these values: | Value | Meaning | | :--------------------- | :----------------------------------------------------------------------------------------------------------- | | `busy` | The line was busy. | | `no_answer` | Nobody answered. | | `rejected` | The call was declined or refused. | | `invalid_number` | The phone number cannot be called. | | `carrier_failure` | The carrier could not connect the call. | | `capacity_exceeded` | Your AI Agent reached its concurrent call limit. Retry with a new `Idempotency-Key`. | | `client_configuration` | Your AI Agent cannot place calls as configured. For example, no trunk is set up, or the trunk is turned off. | | `internal_error` | An error occurred at Ada. | Ada can add new values. Handle a value that you do not know as a failed call. Events can arrive out of order. A call can reach `answered`, `machine_detected` or `failed` without an `initiated` event. ## Best practices These recommendations help each call reach the end user once and start with the right context: * Send an `Idempotency-Key` with every request. If a request times out, retry with the same key, so the end user gets one call only. * After a `capacity_exceeded` failure, retry with a new `Idempotency-Key`. The old key returns the failed attempt. * Keep the linked Playbook active. If it becomes inactive, calls start with your Greeting. * Pass an identifier in `metadata`, then look up other details with an API tool at the start of the Playbook. * Track each call by its `state` and `updated_at`, not by the order in which events arrive. ## Related features These features work with Voice Proactive Outreach: * [Proactive Outreach](/docs/automation/proactive-outreach) * [Messaging Proactive Outreach](/docs/automation/proactive-outreach/messaging) * [Playbooks](/docs/automation/playbooks) * [Voice](/docs/channels/voice) * [Contact center integration](/docs/channels/voice/contact-center-integration) * [Conversations API](/reference/conversations/overview) * [Webhooks](/reference/webhooks/overview) --- Have any questions? Contact your Ada team, or email us at [](mailto:help@ada.cx?subject=Help%20Docs%20inquiry).