POST requests to your server when things
happen during a call — an inbound call starts, a call ends, a grading
run completes, and so on. There are two delivery models:
Webhook endpoints (recommended)
Multiple URLs, per-endpoint secrets, and per-endpoint event filters.
Manage via
GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.Single-URL legacy webhook
One URL per org receives every event type. Still supported;
managed at
GET/PUT /v1/webhook.Payload format
Every webhook body is a JSON object withtype and data:
Signature verification
Every request carries an HMAC-SHA256 signature over the raw JSON body in theX-ThunderPhone-Signature header. The signing key is the
endpoint’s secret (or your org-level webhook secret for legacy
deliveries).
Steps
- Read the raw request body before any parsing.
- Compute
hmac_sha256(secret, body).hexdigest(). - Compare in constant time to the
X-ThunderPhone-Signatureheader.
Delivery semantics
Retries
Retries
ThunderPhone retries on any non-2xx response with exponential backoff
for up to 24 hours. After 24 hours of failures, the endpoint is
marked
status="failing" in
webhook endpoints. Return 2xx as soon as
the payload is durably accepted; process asynchronously.Ordering
Ordering
Delivery ordering is best-effort. In practice we deliver in the
order events are emitted, but retries can reorder on failure.
Always dedup and reconcile by
call_id / object id.Duplicates
Duplicates
Webhooks are at-least-once. A duplicate
call.complete is rare but
possible — be idempotent on call_id.Timeouts
Timeouts
Non-blocking events (e.g.
call.complete) have a 30 s timeout.
Blocking events that drive live call behavior
(e.g. call.incoming) are expected to
respond within 2 s — longer responses delay the call.Source IPs
Source IPs
Outbound webhooks originate from ThunderPhone’s Cloud Run IP range.
If your firewall requires an allowlist, contact support and we’ll
share the current ranges.
Choosing between legacy and endpoint-based webhooks
| Feature | Legacy (/v1/webhook) | Endpoints (/v1/developer/webhook-endpoints) |
|---|---|---|
| Number of URLs | 1 per org | Many per org |
| Event filter | All events | Per-endpoint |
| Secret rotation | Replaces single secret | Per-endpoint secret |
| Disable without delete | — | status=disabled |
| Status visibility | — | active / disabled / failing |
| Best for | Quick prototypes | Production |
Related
Events catalog
All event types and their payloads.
Webhook endpoints
Manage multiple endpoints, event filters, and secrets.
call.incoming
The blocking request your server must answer to route inbound calls.
call.complete
Post-call payload with transcript, recording, and metrics.