Skip to content

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": [ … ]
}
FieldDescription
call_iduuidThe call.
external_refstringEcho of the external_ref you sent.
status'completed' | 'failed'Whether the call ran to an end.
outcomestringcompleted | 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));
}