Campaign webhooks

Check contacts before dialing and receive lifecycle events.

Expand Webhook settings (optional) on the Campaign Details step to connect the campaign to your server. A campaign can make a blocking eligibility request before each call and send asynchronous campaign or contact events.

Configure the Server URL

Add the endpoint that should receive requests under Server URL. The Dashboard also lets you set a 1–30 second timeout, attach a credential, add HTTP headers, and route requests through Vapi’s static IP range (167.150.224.0/23) for firewall allowlisting.

Both Pre-dial webhook and Server messages require a Server URL.

Campaign webhook settings showing the Server URL, timeout, pre-dial webhook, and server messages controls

Filter contacts before dialing

Enable Pre-dial webhook to ask your server whether each contact is eligible immediately before Vapi places the call. Because this request blocks dispatch, keep the handler fast and idempotent.

Before each contact is dispatched, Vapi sends:

campaign.predial request
1{
2 "message": {
3 "type": "campaign.predial",
4 "timestamp": 1787266800000,
5 "campaignId": "3f8f0c31-2db0-4fb8-95d4-27cb56a2d7bf",
6 "contact": {
7 "id": "9a32ab38-4f18-4767-bf41-6326f290ebd4",
8 "campaignId": "3f8f0c31-2db0-4fb8-95d4-27cb56a2d7bf",
9 "orgId": "8e8f1dc8-2993-4b4d-b2fd-9f0fc2739f6d",
10 "number": "+14155550100",
11 "name": "Ada",
12 "createdAt": "2026-08-20T20:18:42.000Z"
13 }
14 }
15}

The contact can also include assistantOverrides or squadOverrides, including dynamic variable values supplied for that contact.

Return true to allow the call:

Eligible response
1{
2 "eligible": true
3}

Return false to skip it:

Ineligible response
1{
2 "eligible": false
3}

The response must be valid JSON with a Boolean eligible field.

ResultContact behavior
eligible: trueVapi continues dispatching the call.
eligible: falseVapi does not place the call and records contact.skipped.
Unreachable server, timeout, non-2xx, or invalid responseVapi does not place the call and records contact.predial-failed.

The Dashboard allows a timeout of up to 30 seconds for this check. Use the pre-dial webhook for suppression lists, consent checks, account-state queries, or other rules that must be evaluated against your backend at call time.

Receive campaign events

Enable Server messages, then select the events that Vapi should send:

  • campaign.started
  • campaign.ended
  • campaign.cancelled
  • campaign.archived
  • contact.dispatched
  • contact.completed
  • contact.failed
  • contact.skipped
  • contact.predial-failed

Every selected event uses the same envelope. For example, contact.completed sends:

contact.completed
1{
2 "message": {
3 "type": "campaign.event",
4 "timestamp": 1787266800000,
5 "campaignId": "3f8f0c31-2db0-4fb8-95d4-27cb56a2d7bf",
6 "eventType": "contact.completed",
7 "data": {
8 "contactId": "9a32ab38-4f18-4767-bf41-6326f290ebd4",
9 "callId": "73a3d2bc-8bde-4a54-bc9d-3503ea8d6b1f",
10 "endedReason": "customer-ended-call"
11 }
12 }
13}

The data object depends on eventType:

Eventsdata fields
campaign.startedworkflowId
campaign.ended, campaign.cancelledendedReason
campaign.archivedEmpty object
contact.dispatched, contact.skippedcontactId
contact.completed, contact.failedcontactId, callId, endedReason
contact.predial-failedcontactId, error

Campaign events are asynchronous. Return any successful 2xx response; Vapi does not use the response body to control the campaign. Process duplicate deliveries safely and do not depend on events arriving in a particular order.

A campaign event reports lifecycle data, not the complete call record. To receive the transcript, recording information, analysis, and other call details, configure the assistant—or the relevant assistant in a squad—to send end-of-call-report. Use callId to associate that report with the campaign contact event.

The default server timeout is 20 seconds. Campaign event delivery does not retry by default; configure a Server URL backoff plan when your integration requires retries.

Next steps