Skip to content

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"
  }
}