Webhooks

One application can provide another application with real-time updates via a webhook (also referred to as a web callback or HTTP push API). A webhook delivers data to other applications as it happens, meaning you get data immediately. In the past, APIs would typically need to poll for data very frequently to get it promptly. This makes webhooks much more efficient for both provider and consumer. The only drawback to webhooks is the difficulty of initially setting them up - this tutorial walks through how to consume webhooks.

Webhooks are sometimes referred to as “Reverse APIs,” as they give you what amounts to an API spec, and you must design an API for the webhook to use. The webhook will make an HTTP request to your app (typically a POST), and you will then be charged with interpreting it.

Telnyx can send webhook events that notify your application any time an event happens on your account. This is especially useful for events like receiving an SMS or MMS message and getting feedback on Call Control events. The messaging webhooks section goes into a bit more detail on how SMS and MMS webhooks work.

HTTP and HTTPS

  • Unsecure (HTTP) URLs are allowed for webhooks.
  • If HTTPS (TLS) is used, the certificate will be validated.

Event Type Naming

Where possible, events map to the C(R)UD operations, but this is certainly not always be applicable.

  • resource.created
  • resource.updated
  • resource.deleted

When the CRUD operations are not applicable, events will be named with past tense verbs.

  • message.created
  • message.deleted
  • message.delivered
  • message.received
  • porting sub request.ported
  • porting sub request.closed

Structure

The top-level structure of the webhook will vary by product but not by type of event received. For example, Call Control webhooks have a different top-level structure than Messaging webhooks however the webhook structure across all Call Control commands is consistent. The payload of the webhook contains the most valuable information for your application.

Call Control Top-Level Structure

Copy
Copied
{
  "call_leg_id": "e97d8d4c-1a25-11cd-bc67-02620a0f6d42",
  "call_session_id": "e97da4f0-1a25-11bd-909f-02620a0f6d642",
  "event_timestamp": "2019-11-10T22:25:27.521992Z",
  "metadata": {
    "attempt": 1,
    "delivered_to": "https://www.example.com/callback",
    "event": {
      "event_type": "call.initiated",
      "id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
      "occurred_at": "2019-11-10T22:25:27.521992Z",
      "payload": {
        ...
      },
      "record_type": "event"
    },
    "status": "delivered"
  },
  "name": "call.initiated",
  "organization_id": null,
  "type": "webhook",
  "user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}

Note: After pasting the above content, Kindly check and remove any new line added

FIELD NAME DESCRIPTION
call_leg_id ID that is unique to the call and can be used to correlate webhook events.
call_session_id ID that is unique to the call session and can be used to correlate webhook events.
event_timestamp ISO 8601 datetime of when the event occurred.
attempt The number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx HTTP 200 OK on receipt of the webhook.
delivered_to URL that the webhook was sent to.
event_type The type of event being delivered which also determines the structure of the payload.
id Unique ID of the event.
occurred_at ISO 8601 datetime of when the event occurred.
record_type Will always be event.
status Status of the webhook for debugging purposes.
name Event name.
organization_id ID of the organization.

Messaging Top-Level Structure

Copy
Copied
{
"data": {
   "event_type": "message.finalized",
   "id": "4ef8c3a6-4195-4389-b3a6-38e3cb9eb4ae",
   "occurred_at": "2019-11-10T22:30:14.148+00:00",
   "payload": {
     ...
   },
   "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://www.example.com/messaging"
  }
}

Note: After pasting the above content, Kindly check and remove any new line added

FIELD NAME DESCRIPTION
event_type The type of event being delivered which also determines the structure of the payload.
id Unique ID of the event.
occurred_at ISO 8601 datetime of when the event occurred.
payload The main data for the event. The structure is denoted by the event_type.
record_type Will always be event.
attempt The number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx a 2xx HTTP status code within 2s of receipt of the webhook.
delivered_to URL that the webhook was sent to.

Full Call Control Example

Copy
Copied
{
  "call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
  "call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
  "event_timestamp": "2019-11-10T22:26:27.521992Z",
  "metadata": {
    "attempt": 1,
    "delivered_to": "https://www.example.com/callback",
    "event": {
      "event_type": "call.answered",
      "id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
      "occurred_at": "2019-11-10T22:26:27.521992Z",
      "payload": {
        "call_control_id": "v2:F5_vIJVqrosogeY_2L_JhCEHd2Dh-x4xz7tROTbh34tg6Zsk4JJc-w",
        "call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
        "call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
        "client_state": null,
        "connection_id": "7267xxxxxxxxxxxxxx",
        "from": "+8005550199",
        "start_time": "2019-11-10T22:26:26.521992Z",
        "to": "+8005550100",
      },
      "record_type": "event"
    },
    "status": "delivered"
  },
  "name": "call.answered",
  "organization_id": null,
  "type": "webhook",
  "user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}

Note: After pasting the above content, Kindly check and remove any new line added

Responding to a webhook

To acknowledge receipt of a webhook, your endpoint should return a 2xx HTTP status code. Any other information returned in the request headers or request body is ignored. All response codes outside this range, including 3xx codes, will indicate to Telnyx that you did not receive the webhook. URL redirection or a "Not Modified" response will be treated as a failure.

Retries

Webhooks will be retried to each of the supplied URLs if your application does not respond in 2000 milliseconds.

Best Practices

If your webhook script performs complex logic or makes network calls, it's possible the script would timeout before Telnyx sees its complete execution. For that reason, you may want to have your webhook endpoint immediately acknowledge receipt by returning a 2xx HTTP status code, and then perform the rest of its duties.

Webhook endpoints may occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events. Additionally, we recommend verifying webhook signatures to confirm that received events are being sent from Telnyx.

Webhook Signing

Telnyx signs the webhook events it sends to clients so that the authenticity of the request can be verified. Webhook signing in API V2 uses public key encryption. Telnyx stores a public-private key pair and uses the private key to sign the payload. The public key is available to you so that you can verify the request.

The public key can be viewed in the Mission Control Portal.

The signature for the payload is calculated by building a string that is the combination of the timestamp of when the request was initiated, the pipe | character and the JSON payload. The signature is then Base64 encoded.

Copy
Copied
Base64.encode64("#{timestamp}|#{payload}")

The signature (Base64 encoded) and the timestamp (in Unix format) are assigned to the request headers telnyx-signature-ed25519 and telnyx-timestamp respectively.

You can then use cryptographic libraries in your language of choice to verify the signature using the public key. For examples, please see: