Webhooks
Receive signed events for everything that happens on a call.
Webhooks deliver call lifecycle events to your servers as JSON POSTs. Events for one call arrive in order. Delivery retries with exponential backoff for 24 hours until your endpoint returns a 2xx.
Event catalogue
- call.initiated, call.ringing, call.answered, call.completed
- call.dtmf for keypad input, call.speech for detected utterances
- recording.available when a recording is stored
- transcript.completed with the full speaker-labelled transcript
- agent.handover when an AI agent escalates to a person
Verifying signatures
Every delivery carries an X-GTalk-Signature header: an HMAC-SHA256 of the timestamp and raw body, keyed with your endpoint secret. Reject anything unsigned, stale or mismatched.
verify.ts
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(req: Request, body: string, secret: string) {
const [ts, sig] = (req.headers.get("x-gtalk-signature") ?? "").split(",");
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = createHmac("sha256", secret)
.update(ts + "." + body)
.digest("hex");
return timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}Example payload
call.completed.json
{
"id": "evt_31c8aa",
"type": "call.completed",
"created": "2026-07-18T14:07:31Z",
"data": {
"call_id": "call_9f4e2a",
"duration_seconds": 184,
"hangup_cause": "normal_clearing",
"recording_id": "rec_77b1d0"
}
}