diff --git a/fern/calls/call-concurrency.mdx b/fern/calls/call-concurrency.mdx index 69c4bbb19..5054395fa 100644 --- a/fern/calls/call-concurrency.mdx +++ b/fern/calls/call-concurrency.mdx @@ -149,5 +149,5 @@ Adjust the `timeRange.step` to inspect usage by hour, day, or week. Peaks that a ## Next steps - **[Call queue management](mdc:docs/calls/call-queue-management):** Build a Twilio queue to buffer calls when you hit concurrency caps. -- **[Outbound campaign planning](mdc:docs/outbound-campaigns/overview):** Design outbound strategies that pair batching with analytics. +- **[Outbound campaign planning](/campaigns/overview):** Design outbound strategies that pair batching with analytics. - **[Enterprise plans](mdc:docs/enterprise/plans):** Review larger plans that include higher default concurrency. diff --git a/fern/calls/call-outbound.mdx b/fern/calls/call-outbound.mdx index da2b2154a..658e10b9a 100644 --- a/fern/calls/call-outbound.mdx +++ b/fern/calls/call-outbound.mdx @@ -80,7 +80,7 @@ Use both `customers` and `schedulePlan` together to schedule batched calls. ## Creating Outboud Calls from the Dashboard -Learn more about how to launch [Outbound Calling Campaigns via Dashboard](/outbound-campaigns/quickstart) +Learn more about how to launch [Campaigns via Dashboard](/campaigns/quickstart) ## Trusted Calling and Caller ID diff --git a/fern/campaigns/advanced.mdx b/fern/campaigns/advanced.mdx new file mode 100644 index 000000000..2703ed5f2 --- /dev/null +++ b/fern/campaigns/advanced.mdx @@ -0,0 +1,217 @@ +--- +title: Campaigns advanced +subtitle: Personalization, scheduling, the pre-dial webhook, and managing campaigns via the API +slug: campaigns/advanced +description: Personalize each campaign call with variables and overrides, schedule dialing windows, gate contacts with the pre-dial webhook, and manage campaigns via the REST API. +--- + +## Personalize each call + +Every contact can get a tailored conversation. Overrides exist at two levels and are deep-merged at dial time: + +- **Campaign-level** overrides apply to every call in the campaign +- **Per-contact** overrides are merged on top for that contact's call + +Both `assistantOverrides` and `squadOverrides` are supported — at the campaign level and per contact. `assistantOverrides` applies when the call is handled by an assistant; `squadOverrides` when it's handled by a squad. + +The most common use is `variableValues`, which feed [dynamic variables](/assistants/dynamic-variables) in your assistant's prompts: + +```bash +curl https://api.vapi.ai/v2/campaign \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Post-Service Feedback", + "assistantId": "your-assistant-id", + "phoneNumberId": "your-phone-number-id", + "maxConcurrency": 10, + "assistantOverrides": { + "variableValues": { "company": "TechFlow" } + }, + "customers": [ + { + "number": "+14155551234", + "name": "John", + "assistantOverrides": { + "variableValues": { "customer_issue": "password reset" } + } + }, + { + "number": "+14155555678", + "name": "Mary", + "assistantOverrides": { + "variableValues": { "customer_issue": "address update" } + } + } + ] + }' +``` + +Your assistant can then reference `{{company}}` and `{{customer_issue}}` in its prompts. + +In the dashboard, extra CSV columns become per-contact `variableValues` automatically — a `customer_issue` column fills `{{customer_issue}}` for each row. + +## Schedule a campaign + +By default, dialing starts immediately on creation. Use `schedulePlan` to control the window: + +- `earliestAt` — dialing starts at this time instead of immediately +- `latestAt` — optional deadline; no further calls are attempted after it + +```bash +curl https://api.vapi.ai/v2/campaign \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Weekend Promo", + "assistantId": "your-assistant-id", + "phoneNumberId": "your-phone-number-id", + "maxConcurrency": 10, + "customers": [ { "number": "+14155551234" } ], + "schedulePlan": { + "earliestAt": "2026-07-04T16:00:00Z", + "latestAt": "2026-07-05T01:00:00Z" + } + }' +``` + +In the dashboard, this is the **Schedule for later** option when launching. + + +Times are absolute UTC instants (ISO 8601). "9am in each contact's local timezone" isn't expressible yet — if you need per-timezone windows, split contacts into one campaign per region with region-appropriate windows. + + +## Pre-dial webhook + +Set a `server` on the campaign to receive a `campaign.predial` webhook **before each contact is dialed**. Your server decides, contact by contact, whether the call should happen — useful for do-not-call registries, opt-out lists, or last-minute eligibility checks that can't be known at campaign creation time. + +```bash +curl https://api.vapi.ai/v2/campaign \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Renewals with DNC check", + "assistantId": "your-assistant-id", + "phoneNumberId": "your-phone-number-id", + "maxConcurrency": 10, + "customers": [ { "number": "+14155551234" } ], + "server": { "url": "https://example.com/vapi/campaign-webhook" } + }' +``` + +Before each dial, your server receives: + +```json +{ + "message": { + "type": "campaign.predial", + "campaignId": "4a5b6c7d-...", + "contact": { + "id": "contact-id", + "campaignId": "4a5b6c7d-...", + "number": "+14155551234", + "name": "John" + } + } +} +``` + +Respond with whether the contact may be dialed: + +```json +{ "eligible": true } +``` + + +The pre-dial check **fails closed**: if your server responds `"eligible": false`, is unreachable, errors, or times out, the contact is **skipped** and not called. Make sure the endpoint is fast and highly available — an outage on your side pauses dialing decisions against you, not in your favor. + + +In the dashboard, this is the **Pre-dial webhook** field when creating a campaign. + +## Tune concurrency + +`maxConcurrency` is required at creation, must be within your org's [concurrency limit](/calls/call-concurrency), and caps how many campaign calls run at once. Both the campaign cap and the org-wide limit apply to every campaign call — see the [overview](/campaigns/overview#concurrency-two-limits-apply). + +Practical guidance: + +- **Leave headroom.** If your org limit is 10 and inbound or one-off outbound calls happen alongside the campaign, a `maxConcurrency` of 10 will starve them — and campaign dispatches at capacity can fail. +- **Telephony limits are separate.** Your provider (e.g. Twilio) has its own rate limits on outbound call initiation. +- **More isn't always faster.** Answer rates, voicemail, and call duration dominate campaign wall-clock time more than raw concurrency. + +## Manage campaigns via the API + +Everything the dashboard does, the API does too — the endpoints live under `/v2/campaign` and use your private API key. Full request/response schemas are in the [API reference](/api-reference/campaigns/campaign-controller-create-v2). + +### Create + +`POST /v2/campaign` creates and starts a campaign in one request. Required: `name`, an `assistantId` or `squadId` (exactly one), `phoneNumberId`, `customers` (at least one), and `maxConcurrency`. + +```bash +curl https://api.vapi.ai/v2/campaign \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Q3 Renewal Reminders", + "assistantId": "your-assistant-id", + "phoneNumberId": "your-phone-number-id", + "maxConcurrency": 5, + "customers": [ + { "number": "+14155551234", "name": "John" }, + { "number": "+14155555678", "name": "Mary" } + ] + }' +``` + +### Monitor + +Poll `GET /v2/campaign/{id}`. The response includes the contact list, current `status`, and — as each call ends — an entry in the `calls` map with the customer, timestamps, `endedReason`, and [`analysis`](/assistants/call-analysis): + +```json +{ + "status": "in-progress", + "calls": { + "call-id-1": { + "id": "call-id-1", + "customer": { "number": "+14155551234", "name": "John" }, + "status": "ended", + "endedReason": "customer-ended-call", + "startedAt": "2026-07-02T18:01:12.000Z", + "endedAt": "2026-07-02T18:03:45.000Z", + "analysis": { "summary": "..." } + } + } +} +``` + +For full call artifacts (recording, transcript), fetch the individual call with [`GET /call/{id}`](/api-reference/calls/get). To list campaigns, use `GET /v2/campaign` (paginated, filterable by `status`). + +### Cancel + +Campaigns are immutable after creation — cancellation is the only supported update: + +```bash +curl -X PATCH https://api.vapi.ai/v2/campaign/CAMPAIGN_ID \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ "status": "cancelled" }' +``` + +New calls stop being dispatched; calls already in progress finish naturally. + +### Delete + +`DELETE /v2/campaign/{id}` archives the campaign — cancelling it first if it's still running. Archived campaigns no longer appear in list or get responses. + +## Re-running a campaign + +Since campaigns are immutable, iteration works by duplication: pass `duplicateFromCampaignId` on create to inherit the source campaign's configuration and contacts. Any fields you provide override the source; if you provide `customers`, they replace the source's contact list. + +```bash +curl https://api.vapi.ai/v2/campaign \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Q3 Renewal Reminders (rerun)", + "duplicateFromCampaignId": "SOURCE_CAMPAIGN_ID" + }' +``` diff --git a/fern/campaigns/overview.mdx b/fern/campaigns/overview.mdx new file mode 100644 index 000000000..64aa4c16c --- /dev/null +++ b/fern/campaigns/overview.mdx @@ -0,0 +1,59 @@ +--- +title: Campaigns overview +subtitle: Scalable batch outbound calling with per-campaign concurrency control +slug: campaigns/overview +description: Learn how Vapi Campaigns work — upload contacts, set a concurrency limit, and let Vapi dial through your list from the dashboard or the API. +--- + +## Overview + +Campaigns are Vapi's batch outbound calling system. You provide a list of contacts, pick an assistant (or squad) and a phone number, set a concurrency limit, and Vapi dials through the list for you — as soon as one call finishes, the next contact is dialed, keeping up to your concurrency limit in flight until everyone has been called. + +You can create and manage campaigns from the **dashboard** or programmatically via the **API** — both drive the same system. + + +Campaigns are in limited availability. If you don't see **Campaigns** in your dashboard, or the API returns `403 Campaigns V2 is not enabled for your organization`, contact [Vapi support](/support) to have it enabled. + + +## Key capabilities + +- **Scale**: call thousands of contacts from a single campaign +- **Concurrency control**: cap how many calls run at once with `maxConcurrency` +- **Personalization**: per-contact variables and overrides for tailored conversations +- **Scheduling**: start now or within a time window +- **Pre-dial webhook**: approve or skip each contact right before it's dialed +- **Monitoring**: per-call outcomes, transcripts, and analysis as calls complete + +## How a campaign runs + +1. **Create** — you submit the campaign (dashboard or [`POST /v2/campaign`](/api-reference/campaigns/campaign-controller-create-v2)). Campaigns start automatically; there is no draft state. +2. **Dispatch** — Vapi claims contacts from your list and dials them, keeping up to `maxConcurrency` calls active at once. When a call ends, the next contact is dialed immediately. +3. **Complete** — each finished call is recorded on the campaign with its outcome, timestamps, and [analysis](/assistants/call-analysis). When every contact has been called, the campaign ends. + +### Campaign lifecycle + +| Status | Meaning | +| --- | --- | +| `scheduled` | Created; waiting for its schedule window (or about to start dialing) | +| `in-progress` | Actively dialing through the contact list | +| `ended` | All contacts have been called (`endedReason: campaign.ended.success`) | +| `cancelled` | Stopped by you before completing; in-progress calls finished naturally | + +Campaigns are immutable after creation — cancellation is the only change you can make to a running campaign. Deleting a campaign archives it: it stops (if running) and disappears from your list. To iterate on a campaign, duplicate it with your changes (see [Advanced](/campaigns/advanced#re-running-a-campaign)). + +## Concurrency: two limits apply + +- **Campaign pacing** — `maxConcurrency` on the campaign caps how many of *its* calls run at once. It's required at creation and can't exceed your org limit. +- **Organization capacity** — your org-wide [concurrency limit](/calls/call-concurrency) is shared by *all* calls your org makes, campaign or not. + +If your org is at capacity when a campaign call would dispatch, that dispatch can fail even though the campaign is under its own cap. If you place other calls while campaigns run, keep `maxConcurrency` comfortably below your org limit. + +## Next steps + +- **[Quickstart](/campaigns/quickstart)**: launch your first campaign from the dashboard +- **[Advanced](/campaigns/advanced)**: personalization, scheduling, the pre-dial webhook, and managing campaigns via the API +- **[API reference](/api-reference/campaigns/campaign-controller-create-v2)**: the `/v2/campaign` endpoints + + +It is a violation of FCC law to dial phone numbers without consent in an automated manner. See our [TCPA Consent Guide](/tcpa-consent) before launching campaigns. + diff --git a/fern/campaigns/quickstart.mdx b/fern/campaigns/quickstart.mdx new file mode 100644 index 000000000..3489abcba --- /dev/null +++ b/fern/campaigns/quickstart.mdx @@ -0,0 +1,102 @@ +--- +title: Campaigns quickstart +subtitle: Launch your first batch outbound campaign from the Vapi Dashboard +slug: campaigns/quickstart +description: Create, launch, and monitor a batch outbound calling campaign step by step in the Vapi Dashboard. +--- + +## Overview + +Launch a batch outbound campaign from the dashboard: upload your contacts, pick who handles the calls, set your concurrency, and hit launch. + +**In this quickstart, you'll learn to:** + +- Prepare a contact list (CSV or manual entry) +- Configure and launch a campaign +- Monitor progress and per-call outcomes + +Prefer to do this programmatically? See [managing campaigns via the API](/campaigns/advanced#manage-campaigns-via-the-api). + +## Prerequisites + +- A [Vapi account](https://dashboard.vapi.ai) with Campaigns enabled (see [availability](/campaigns/overview)) +- An **assistant** or **squad** to handle the calls +- A **phone number** — imported from a provider (Twilio, Vonage, Telnyx) or a free Vapi number +- Your contacts' phone numbers in E.164 format (e.g. `+14155551234`) + +## 1. Prepare your contacts + +The fastest path is a CSV. Only one column is required: + +| number | name | customer_issue | +| --- | --- | --- | +| +14151231234 | John | password reset | +| +14153455678 | Mary | address update | + +- `number` is **required**, lowercase, in E.164 format +- `name` is optional +- Any additional columns become [dynamic variables](/assistants/dynamic-variables) for that contact's call — `{{customer_issue}}` in your assistant's prompt resolves per contact +- Column names can't contain spaces and must start with a letter +- Save as UTF-8; avoid blank rows and duplicate headers + +For a handful of contacts, you can skip the CSV and enter them manually during campaign creation. + +## 2. Launch a campaign + + + + Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and click **Campaigns** in the left sidebar. + + + + Click **Create Campaign** and give it a name (e.g. "Post-Service Feedback"). + + + + Pick the number to call from. To maximize answer rates, review the [trusted calling best practices](/calls/outbound-calling#trusted-calling-and-caller-id) — unregistered numbers get flagged as spam. + + + + Choose **Upload CSV** (a template is available to download) or **Enter manually**. Uploaded rows are validated before launch. + + + + Select an **Assistant** or a **Squad**. + + + + Use the slider to cap how many calls run at once. The maximum is your organization's concurrency limit — leave headroom if you place other calls while the campaign runs. See [concurrency](/campaigns/overview#concurrency-two-limits-apply). + + + + Provide a server URL to approve or skip each contact right before dialing — useful for do-not-call checks or last-minute eligibility. Details in [Advanced](/campaigns/advanced#pre-dial-webhook). + + + + **Send Now** starts dialing immediately. **Schedule for later** starts dialing at the time you pick. + + + + Click **Launch campaign**. The campaign starts automatically — there is no draft state. + + + +## 3. Monitor your campaign + + + + Open the campaign to see its status (`scheduled` → `in-progress` → `ended`) and calls completing in real time. + + + + Each finished call shows the contact, duration, outcome, and links to the full call details — transcript, recording, and [analysis](/assistants/call-analysis). + + + + Cancelling stops new calls from being dialed; calls already in progress finish naturally. Campaigns can't be edited after launch — to change something, cancel and duplicate it with your changes (see [Advanced](/campaigns/advanced#re-running-a-campaign)). + + + + +It is a violation of FCC law to dial phone numbers without consent in an automated manner. See our [TCPA Consent Guide](/tcpa-consent) before launching campaigns. + diff --git a/fern/docs.yml b/fern/docs.yml index 3a8641ad6..717fe6ae6 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -388,15 +388,21 @@ navigation: icon: fa-light fa-circle-dot # Squads moved to top-level section - - section: Outbound Campaigns + - section: Campaigns collapsed: open-by-default contents: - page: Quickstart - path: outbound-campaigns/quickstart.mdx + path: campaigns/quickstart.mdx icon: fa-light fa-rocket + availability: pre-release - page: Overview - path: outbound-campaigns/overview.mdx + path: campaigns/overview.mdx icon: fa-light fa-eye + availability: pre-release + - page: Advanced + path: campaigns/advanced.mdx + icon: fa-light fa-sliders + availability: pre-release - section: Chat collapsed: open-by-default @@ -885,6 +891,10 @@ navigation: - tab: changelog redirects: + - source: /outbound-campaigns/overview + destination: /campaigns/overview + - source: /outbound-campaigns/quickstart + destination: /campaigns/quickstart - source: /developer-documentation destination: /introduction - source: /documentation/general/changelog diff --git a/fern/outbound-campaigns/overview.mdx b/fern/outbound-campaigns/overview.mdx deleted file mode 100644 index 996191599..000000000 --- a/fern/outbound-campaigns/overview.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Outbound campaigns overview -subtitle: Create, execute, and manage outbound phone campaigns directly within the Vapi Dashboard -slug: outbound-campaigns/overview -description: Learn how to efficiently schedule calls, manage recipients, analyze performance metrics, and review detailed call logs and transcripts with Vapi's Outbound Call Campaigns ---- - -## Overview - -Outbound Call Campaigns allow users to efficiently create, execute, and manage outbound phone campaigns directly within the Vapi Dashboard. It enables users to efficiently schedule calls, manage recipients, analyze performance metrics, and review detailed call logs and transcripts. - - - Vapi Setup Campaign - - -## Key benefits - -- **Intuitive UI**: Quickly set up campaigns in an easy-to-follow setup page -- **Personalized**: Use dynamic variables to personalized outreach -- **Analytics**: Get real-time monitoring and detailed analysis of call performance and outcomes - -## Common use cases - -- **Conversion Optimization**: Re-engage potential customers via targeted follow-up calls for abandoned carts -- **Appointment Reminders**: Reduce missed appointments with timely reminder calls -- **Customer Satisfaction**: Conduct post-service feedback and follow-up calls to enhance customer experiences -- **Subscription Renewals**: Facilitate timely renewals with proactive call reminders -- **Insurance Updates**: Verify and update policy details through targeted calls - -## Campaign setup process - -Outbound Call Campaigns follow a structured process: - - - - Set campaign name and type. - - - - Choose outbound phone numbers (recommend Twilio). - - - - Upload recipients via CSV, supported with dynamic variables. - - - - Select an existing assistant to handle the call. - - - - Review campaign and initiate or schedule calls for later. - - - -## Campaign analytics - -The Campaign Dashboard provides comprehensive insights: - -- **Campaign Overview**: Monitor status, completed calls, pick up rate, and voicemail -- **Detailed Call Reports**: Access individual call details, customer information, call duration, outcome statuses, and transcripts - -## Required information - -Outbound Campaigns only require a number to work. `number` column is required and needs to be spelled in lowercase. - -| number | | -| --- | --- | -| +14151231234 | | -| +14153455678 | | - - -Phone numbers must be formatted in E.164 format: [+] [country code] [subscriber number including area code] -- Example: +14151234567 -- Maximum 15 digits total -- No spaces or special characters - - -## Tips for Clean Data -- Use UTF-8 encoding when saving your CSV. -- Avoid blank rows or duplicated headers. -- Double-check that your column names match the variables used in your assistant. - -## Avoiding Spam - -To maximize call answer rates and establish trust with recipients, you should implement proper caller identification and trusted calling standards. This involves several key components that work together to verify your identity and build caller reputation. -Learn more about [Trusted Calling](/calls/outbound-calling#trusted-calling-and-caller-id) - -## Dynamic variables - -Outbound Campaigns allows users to specify dynamic variables to pass to Assistants via additional columns in the CSV file. Outbound Campaigns can take one more additional columns. - -| number | name | customer_issue | -| --- | --- | --- | -| +14151231234 | John | password reset | -| +14153455678 | Mary | address update | - -`{{name}}` and `{{customer_issue}}` can be used in the Assistant prompt as dynamic variables, based on this CSV file. - - -- Column names cannot have spaces. Use `{{customer_issue}}` instead of `{{customer issue}}` -- Column names must start with a letter -- Users can use the same [Default Variables](/assistants/dynamic-variables#default-variables) as they can within Assistants - - -## Concurrency - -Check concurrency limits in your Vapi organization. If your org has a concurrency limit of 10, a maximum of 10 calls will be started at a single time. The rest of the calls will be queued and retried a few minutes later as your concurrency slots become available. To increase call rate, you need you increase your Vapi org concurrency limit. - -Note that concurrency limits are on the Vapi side. Your telephony provider (e.g. Twilio) may have other rate limits. diff --git a/fern/outbound-campaigns/quickstart.mdx b/fern/outbound-campaigns/quickstart.mdx deleted file mode 100644 index ee88e2faa..000000000 --- a/fern/outbound-campaigns/quickstart.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Outbound campaigns quickstart -subtitle: Build a simple personalized outbound campaign that conducts post-service feedback and follow-up calls to improve customer experience -slug: outbound-campaigns/quickstart -description: Build a simple personalized outbound campaign that conducts post-service feedback and follow-up calls to improve customer experience ---- - -## Overview - -Build a simple personalized outbound campaign using Vapi that conducts post-service feedback and follow-up calls to improve customer experience and gather valuable insights from your customers. - - - Vapi Campaigns - - - -**In this quickstart, you'll learn to:** -- Set up an outbound campaign with customer data -- Configure personalized feedback collection calls -- Launch and monitor campaign performance -- Access detailed call outcomes and analytics - -## Prerequisites - -- A [Vapi account](https://dashboard.vapi.ai) -- Phone number set up in your organization with a provider like Twilio (Vapi free numbers do not work for Outbound Campaigns) -- Recipient information ready in CSV format -- An existing Assistant configured in your account - ---- - -## 1. Launch a Campaign - - - - Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and log in to your account. - - - - Click `Outbound Campaigns` in the left sidebar to access the campaigns section. - - - - - Click **Create Campaign** - - Enter a **Campaign Name** (e.g., "Post-Service Feedback Campaign") - - Select **Campaign Type** based on your feedback collection needs - - - - Select a phone number from your available numbers. This must be a number from your phone provider (like Twilio), not a Vapi free number. - - - - Upload your customer list: - - Click **Manage Recipients** - - Upload your CSV file with customer information - - Review the recipient list for accuracy - - Follow [best practices](/outbound-campaigns/overview#required-information) on how to format your CSV file - - - - Choose the Assistant that will conduct the feedback calls: - - Select from your existing Assistants - - - - - Review all campaign settings - - Verify recipient count and Assistant configuration - - Click **Launch Campaign** to start the outbound calls - - - ---- - -## 2. Monitor Your Campaign - - - - Once launched, monitor your campaign performance in real-time through the Campaign Dashboard. - - - - - View completion rates and call statuses - - Track progress of scheduled campaigns - - Cancel campaigns you no longer want to run - - - - See call logs for each customer contact, including: - - Call duration and outcome - - Transcript and recordings - - \ No newline at end of file