Skip to main content

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:
  1. Connection webhook config — default webhook URL and settings tied to a Voice API connection in Mission Control.
  2. Custom webhook config — per-command overrides. Pass webhook_url and webhook_url_method in any call control command to route that command’s webhooks to a different endpoint.
  3. Events webhook config — advanced configuration that routes specific event types to different URLs.
You can also manage webhook settings programmatically via the Call Control Applications API. Use Create or Update to set webhook URLs, failover URLs, API version, and timeout values on a connection.

Configuration parameters

ParameterTypeDescription
webhook_event_urlStringPrimary destination for webhook delivery
webhook_event_failover_urlStringSecondary URL used when the primary fails
webhook_api_versionStringWebhook format version ("1" or "2")
webhook_timeout_secsIntegerSeconds to wait before timing out (0–30, default: null)

HTTP methods and headers

Methods

  • Webhooks use the POST method by default. Pass webhook_url_method as GET in 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:
HeaderDescription
Content-Typeapplication/json (POST requests)
User-Agenttelnyx-webhooks
Telnyx-Signature-Ed25519ED25519 signature for verification
Telnyx-TimestampUnix timestamp when the webhook was generated

Webhook payload structure

All Voice API webhooks share a common envelope. Below is an example call.initiated payload:
{
  "data": {
    "record_type": "event",
    "event_type": "call.initiated",
    "id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
    "occurred_at": "2018-02-02T22:25:27.521992Z",
    "payload": {
      "call_control_id": "d14dbcee-880b-11eb-8204-02420a0f7568",
      "connection_id": "7267xxxxxxxxxxxxxx",
      "call_leg_id": "d14dbcee-880b-11eb-8204-02420a0f7568",
      "call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
      "client_state": "aGF2ZSBhIG5pY2UgZGF5ID1d",
      "from": "+12025550133",
      "to": "+12025550131",
      "direction": "incoming",
      "state": "parked"
    }
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/webhooks"
  }
}

Common fields

FieldLocationDescription
record_typedataAlways "event"
event_typedataEvent name (see Event types below)
iddataUnique identifier for this webhook event
occurred_atdataISO 8601 timestamp of when the event occurred
call_control_iddata.payloadID used to issue call control commands for this call leg
call_leg_iddata.payloadUnique ID for this call leg — use to correlate webhooks
call_session_iddata.payloadShared ID across related call legs (e.g., both sides of a transfer)
connection_iddata.payloadVoice API connection used for the call
client_statedata.payloadBase64-encoded state passed through from a previous command
fromdata.payloadCalling party number or SIP URI
todata.payloadCalled party number or SIP URI
attemptmetaDelivery attempt number (increments on retries)
delivered_tometaURL the webhook was sent to

Event types

The following event types are fired by the Voice API. Each event type appears in the event_type field of the webhook payload.

Call state

EventDescriptionTriggered by
call.initiatedA new call leg has been createdDial, Transfer, or an inbound call
call.answeredThe call has been answeredAnswer, or remote party picks up
call.hangupThe call has endedHangup, Reject, or remote hangup
call.bridgedTwo call legs have been connectedBridge, Transfer

Audio playback

EventDescriptionTriggered by
call.playback.startedAudio file playback has startedPlay audio, Gather using audio
call.playback.endedAudio file playback has finishedPlayback completes or Stop playback
call.speak.startedText-to-speech playback has startedSpeak text
call.speak.endedText-to-speech playback has finishedSpeak completes or Stop playback

DTMF and gather

EventDescriptionTriggered by
call.dtmf.receivedA DTMF digit was receivedCaller presses keypad during Gather using audio or Gather using speak
call.gather.endedA gather operation has completedGather finishes (timeout, max digits, or terminating key)

Recording

EventDescriptionTriggered by
call.recording.savedA call recording has been savedRecording stop, or call ends while recording

Answering machine detection (AMD)

EventDescriptionTriggered by
call.machine.detection.endedStandard AMD has determined human vs. machineDial with answering_machine_detection enabled
call.machine.greeting.endedMachine greeting has finished (beep detected)Dial with answering_machine_detection set to detect greeting end
call.machine.premium.detection.endedPremium AMD has determined human vs. machineDial with premium AMD enabled
call.machine.premium.greeting.endedPremium AMD greeting/beep detection completedDial with premium AMD greeting detection

Media forking

EventDescriptionTriggered by
call.fork.startedMedia forking has startedForking start
call.fork.stoppedMedia forking has stoppedForking stop, or call ends

Queue

EventDescriptionTriggered by
call.enqueuedCall was placed in a queueEnqueue
call.dequeuedCall was removed from a queueDequeue command or call ends

Transcription

EventDescriptionTriggered by
call.transcriptionReal-time transcription data receivedTranscription start

Streaming

EventDescriptionTriggered by
streaming.startedMedia streaming has startedStreaming start
streaming.stoppedMedia streaming has stoppedStreaming stop, or call ends

Response codes

Your webhook endpoint’s HTTP response determines whether delivery is considered successful:
CodeMeaningBehavior
2xxSuccessWebhook acknowledged
3xxRedirectFollowed (up to 3 redirects)
408, 429Timeout / Rate limitedRetried
Other 4xxClient errorNot retried
5xxServer errorRetried

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.
# List failed voice webhook deliveries from the last hour
curl -X GET "https://api.telnyx.com/v2/webhook_deliveries?filter[status][eq]=failed&filter[event_type]=call.initiated" \
  -H "Authorization: Bearer YOUR_API_KEY"
Each delivery record includes the full webhook payload, HTTP status codes, and attempt-level details (request/response headers and bodies). See Get a webhook delivery for the full response schema.

Best practices

  1. Return 2xx immediately — acknowledge receipt within a few seconds, then process asynchronously.
  2. Implement idempotency — webhooks may be delivered more than once. Use the event id to deduplicate.
  3. Verify signatures — validate the Telnyx-Signature-Ed25519 header to confirm webhook authenticity. See Webhook signing.
  4. Use command_id — include a command_id in your call control commands to prevent duplicate command processing. Commands with duplicate IDs within 60 seconds are ignored.
  5. Monitor failures — track failed webhook deliveries and configure a failover URL for critical applications.