Webhooks give developers full control over the Atllas integration layer. You can trigger calls via HTTP POST and receive call results delivered to any endpoint you specify.
Inbound Webhooks — Trigger a Call
Send a POST request to your inbound webhook URL to add a contact to a campaign and trigger a call.
Endpoint
POST https://wh.atll.as/{your-webhook-slug}
Your webhook slug is generated when you create an inbound webhook. Find it under Integrations → Webhooks. Each inbound webhook is bound to a specific campaign at creation time, so the campaign does not need to be specified per request.
Request Body
{
"type": "calls.execute",
"data": {
"phoneNumber": "+15551234567",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"companyName": "Acme Corp",
"note": "Expressed interest in the enterprise plan"
}
}
| Field | Required | Description |
|---|
type | Yes | Must be "calls.execute" |
data.phoneNumber | Yes | E.164 format recommended (+15551234567) |
data.firstName | No | Used for personalisation |
data.lastName | No | |
data.email | No | Used for email follow-ups if configured |
data.companyName | No | |
data.note | No | Additional context for this contact |
data.address1, data.address2, data.city, data.state, data.zipCode | No | Address fields, available for personalisation |
Field names are camelCase. Sending snake_case (e.g. first_name, phone_number) will be ignored — the call will be placed using only phoneNumber.
Response
A 201 response means the request was accepted. The campaign attached to the webhook must be active for the call to actually be placed; if the user is out of credits, the call is recorded as cancelled even though the response status is the same.
Customising the Phone Call
The webhook is bound to an inbound campaign in AI Calling. That campaign owns every call setting — voice, call script, voicemail message, follow-ups, call forwarding, keypad navigation, language, background ambiance, and so on. Whatever’s on the campaign is what every webhook-triggered call uses.
To change call behaviour:
- Open AI Calling and find the campaign your webhook is bound to (it’ll be labelled as inbound)
- Edit any setting — voice, script, follow-ups, voicemail, etc.
- Save
Inbound campaigns can be edited at any time (unlike outbound campaigns, which lock once they start dialing). Changes apply to all future calls triggered by the webhook — already-completed calls keep the settings they ran with.
Viewing Results
Every call triggered by the webhook appears in the bound campaign’s results table in AI Calling — the same place outbound campaign results live.
Each call result includes the transcript, recording, AI summary, lead warmth classification, and extracted action items. See Call Results & Transcripts for what’s in the detail panel.
If you also want each completed call delivered to your own endpoint as it happens, configure a Response Webhook on the inbound webhook (covered below) — Atllas will POST the result back to your URL when the call wraps up.
Outbound Webhooks — Receive Call Results
Configure a URL to receive a POST request after each call completes.
Setting Up
- Go to Integrations → Webhooks → Outbound
- Click Add Endpoint
- Enter your endpoint URL
- Optionally add custom headers (see below)
- Click Save and use Test to verify connectivity
Event
Outbound webhooks emit a single event:
| Event | When |
|---|
call.finished | Fires after the call completes and final analysis is attached (transcript, summary, lead warmth) |
Payload
{
"type": "call.finished",
"timestamp": 1714694400000,
"webhook": {
"id": "wh_abc123",
"type": "outbound"
},
"call": {
"id": "clx_abc123",
"status": "finished",
"recipient": {
"phoneNumber": "+15551234567",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"address1": "123 Main St",
"city": "Austin",
"state": "TX",
"zipCode": "78701",
"note": "VIP lead"
},
"summary": "Jane expressed interest in the enterprise plan and asked about pricing.",
"transcript": [
{ "who": "assistant", "what": "Hi, is this Jane?", "when": "2024-04-30T14:00:03.000Z" },
{ "who": "user", "what": "Yes, speaking.", "when": "2024-04-30T14:00:05.000Z" }
],
"recording": "https://...",
"duration": 142,
"analysis": {
"lead_warmth": "hot",
"sentiment": "positive"
},
"tokensConsumed": 1
},
"campaign": {
"id": "cmp_xyz789",
"name": "Q2 Enterprise Outbound"
}
}
Field Reference
| Path | Description |
|---|
type | Always "call.finished" |
timestamp | Unix epoch in milliseconds |
webhook.id | The outbound webhook’s ID |
webhook.type | Always "outbound" |
call.id | The call ID |
call.status | One of: finished, missed, failed, cancelled, filtered (DNC) |
call.recipient.phoneNumber | Contact phone in E.164 |
call.recipient.firstName / lastName / email | Contact identity fields |
call.recipient.address1 / address2 / city / state / zipCode / note | Optional address + note |
call.summary | One-paragraph AI summary |
call.transcript | Array of { who, what, when } turns. who is typically "user" (caller) or "assistant" (AI); when is an ISO timestamp |
call.recording | URL to the MP3 recording |
call.duration | Call length in seconds |
call.analysis.lead_warmth | hot, warm, cold, dead, or unknown |
call.tokensConsumed | Credits used for the call |
campaign.id / campaign.name | Source campaign info |
Recipient field names are camelCase (firstName, phoneNumber) and there is no company field on the recipient. Build your integrations against the names shown above.
Response Webhooks
If you triggered a call via an inbound webhook and want to receive the result back to the originating system, configure a Response Webhook URL on your inbound webhook. When the call completes, Atllas POSTs the result payload to that URL — forming a request/response pattern.
Response webhook payloads use the call.completed event type and the same overall structure as outbound webhook payloads, with one difference: recipient, summary, transcript, recording, duration, analysis, and tokensConsumed are all optional, since some calls (e.g. ones that never connected) won’t have all fields populated.
Signature Verification
If your outbound webhook is configured with a secret, every delivery includes an HMAC-SHA256 signature header so your endpoint can verify the payload genuinely came from Atllas (and wasn’t tampered with in transit).
Atllas sends two extra headers when a secret is set:
| Header | Description |
|---|
X-Atllas-Signature | Hex-encoded HMAC-SHA256 of the raw JSON body, using your secret as the key |
X-Atllas-Event | The event type (call.finished) — useful for routing without parsing the body |
To verify a request:
import { createHmac } from 'node:crypto'
function verifyAtllasWebhook(rawBody, secret, signatureHeader) {
const expected = createHmac('sha256', secret).update(rawBody).digest('hex')
return expected === signatureHeader
}
Use the raw request body (not the parsed JSON) when computing the HMAC — re-serialising the parsed object can produce a different byte sequence and fail verification.
Webhook secrets are configured per-endpoint. Zapier-managed subscriptions get a secret automatically. If you need to add a secret to a manually-created webhook, contact support.
Add custom headers to your outbound webhook requests for authentication:
| Use Case | Header Example |
|---|
| API key auth | X-API-Key: your-secret-key |
| Bearer token | Authorization: Bearer your-token |
| HubSpot / FollowUp Boss | Provider-specific auth headers |
Headers are encrypted at rest and never exposed in the portal after saving.
Testing & Logs
Click Test on any outbound webhook to send a sample payload to your endpoint. The portal shows the HTTP response code and body so you can verify your endpoint is receiving correctly.
The test payload uses event type "call.completed" and contains placeholder data — not "call.finished" like real outbound deliveries. If your endpoint switches behaviour by event type, make sure to also test against a real call before relying on it in production. The signature header is not included on test deliveries.
Delivery Logs
The delivery log shows recent webhook delivery attempts with:
- Timestamp
- HTTP status code returned by your endpoint
- Response body (truncated)
- Whether delivery succeeded or failed