- product:numbers - product:voice - product:messaging - product:fax - sdk:compatibility - language:nodejs ## 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](/rest/compatibility-api/endpoints/create-a-call) or [Send a Message](/rest/compatibility-api/endpoints/create-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](/guides/how-to-test-webhooks-with-ngrok)! :::info What do I do with a webhook? Some webhooks require 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 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](/guides/creating-and-using-cxml-applications) 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](/rest/compatibility-api/endpoints/create-a-call) through the API or by setting the statusCallback attribute on the [](/compatibility-api/cxml/voice/number-noun) 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](/guides/signalwire-status-callbacks#voice-status-callbacks) 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 its 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](/guides/signalwire-status-callbacks#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](/guides/creating-and-using-cxml-applications) 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 ### 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](/rest/compatibility-api/endpoints/create-message) through the API or by setting the statusCallback attribute on the [](/compatibility-api/cxml/messaging/message#message-status) element with [XML](pathname:///compatibility-api/cxml/messaging/message#message-status). Read in-depth about SMS status callbacks [here](/guides/signalwire-status-callbacks#sms-status-callbacks) to learn all of their possible parameters and statuses and see a working code example! :::info 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 carriers 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](/guides/what-is-a-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. Click on the phone number to be set up and then click on **Edit Settings**. In the Edit Settings page, the number can be given a name and set up **Voice/Fax & Messaging** setting. 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. :::danger 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](/compatibility-api), select **LaML Webhooks** for **When a Call Comes In**. If you are using the [RELAY Realtime API](/sdks/reference/realtime-sdk), 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 (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 Dashboards [API Credentials](https://my.signalwire.com?page=credentials) with the validateRequest method: js 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 applications logic in the truth case and return unauthorized for the false case.