Webhooks
Pass a callback_url when you place a call. When the call ends, the result is POSTed there — retried with backoff until your endpoint answers 2xx.
Payload
callbackhttp
POST {callback_url}
x-cv-signature: <hex HMAC-SHA256 of the raw body with your callback signing secret>
{
"call_id": "…",
"external_ref": "crm-8812",
"status": "completed",
"outcome": "booked",
"duration_seconds": 143,
"summary": "Confirmed; moved to Tue 14:30.",
"transcript": [ … ],
"actions": [ … ]
}| Field | Description |
|---|---|
call_iduuid | The call. |
external_refstring | Echo of the external_ref you sent. |
status'completed' | 'failed' | Whether the call ran to an end. |
outcomestring | completed | no_answer | voicemail | opted_out | transferred | booked | failed |
transcript{ direction, text }[] | in = the other party, out = the agent. |
actions{ type, … }[] | Tool actions the agent took: bookings, notes, opt-outs, transfers. |
Verifying the signature
Compute an HMAC-SHA256 of the raw body with the webhook secret from Settings and compare in constant time.
verify.tsts
import crypto from 'node:crypto';
function verify(rawBody: string, header: string, secret: string) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}