Overview
Voice API webhooks are HTTP callbacks that notify your application in real time when events occur during a call — a call is initiated, audio playback finishes, a recording is saved, and so on. Your application receives a JSON payload for each event and can respond with call control commands to drive the call flow.Webhook delivery
When an event occurs on a call, Telnyx delivers the webhook to your configured URL. If the primary URL fails, the webhook is sent to the failover URL (if configured). For details on retry logic, signature verification, and general webhook behavior, see Webhook Fundamentals.Configuration
Webhooks can be configured at three levels:- Connection webhook config — default webhook URL and settings tied to a Voice API connection in Mission Control.
- Custom webhook config — per-command overrides. Pass
webhook_urlandwebhook_url_methodin any call control command to route that command’s webhooks to a different endpoint. - Events webhook config — advanced configuration that routes specific event types to different URLs.
Configuration parameters
| Parameter | Type | Description |
|---|---|---|
webhook_event_url | String | Primary destination for webhook delivery |
webhook_event_failover_url | String | Secondary URL used when the primary fails |
webhook_api_version | String | Webhook format version ("1" or "2") |
webhook_timeout_secs | Integer | Seconds to wait before timing out (0–30, default: null) |
HTTP methods and headers
Methods
- Webhooks use the
POSTmethod by default. Passwebhook_url_methodasGETin a call control command to receive that command’s webhook payloads as URL query parameters instead of a JSON body.
Headers
Every webhook request includes:| Header | Description |
|---|---|
Content-Type | application/json (POST requests) |
User-Agent | telnyx-webhooks |
Telnyx-Signature-Ed25519 | ED25519 signature for verification |
Telnyx-Timestamp | Unix timestamp when the webhook was generated |
Webhook payload structure
All Voice API webhooks share a common envelope. Below is an examplecall.initiated payload:
Common fields
| Field | Location | Description |
|---|---|---|
record_type | data | Always "event" |
event_type | data | Event name (see Event types below) |
id | data | Unique identifier for this webhook event |
occurred_at | data | ISO 8601 timestamp of when the event occurred |
call_control_id | data.payload | ID used to issue call control commands for this call leg |
call_leg_id | data.payload | Unique ID for this call leg — use to correlate webhooks |
call_session_id | data.payload | Shared ID across related call legs (e.g., both sides of a transfer) |
connection_id | data.payload | Voice API connection used for the call |
client_state | data.payload | Base64-encoded state passed through from a previous command |
from | data.payload | Calling party number or SIP URI |
to | data.payload | Called party number or SIP URI |
attempt | meta | Delivery attempt number (increments on retries) |
delivered_to | meta | URL the webhook was sent to |
Event types
The following event types are fired by the Voice API. Each event type appears in theevent_type field of the webhook payload.
Call state
| Event | Description | Triggered by |
|---|---|---|
call.initiated | A new call leg has been created | Dial, Transfer, or an inbound call |
call.answered | The call has been answered | Answer, or remote party picks up |
call.hangup | The call has ended | Hangup, Reject, or remote hangup |
call.bridged | Two call legs have been connected | Bridge, Transfer |
Audio playback
| Event | Description | Triggered by |
|---|---|---|
call.playback.started | Audio file playback has started | Play audio, Gather using audio |
call.playback.ended | Audio file playback has finished | Playback completes or Stop playback |
call.speak.started | Text-to-speech playback has started | Speak text |
call.speak.ended | Text-to-speech playback has finished | Speak completes or Stop playback |
DTMF and gather
| Event | Description | Triggered by |
|---|---|---|
call.dtmf.received | A DTMF digit was received | Caller presses keypad during Gather using audio or Gather using speak |
call.gather.ended | A gather operation has completed | Gather finishes (timeout, max digits, or terminating key) |
Recording
| Event | Description | Triggered by |
|---|---|---|
call.recording.saved | A call recording has been saved | Recording stop, or call ends while recording |
Answering machine detection (AMD)
| Event | Description | Triggered by |
|---|---|---|
call.machine.detection.ended | Standard AMD has determined human vs. machine | Dial with answering_machine_detection enabled |
call.machine.greeting.ended | Machine greeting has finished (beep detected) | Dial with answering_machine_detection set to detect greeting end |
call.machine.premium.detection.ended | Premium AMD has determined human vs. machine | Dial with premium AMD enabled |
call.machine.premium.greeting.ended | Premium AMD greeting/beep detection completed | Dial with premium AMD greeting detection |
Media forking
| Event | Description | Triggered by |
|---|---|---|
call.fork.started | Media forking has started | Forking start |
call.fork.stopped | Media forking has stopped | Forking stop, or call ends |
Queue
| Event | Description | Triggered by |
|---|---|---|
call.enqueued | Call was placed in a queue | Enqueue |
call.dequeued | Call was removed from a queue | Dequeue command or call ends |
Transcription
| Event | Description | Triggered by |
|---|---|---|
call.transcription | Real-time transcription data received | Transcription start |
Streaming
| Event | Description | Triggered by |
|---|---|---|
streaming.started | Media streaming has started | Streaming start |
streaming.stopped | Media streaming has stopped | Streaming stop, or call ends |
Response codes
Your webhook endpoint’s HTTP response determines whether delivery is considered successful:| Code | Meaning | Behavior |
|---|---|---|
| 2xx | Success | Webhook acknowledged |
| 3xx | Redirect | Followed (up to 3 redirects) |
| 408, 429 | Timeout / Rate limited | Retried |
| Other 4xx | Client error | Not retried |
| 5xx | Server error | Retried |
Debugging deliveries
Use the Webhook Deliveries API to inspect delivery history for your account. You can filter by status, event type, and time range — useful for diagnosing missed or failed webhooks.Best practices
- Return 2xx immediately — acknowledge receipt within a few seconds, then process asynchronously.
- Implement idempotency — webhooks may be delivered more than once. Use the event
idto deduplicate. - Verify signatures — validate the
Telnyx-Signature-Ed25519header to confirm webhook authenticity. See Webhook signing. - Use
command_id— include acommand_idin your call control commands to prevent duplicate command processing. Commands with duplicate IDs within 60 seconds are ignored. - Monitor failures — track failed webhook deliveries and configure a failover URL for critical applications.