AI Bot Vendor - Dialer Requirements (Beta)
Wants to integrate your platform with Dialer?
This guide is for customers who want to connect their own AI voice bot to the CommPeak Dialer (instead of using a managed available engines). It is the full integration contract. The contract is vendor-neutral: any bot that satisfies it will work.
Your bot has two responsibilities:
A. Accept a SIP call from the dialer and read the per-call context we attach as custom SIP headers
B. Call two dialer webhooks during the call - one to transfer to a human, one to end the call with a disposition
Onboarding is done with CommPeakThere is no self-serve "custom bot" setup yet. Build your bot to this contract, then contact your CommPeak account manager. We register your engine and provide: the dialer source IPs to allowlist, your webhook URL + Bearer token, your account's status codes, and confirm your concurrency limit (it becomes the Bot Flow channel count)
How it fits together
A predictive campaign dials a lead; when a live person answers, the dialer bridges the call to your bot with the lead's context attached to the INVITE.
sequenceDiagram
participant D as CommPeak Dialer
participant B as Your AI bot
D->>B: SIP INVITE sip:{number}@{your host} + X-* headers
B-->>D: 200 OK (answer the call)
Note over B: Bot runs the qualifying conversation
Note over D,B: Every webhook carries Authorization Bearer + call_id (= X-Dialer-Call-Id)
alt Lead asks for a human
B->>D: POST /transfer { call_id, summary }
D-->>B: { result: "<line to speak>" }
D->>D: Bridge the lead to an available human in its group
else Call is ending
B->>D: POST /hangup { call_id, status_code, comment, next_call_at }
D-->>B: { result: ok }
D->>B: SIP BYE (dialer ends the call)
opt Your side hangs up first
B->>D: SIP BYE (optional)
end
endPart A - Receiving the call (SIP)
Dial target
The dialer originates sip:{number}@{host}:
{number}: the E.164 phone number you bind to the bot. This is the inbound routing key (route the call by the dialed number), not the bot/assistant ID{host}: your SIP host, e.g.sip.example.com:5060;transport=tcp.
You give CommPeak the host and number at onboarding, and you must allowlist the dialer's FreeSWITCH source IPs (we provide them) so your SIP endpoint accepts our INVITE
Per-call context headers
The dialer attaches lead and call context as custom X-… SIP headers on the INVITE. Read them off the incoming SIP message (most bot platforms expose SIP headers as variables).
| Header | Carries | Example |
|---|---|---|
X-Dialer-Call-Id | Call-correlation id - you MUST echo this back as call_id on every webhook | a UUID |
X-Tenant-Id | Account (tenant) id | 42 |
X-Lead-Id | Lead id | 99812 |
X-Lead-First-Name | Lead first name | Jane |
X-Lead-Last-Name | Lead last name | Doe |
X-Lead-Phone | Lead phone | +15551234567 |
X-Campaign-Id | Campaign id | 7 |
X-Campaign-Name | Campaign name | Q3 Outreach |
X-OI | Your CRM's original identifier | crm-8821 |
X-Lead-Local-Time | The lead's local wall-clock time (Y-m-d H:i) | 2026-06-30 14:05 |
X-Lead-Timezone | The lead's GMT-offset label | GMT+3 |
Nullable fields are sent as empty strings, not omitted.
Use the lead's local time for callbacksWhen the lead asks for a callback, compute the time against
X-Lead-Local-Time/X-Lead-Timezone- never your bot's own clock - then send it asnext_call_at(see Part B)
Inbound calls
If you also accept inbound calls (a caller dialing in via an IVR), the INVITE adds:
| Header | Carries |
|---|---|
X-Source | inbound |
X-DID | The number the caller dialed |
X-Caller-Number | The caller's number |
X-Lead-Matched | Whether the caller matched a known lead |
When no lead is matched, the dialer accepts only these reserved status_code values on hangup (recorded for reporting only): INBOUND_RESOLVED, INBOUND_NO_RESOLUTION, INBOUND_TRANSFERRED, INBOUND_ABANDONED.
Part B - Calling the Dialer webhooks
Endpoints
Both are POST, Content-Type: application/json. {engine} and {bot_flow_id} are filled into the full URL we give you at onboarding.
POST /integrations/aibot/{engine}/transfer/{bot_flow_id}
POST /integrations/aibot/{engine}/hangup/{bot_flow_id}
Authentication
Send the per-engine token as a Bearer header on every request:
Authorization: Bearer <your-webhook-token>
It's verified in constant time; a missing or blank token is rejected with HTTP 401. (No request-body HMAC signature is required.)
Correlation & idempotency
Every webhook body must include:
call_id(required): exactly theX-Dialer-Call-Idyou received on the SIP INVITE. This is how the dialer ties the webhook to the live call and lead.engine_event_id(recommended): a stable per-conversation id of yours. The dialer dedupes on(call_id, action, engine_event_id)for 24h, so a retry of the same webhook is safely ignored. Omit it and no dedupe happens.
Transfer to a human
POST /integrations/aibot/{engine}/transfer/{bot_flow_id}
| Field | Required | Meaning |
|---|---|---|
call_id | Yes | The correlation ID |
summary | Yes | A short recap shown to the human who receives the call |
engine_event_id | Recommended | AI Engine call ID/UUID |
You don't pick a target - the dialer bridges the lead to an available human in the lead's predictive group. Keep the lead on the line; the dialer un-bridges your leg and runs the human search.
Response: { "result": "<a short line to speak to the caller>" } (e.g. "Transferring you now, please hold."). Some integrations return { "result": "ok" } - speak your own hold line in that case.
End the call (hangup)
POST /integrations/aibot/{engine}/hangup/{bot_flow_id}
| Field | Required | Meaning |
|---|---|---|
call_id | Yes | The correlation ID |
status_code | Yes | The disposition for the lead - one of your account's status codes (see below) |
comment | No | One-sentence outcome, saved as a comment on the lead |
next_call_at | No | Callback time in ISO-8601 with UTC offset, e.g. 2026-06-17T20:00:00+03:00. Blank, past, or unparseable values are ignored. Stored as UTC |
summary | No | Conversation summary |
engine_event_id | Recommended | AI Engine call ID/UUID |
An unknown/unmapped status_code applies the campaign's default status and returns HTTP 400 with { "error": "..." }.
Response: { "result": "ok" }. After processing hangup, the dialer sends a SIP BYE and ends the call - make sure your SIP endpoint handles it gracefully. You can also send your own BYE as soon as hangup succeeds (whichever side's BYE lands first ends the call), but it's optional. Calling hangup more than once is unnecessary.
Status codes
Your valid status_code values are provided by CommPeak at setup - they map to your account's lead statuses. Treat the set as a fixed enum and have your model pick from it. Codes are not sent per call.
Part C - What your Bot must implement
Concretely, your bot needs:
- A
transfer_to_humanaction →POST …/transferwithsummary+ the correlation envelope + Bearer. Trigger it only when the lead explicitly asks for a human now. - A
hangupaction →POST …/hangupwithstatus_code(+ optionalcomment,next_call_at,summary) + the correlation envelope + Bearer. Trigger it when the call is ending. - A call-termination step - after
hangupsucceeds, the dialer sends a SIPBYEto end the call; handle it gracefully. Sending your ownBYEfirst is optional. Don't callhanguptwice.
Part D - Vendor API Access the Dialer needs
To connect your vendor account as an AI Engine and import a bot as a Bot Flow, the Dialer calls your vendor account's API directly. The API key you provide must allow the reads below - without them the Engine cannot be created and bots cannot be imported.
API credentials
| What the Dialer needs | Why |
|---|---|
| API base URL | All reads/writes below are sent here |
| API key / token | Authenticates the Dialer against your account |
NOTECredentials are stored encrypted and are never exposed back in the UI (masked on edit; leave blank to keep the stored value).
Connectivity test
The Engine's Test connection runs these read probes - all must return successfully before the Engine can be used:
Bot list
The bot must already exist on your vendor account - the Dialer never authors bots. When creating a Bot Flow, the Dialer enumerates your account's bots to build the import list:
Bots already imported into another Bot Flow are hidden from the list (one Bot Flow per vendor bot).
Max concurrent calls (outbound channels)
A Bot Flow's Outbound Channels (simultaneous calls - one AI Agent is created per channel) is validated against the bot's concurrency limit on the vendor side:
Your account-level Dialer limits (max concurrent AI agents, AI-per-human ratio) always apply on top.
Auto-provisioning write access ("Set it for me")
If you use the recommended one-click setup, the same API key must also allow creating/updating on your account: the webhook tools attached to the bot and the SIP phone number binding - plus, per vendor: Vapi - the BYO SIP trunk credential (POST /credential) and the assistant update; ElevenLabs - the webhook secret (POST /v1/convai/secrets) and the agent workflow update. If your key is read-only, choose "I'll set it up myself" and follow the post-save guide instead.
Integration checklist
-
SIP endpoint answers
sip:{number}@{host}and the dialer's source IPs are allow listed. -
Bot reads
X-Dialer-Call-Idand theX-Lead-*/X-Campaign-*context headers. -
Callback times are computed from
X-Lead-Local-Time/X-Lead-Timezone. -
Webhooks send
Authorization: Bearer <token>andcall_id(=X-Dialer-Call-Id). -
hangupalways sends a validstatus_code; the bot handles the dialer'sBYEthat follows (its ownBYEis optional). -
transfersends a usefulsummaryfor the receiving human. -
(Inbound) handles
X-Source=inboundcontext and the reservedINBOUND_*codes. -
API key created with the scopes above and pasted into the AI Engine.
-
Test connection passes (all probes green).
-
The bot exists on the vendor account before creating the Bot Flow.
-
Bot concurrency on the vendor covers the Outbound Channels you plan to set.
✔️ Build to this contract, then contact CommPeak to onboard your bot.
Updated about 13 hours ago