Skip to main content
When an inbound phone call reaches a number without an assigned agent, or a web widget session starts on a publishable key in mode="webhook", ThunderPhone sends a blocking telephony.incoming / web.incoming request to your legacy webhook URL and waits up to 10 seconds for a configuration response. Use this exchange to dynamically choose a prompt, voice, and tools per call — see the dynamic call configuration guide for the end-to-end pattern.
Subscribed webhook endpoints also receive telephony.incoming / web.incoming — for every inbound call and web session, agent-configured or not — but those deliveries are fire-and-forget notifications with an event_id, never blocking. Only the legacy single-URL webhook carries the configuration exchange on this page. Endpoint notification shapes are in the events catalog.
The blocking exchange has no fallback: if your handler returns a non-2xx status, times out, or returns a config that fails validation, the call is rejected (the phone call does not connect; the widget session request fails with 502/422). Answer fast — the caller is hearing ringback while you decide.

Request payload

For phone calls (telephony.incoming):
For web widget sessions (web.incoming) the data identifies the embedding page instead of phone numbers:
Webhook-mode widgets deliver this request to the publishable key’s own webhook_url when one is set, falling back to the org-level webhook URL. Either way it is signed with the org webhook secret.

Response schema

Return a JSON object describing the agent configuration for this call. prompt and voice are required; everything else is optional.
Unknown top-level keys are silently ignored — a typo’d field name doesn’t reject the config, it just doesn’t apply. Speak-order and max_hold_seconds are not accepted here; they are only configurable on the Agent itself.
Because prompt and voice are required, returning {} or any response that fails validation rejects the call with 422 — there is no static-agent fallback on this path (a number or key in webhook mode has no assigned agent).

Response size limit

Configuration responses are limited to 5 MiB. If a handler returns a larger response, including with a 2xx status, ThunderPhone reports that the response exceeded the limit and rejects the call or widget session. Keep the response to the fields needed for call setup; host large data behind function tools or another service instead of embedding it in the configuration.

Example handler


Response with function tools

Attach tools so the AI can call your APIs mid-conversation:
Tool-endpoint requests are signed with the same org webhook secret that signed this exchange. See Function Tools for the exact shape and the signed request format.

Product tier cheat sheet


telephony.complete / web.complete

The non-blocking end-of-call event.

Function Tools

Full JSON schema for tools[] and the signed endpoint contract.

Webhook endpoints

Subscribe multiple URLs to telephony.incoming / web.incoming.

Dynamic call configuration

Patterns for per-caller prompts, tools, and A/B tests.