Events
Every event comes in the same envelope: id, type, created, livemode, api_version and data.object. The object is the lead or the call as the API returns it, plus a few fields of the event’s own.
Check the signature before you trust an event: see Webhooks and signatures. An event can arrive twice: skip an id you have already handled.
| Event | About | When |
|---|---|---|
lead.created |
lead | A lead was added: through POST /leads, or one Add Lead in the app. CSV imports do not send it. |
lead.queued |
lead | A lead was put in the dialing queue, right after lead.created (or when POST /leads re-queued an existing lead). status says queued, scheduled or held, with scheduled_for. |
lead.interested |
call | The AI saw buying intent. intent carries what the lead said (excerpt) and who the call is offered to (the ready SDRs first, else the closers). |
lead.opted_out |
lead | The lead’s number went on the Do Not Call list. opt_out.source says how: api, ai (the AI’s tool during the call), outcome (a DNC outcome), manual, bulk or sms (a STOP reply). One event per lead of yours with that number. |
lead.late |
lead | A speed-to-lead lead was still waiting for its call after the campaign’s late minutes (default 15). It is still called; late is true. |
call.started |
call | A call to the lead started dialing (the call record exists). |
call.answered |
call | The far end picked up. answered_by is person, machine (a voicemail box or a phone menu) or unknown (nothing checked). |
call.completed |
call | The outcome is final: outcome, the note, duration, handled_by, owner, and the API paths for the recording and transcript. An AI-only call sends it after the after-call check; a call a person handled sends it when they file the outcome (or after 10 minutes with none: outcome other, note “No outcome was filed”). A later correction sends it again with the same id, a newer updated and revision 2, 3 … |
handover.accepted |
call | A person took the call: handled_by names them (an SDR or a closer), tth_seconds is how long it took from the intent. |
voicemail.left |
call | A voicemail was delivered. Never sent for a message that was not delivered. |
callback.booked |
lead | A day and time to call the lead back was booked. callback.at is UTC; callback.timezone is the lead’s. |
lead.created
Section titled “lead.created”A lead was added: through POST /leads, or one Add Lead in the app. CSV imports do not send it.
Sent when: POST /leads accepted a new lead; A person added one lead in the app.
{ "id": "evt_leadcreatedxxxxxxxxxxxxx", "type": "lead.created", "created": "2026-10-06T16:58:04Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "name": "LEAD_NAME", "phone": "+15555550142", "address": "1 Example Street, Springfield", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "lead_source": "Example CRM", "owner": null, "created": "2026-10-06T16:58:04.000Z", "updated": "2026-10-06T16:58:04.000Z", "status": "queued", "call_now": true, "place_in_line": null, "estimated_wait_seconds": null, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "callback_at": null, "late": false, "attempts": 0, "last_outcome": null, "last_outcome_label": null, "next_dial_at": null, "calls": [], "livemode": true } }}lead.queued
Section titled “lead.queued”A lead was put in the dialing queue, right after lead.created (or when POST /leads re-queued an existing lead). status says queued, scheduled or held, with scheduled_for.
Sent when: POST /leads accepted a lead; POST /leads re-queued a lead last sent longer ago than the duplicate window.
{ "id": "evt_leadqueuedxxxxxxxxxxxxxx", "type": "lead.queued", "created": "2026-10-06T16:58:04Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "name": "LEAD_NAME", "phone": "+15555550142", "address": "1 Example Street, Springfield", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "lead_source": "Example CRM", "owner": null, "created": "2026-10-06T16:58:04.000Z", "updated": "2026-10-06T16:58:04.000Z", "status": "queued", "call_now": true, "place_in_line": null, "estimated_wait_seconds": null, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "callback_at": null, "late": false, "attempts": 0, "last_outcome": null, "last_outcome_label": null, "next_dial_at": null, "calls": [], "livemode": true } }}lead.interested
Section titled “lead.interested”The AI saw buying intent. intent carries what the lead said (excerpt) and who the call is offered to (the ready SDRs first, else the closers).
Sent when: The AI detected buying intent during the call.
Besides the call object’s fields, it carries:
| Field | Type | Notes |
|---|---|---|
intent |
object |
{ "id": "evt_leadinterestedxxxxxxxxxx", "type": "lead.interested", "created": "2026-10-06T16:59:02Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "in_progress", "outcome": null, "outcome_label": null, "note": null, "duration_seconds": null, "started": "2026-10-06T16:58:06.000Z", "answered": "2026-10-06T16:58:14.000Z", "ended": null, "updated": "2026-10-06T16:59:02.000Z", "handled_by": { "id": null, "name": "AI", "role": "ai" }, "owner": null, "tth_seconds": null, "callback_at": null, "recording_available": false, "transcript_available": false, "started_by": { "type": "api", "api_key_id": "key_example" }, "intent": { "at": "2026-10-06T16:59:02.000Z", "excerpt": "Yes, I'd like to hear what it would cost for my house.", "confidence": 0.92, "offered_to": [ { "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "name": "SDR_NAME", "role": "sdr" } ] } } }}lead.opted_out
Section titled “lead.opted_out”The lead’s number went on the Do Not Call list. opt_out.source says how: api, ai (the AI’s tool during the call), outcome (a DNC outcome), manual, bulk or sms (a STOP reply). One event per lead of yours with that number.
Sent when: POST /leads/{id}/opt_out, or the DNC endpoints; The AI took the number off the list on a call; A DNC outcome; Mark DNC, the DNC page or bulk DNC in the app; A STOP reply by text.
Besides the lead object’s fields, it carries:
| Field | Type | Notes |
|---|---|---|
opt_out |
object |
{ "id": "evt_leadoptedoutxxxxxxxxxxxx", "type": "lead.opted_out", "created": "2026-10-06T17:01:40Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "name": "LEAD_NAME", "phone": "+15555550142", "address": "1 Example Street, Springfield", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "lead_source": "Example CRM", "owner": null, "created": "2026-10-06T16:58:04.000Z", "updated": "2026-10-06T17:01:40.000Z", "status": "out_of_queue", "call_now": true, "place_in_line": null, "estimated_wait_seconds": null, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "callback_at": null, "late": false, "attempts": 0, "last_outcome": "dnc", "last_outcome_label": "DNC", "next_dial_at": null, "calls": [], "livemode": true, "opt_out": { "source": "ai", "at": "2026-10-06T17:01:40.000Z" } } }}lead.late
Section titled “lead.late”A speed-to-lead lead was still waiting for its call after the campaign’s late minutes (default 15). It is still called; late is true.
Sent when: The late sweep stamped the lead (every 30 s).
{ "id": "evt_leadlatexxxxxxxxxxxxxxxx", "type": "lead.late", "created": "2026-10-06T17:13:04Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "name": "LEAD_NAME", "phone": "+15555550142", "address": "1 Example Street, Springfield", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "lead_source": "Example CRM", "owner": null, "created": "2026-10-06T16:58:04.000Z", "updated": "2026-10-06T17:13:04.000Z", "status": "queued", "call_now": true, "place_in_line": null, "estimated_wait_seconds": null, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "callback_at": null, "late": true, "attempts": 0, "last_outcome": null, "last_outcome_label": null, "next_dial_at": null, "calls": [], "livemode": true } }}call.started
Section titled “call.started”A call to the lead started dialing (the call record exists).
Sent when: The dialer, speed to lead, POST /calls or a person dialed the lead.
{ "id": "evt_callstartedxxxxxxxxxxxxx", "type": "call.started", "created": "2026-10-06T16:58:06Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "ringing", "outcome": null, "outcome_label": null, "note": null, "duration_seconds": null, "started": "2026-10-06T16:58:06.000Z", "answered": null, "ended": null, "updated": "2026-10-06T16:58:06.000Z", "handled_by": { "id": null, "name": "AI", "role": "ai" }, "owner": null, "tth_seconds": null, "callback_at": null, "recording_available": false, "transcript_available": false, "started_by": { "type": "api", "api_key_id": "key_example" } } }}call.answered
Section titled “call.answered”The far end picked up. answered_by is person, machine (a voicemail box or a phone menu) or unknown (nothing checked).
Sent when: The answering-machine check decided; The voicemail detector decided (or 20 s passed with no mailbox); A person on our side picked the call up directly.
Besides the call object’s fields, it carries:
| Field | Type | Notes |
|---|---|---|
answered_by |
string | One of person / machine / unknown. |
{ "id": "evt_callansweredxxxxxxxxxxxx", "type": "call.answered", "created": "2026-10-06T16:58:14Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "in_progress", "outcome": null, "outcome_label": null, "note": null, "duration_seconds": null, "started": "2026-10-06T16:58:06.000Z", "answered": "2026-10-06T16:58:14.000Z", "ended": null, "updated": "2026-10-06T16:58:14.000Z", "handled_by": { "id": null, "name": "AI", "role": "ai" }, "owner": null, "tth_seconds": null, "callback_at": null, "recording_available": false, "transcript_available": false, "started_by": { "type": "api", "api_key_id": "key_example" }, "answered_by": "person" } }}call.completed
Section titled “call.completed”The outcome is final: outcome, the note, duration, handled_by, owner, and the API paths for the recording and transcript. An AI-only call sends it after the after-call check; a call a person handled sends it when they file the outcome (or after 10 minutes with none: outcome other, note “No outcome was filed”). A later correction sends it again with the same id, a newer updated and revision 2, 3 …
Sent when: The after-call check filed an AI-only call’s outcome; A person filed the outcome; 10 minutes passed with no outcome filed; The outcome was corrected later.
Besides the call object’s fields, it carries:
| Field | Type | Notes |
|---|---|---|
revision |
integer | |
recording_path |
string or null | GET it for a 5-minute recording link |
transcript_path |
string or null |
{ "id": "evt_callcompletedxxxxxxxxxxx", "type": "call.completed", "created": "2026-10-06T17:05:20Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "ended", "outcome": "interested", "outcome_label": "Interested", "note": "Wants a quote for a 6 kW system; home owner, roof replaced 2019.", "duration_seconds": 412, "started": "2026-10-06T16:58:06.000Z", "answered": "2026-10-06T16:58:14.000Z", "ended": "2026-10-06T17:04:58.000Z", "updated": "2026-10-06T17:05:20.000Z", "handled_by": { "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "name": "SDR_NAME", "role": "sdr" }, "owner": null, "tth_seconds": 9.3, "callback_at": null, "recording_available": true, "transcript_available": true, "started_by": { "type": "api", "api_key_id": "key_example" }, "revision": 1, "recording_path": "/api/v1/external/calls/e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b/recording", "transcript_path": "/api/v1/external/calls/e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b/transcript" } }}handover.accepted
Section titled “handover.accepted”A person took the call: handled_by names them (an SDR or a closer), tth_seconds is how long it took from the intent.
Sent when: An SDR bridged or took over the call; A closer pressed 1.
{ "id": "evt_handoveracceptedxxxxxxxx", "type": "handover.accepted", "created": "2026-10-06T16:59:11Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "in_progress", "outcome": null, "outcome_label": null, "note": null, "duration_seconds": null, "started": "2026-10-06T16:58:06.000Z", "answered": "2026-10-06T16:58:14.000Z", "ended": null, "updated": "2026-10-06T16:59:11.300Z", "handled_by": { "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "name": "SDR_NAME", "role": "sdr" }, "owner": null, "tth_seconds": 9.3, "callback_at": null, "recording_available": false, "transcript_available": false, "started_by": { "type": "api", "api_key_id": "key_example" } } }}voicemail.left
Section titled “voicemail.left”A voicemail was delivered. Never sent for a message that was not delivered.
Sent when: The voicemail agent reported the message delivered, confirmed after the call.
{ "id": "evt_voicemailleftxxxxxxxxxxx", "type": "voicemail.left", "created": "2026-10-06T16:58:54Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "e4d3c2b1-a09f-4e8d-9c7b-6a5f4e3d2c1b", "object": "call", "livemode": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "name": "LEAD_NAME", "phone": "+15555550142" }, "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "direction": "outbound", "status": "ended", "outcome": "voicemail", "outcome_label": "Voicemail", "note": null, "duration_seconds": 48, "started": "2026-10-06T16:58:06.000Z", "answered": null, "ended": "2026-10-06T16:58:54.000Z", "updated": "2026-10-06T16:58:54.000Z", "handled_by": { "id": null, "name": "AI", "role": "ai" }, "owner": null, "tth_seconds": null, "callback_at": null, "recording_available": false, "transcript_available": false, "started_by": { "type": "api", "api_key_id": "key_example" } } }}callback.booked
Section titled “callback.booked”A day and time to call the lead back was booked. callback.at is UTC; callback.timezone is the lead’s.
Sent when: The AI booked it on the call; Nobody took an interested lead and it was filed as a callback; A person booked it.
Besides the lead object’s fields, it carries:
| Field | Type | Notes |
|---|---|---|
callback |
object |
{ "id": "evt_callbackbookedxxxxxxxxxx", "type": "callback.booked", "created": "2026-10-06T17:02:10Z", "livemode": true, "api_version": "2026-10-01", "data": { "object": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "name": "LEAD_NAME", "phone": "+15555550142", "address": "1 Example Street, Springfield", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "lead_source": "Example CRM", "owner": null, "created": "2026-10-06T16:58:04.000Z", "updated": "2026-10-06T17:02:10.000Z", "status": "callback_scheduled", "call_now": true, "place_in_line": null, "estimated_wait_seconds": null, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "callback_at": "2026-10-07T18:30:00.000Z", "late": false, "attempts": 0, "last_outcome": null, "last_outcome_label": null, "next_dial_at": null, "calls": [], "livemode": true, "callback": { "at": "2026-10-07T18:30:00.000Z", "timezone": "America/New_York" } } }}