Skip to main content

Webhooks Overview

What is a Webhook?

The SignalWire Compatibility APIs allow you to easily send/receive HTTP requests from/to the SignalWire servers. For example, you can easily make an HTTP request to SignalWire in order to Create a Call or Send a Message. However, if you are using SignalWire to handle inbound calls or inbound messages, you will need to use a webhook!

A webhook is an HTTP(S) request sent to your web application when a key event has occurred, such as an inbound call, inbound message, or a status change. This allows SignalWire to query your web application in order for instructions on what to do next.

For example, you might use a webhook to handle an inbound call by reading the instructions in your webhook to play an IVR, route the customer to the right department, and connect them with an agent. You could also use a webhook as a status callback where each status change of a message is sent to your web application which might store some instructions for handling emergent errors.

To learn how to use ngrok for local testing, check out our guide!

What do I do with a webhook?

Some webhooks require <Response> from your web application, such as the earlier example of the inbound call being routed through an IVR in your application. In this instance, your web application MUST send valid XML to the webhook request, EVEN if the XML response is just an empty <Response> tag. If you do not return valid XML, you will get a document parse error and inconsistent results.

Other webhooks do not require a response, such as the status callback example above. This webhook request only requires an HTTP status code of 200 OK, meaning that the request was successful.

Voice Webhooks

Inbound Voice Call

You will receive an incoming voice call webhook request when you have your webhook configured to handle inbound calls to a number. You can use a webhook that points to your web application hosted on a server or ssh tunnel, or you could also use XML Bins as webhooks for serverless code!

Status Callback

When one of your SignalWire phone numbers receives a call or is used to place an outgoing call, you can have asynchronous HTTP requests sent to your server that tell you about the status changes and the call details. You can do this by setting the StatusCallback parameter when placing an outbound call through the API or by setting the statusCallback attribute on the <Number> element with SignalWire Compatibility XML.

SignalWire will send you a status callback when the call is completed unless directed otherwise; you can use the events initiated, ringing, answered, and completed in the StatusCallbackEvent parameter in order to get updates when each of those statuses is reached.

Read in-depth about voice status callbacks here to see all of the possible parameters & statuses as well as a working code example!

Recording Status Callback

If you are recording your voice calls, you may notice that the recording is not always instantly available due to the need for some audio processing to transcode it into a compressed audio format after the voice call is complete. If you would like to be notified when it's done, you can use recording status callbacks!

There are a few different statuses your recording could have; in-progress, completed, absent, or failed. When the voice recording is complete, a request will be sent with the completed status and the audio file link within the 'RecordingUrl' parameter.

Read in-depth about recording status callbacks to see all of the possible parameters and statuses as well as a working code example!

SMS Webhooks

Inbound Message

You will receive an incoming message webhook request when you have your webhook configured to handle inbound messages to a number. You can use a webhook that points to your web application hosted on a server or ssh tunnel, or you could also use XML Bins as webhooks for serverless code!

It is also possible to receive an incoming text message, and not send a reply message back to the user. To do that, you can simply use a LaML Bin with an empty response tag for handling inbound messages, as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
</Response>

Status Callbacks

Like status callbacks for voice, SMS status callbacks are a way to have updates on the delivery of your messages sent directly to your server! Each time the message status changes (e.g., from queued to sending to sent to delivered), SignalWire will send an update to the URL that you have designated.

You can do this by setting the StatusCallback parameter when sending an outbound message through the API or by setting the statusCallback attribute on the <Message> element with XML.

Read in-depth about SMS status callbacks here to learn all of their possible parameters and statuses and see a working code example!

"Sent" vs "Delivered"

SignalWire can’t and won’t show a message as Delivered unless we can 100% confirm delivery to the end network by getting a Delivery Receipt (DLR) from the receiving carrier. A status of Sent means that the message left SignalWire successfully and reached our downstream peer. Once we receive the Delivery Receipt indicating that the message entered the end carrier's network, it switches to Delivered.

If you see a message with a status of Delivered that did not reach the end handset, feel free to open a support ticket with the message SID for us to escalate the example to our carrier partners to find out why the MNOs (Verizon, AT&T, T-Mobile, etc) marked it as Delivered.

Some carriers may send delayed DLRs, and others may not send DLRs at all. Providers do not currently allow for any DLRs for MMS, so you will only ever see the status Sent.

How to Configure Your Webhook to a SignalWire Number

To access the number settings and configure the webhooks in the SignalWire Space, click on Phone Numbers and find the number to set up.

A screenshot of the Phone Numbers tab of a SignalWire Space showing a list of phone numbers.

Click on the phone number to be set up and then click on Edit Settings.

A screenshot of the Phone Numbers tab. A number has been selected, and the number details are visible. There are options to Edit Settings, Transfer Number, Set E911 Address, and Release Number.

In the Edit Settings page, the number can be given a name and set up Voice/Fax & Messaging setting.

A screenshot of the Edit Settings page for the selected phone number.

Navigate to either the Voice & Fax section or the Messaging section depending on your use case, as you will have to set different webhooks for each.

Voice vs Fax

If you set your phone number to handle incoming calls using Fax, you will NOT be able to also use it for voice. The reverse is also true! You can only use a phone number for voice OR fax, not both.

If you use the SignalWire Compatibility APIs, select LaML Webhooks for When a Call Comes In. If you are using the RELAY Realtime API, select Relay for When a Call Comes In. The other options are all third-party integrations you can choose to use for different use cases!

GET and POST are two different types of HTTP methods. GET is used for requesting something from a resource, whereas POST is used to send data to a server. If you were using a webhook that pointed towards your web application for handling inbound calls, you would use a POST request. If you were using an XML Bin to <Say> (text to speech) a quick message for your customers to listen to when calling your number, you would use GET.

How to Verify Webhooks

To verify webhooks that originated from SignalWire, SignalWire signs its requests with a digital HMAC security key. You can verify that the security key matches the key documented in your Dashboard's API Credentials with the validateRequest method:

import { RestClient } from "@signalwire/compatibility-api";

app.post("/mywebhook", (req, res) => {
const valid = RestClient.validateRequest(
<--Signing Key copied from your credentials page-->,
req.headers["x-signalwire-signature"],
"https://example.ngrok.io/mywebhook",
req.body
);
});

This method respond with a boolean value. You can continue your application's logic in the truth case and return unauthorized for the false case.