# Setting up your first webhook

{% stepper %}
{% step %}

### Create your webhook endpoint

You will need to create an endpoint on your server to receive event notifications. Mobile Text Alerts will send HTTP `POST` requests to this endpoint and expects it to return a response with a <mark style="color:green;">`200`</mark> HTTP status code. If other status codes are returned, this is treated as a failed request. You can configure [email alerts when Mobile Text Alerts receives these failed requests](/getting-started/setting-up-webhooks.md#webhook-failure-email-alerts) when registering your webhook.

{% hint style="warning" %}
Use a secure endpoint (HTTPS not HTTP). This eliminates risks by encrypting the entire request while in transit.
{% endhint %}

Once configured and registered, this endpoint will receive event payloads from Mobile Text Alerts. Request bodies are JSON. You can view the [expected event payloads for each event type here](/tutorials/webhooks.md#webhooks-event-payloads).
{% endstep %}

{% step %}

### Get the URL of this endpoint

Mobile Text Alerts will send HTTP `POST` requests to the URL of your server endpoint.

A `url` must be specified for each webhook event type that you register. You can configure multiple event types to be sent to the same destination URL endpoint. This would require multiple calls to the [Register Webhook endpoint](/api-reference/webhooks.md#register-webhook) for each event type you want to receive, each with the same `url` field.

*Example URL:*

```
https://www.yoursite.com/app/hooks
```

{% endstep %}

{% step %}

### Create a secret value

When registering a webhook, you are required to provide a `secret` value to Mobile Text Alerts. This is typically a 128-character hexadecimal `string`. This is used to validate that the requests you receive are from Mobile Text Alerts.

{% hint style="info" %}
**Secret Best Practices:**

* Store your `secret` as an environment variable or in a secrets manager (e.g. AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager).
* Never commit the `secret` to source control.
* Never log the `secret` or include it in error responses.
  {% endhint %}

*Example secret generation:*

{% tabs %}
{% tab title="Unix / macOS" %}

```bash
openssl rand -hex 64
```

{% endtab %}

{% tab title="Python" %}

```python
python3 -c "import secrets; print(secrets.token_hex(64))"
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
```

{% endtab %}
{% endtabs %}

Mobile Text Alerts will generate a [HMAC-SHA256](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hmacsha256) signature using the request body and the `secret`. The signature is set as an `X-Signature` header in the request Mobile Text Alerts sends to your endpoint.

Your webhook listener should validate that the request is from Mobile Text Alerts by generating the [HMAC-SHA256](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hmacsha256) signature of the request body and comparing it to the value of the `X-Signature` header.

{% hint style="warning" %}
Mobile Text Alerts provides the `X-Signature` header signature as a robust validation mechanism for your security but does not enforce verification of your endpoint listener. This makes client-side enforcement a developer responsibility. See [Webhook Signature Verification](/tutorials/webhooks/webhook-signature-verification.md) to learn more.
{% endhint %}
{% endstep %}

{% step %}

### Register your webhook

You will need to register your webhook endpoint for each event type you want to receive. To do this, call the [Register Webhook <mark style="color:blue;">`/webhooks`</mark> endpoint](/api-reference/webhooks.md#register-webhook) of the Mobile Text Alerts API.

**Required fields:**

* `event: string` - Choose which [event type](/getting-started/setting-up-webhooks.md#event-types) you want to receive event notifications for. This can be one of the following: `message-reply`, `delivery-status`, `message-send`, or `number-opt-in`.
* `url: string` - This is your hosted URL endpoint (created in step 2 above) that Mobile Text Alerts will make a `POST` request to when events trigger.
* `secret: string` - This is a shared secret between your organization and Mobile Text Alerts (created in step 3 above).

[Click here to see all fields.](/api-reference/webhooks.md#register-webhook)

*Example request:*

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location 'https://api.mobile-text-alerts.com/v3/webhooks' \
 --header 'Authorization: Bearer <APIKey>' \
 --header 'Content-Type: application/json' \
 --data-raw '{
    "event": "delivery-status",
    "url": "https://www.example.com/app/hooks",
    "secret": "abc123-abc2-cde1-1234-xyz123456",
    "alertEmail": "alert@example.com",
    "sendAlertEmail": true
}'
```

{% endtab %}

{% tab title="Node.js" %}
Requirements: Node.js `18+` (native `fetch`) and an `MTA_API_KEY` environment variable.

```js
async function main() {
  const response = await fetch('https://api.mobile-text-alerts.com/v3/webhooks', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.MTA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      event: 'delivery-status',
      url: 'https://www.example.com/app/hooks',
      secret: 'abc123-abc2-cde1-1234-xyz123456',
      alertEmail: 'alert@example.com',
      sendAlertEmail: true
    })
  });

  const data = await response.json();
  console.log(data);
}

main().catch((err) => {
  console.error('Request failed:', err);
  process.exitCode = 1;
});
```

{% endtab %}

{% tab title="Python" %}
Requirements: `pip install requests` and an `MTA_API_KEY` environment variable.

```python
import requests
import os

response = requests.post(
    'https://api.mobile-text-alerts.com/v3/webhooks',
    headers={
        'Authorization': f'Bearer {os.getenv("MTA_API_KEY")}',
        'Content-Type': 'application/json'
    },
    json={
        'event': 'delivery-status',
        'url': 'https://www.example.com/app/hooks',
        'secret': 'abc123-abc2-cde1-1234-xyz123456',
        'alertEmail': 'alert@example.com',
        'sendAlertEmail': True
    }
    )
print(response.json())
```

{% endtab %}
{% endtabs %}

*Example successful* <mark style="color:green;">`200`</mark> *response:*

*(Note: The response contains the `id` field which is the `webhookId` used in requests to update/delete this webhook.)*

```json
{
  "message": "Webhook 11 created successfully.",
  "data": {
    "id": 11,
    "event": "delivery-status",
    "url": "https://www.example.com/app/hooks",
    "alertEmail": "alert@example.com",
    "sendAlertEmail": true,
    "skipErrors": false,
    "skipErrorCodes": [],
    "retryOnError": true,
    "maxThroughputPerMinute": 600,
    "createdAt": "2022-04-18T05:00:00.000Z"
  }
}
```

{% endstep %}

{% step %}

### Receive event payloads to your URL

Once your webhook is registered, you will start receiving the [event payloads](/tutorials/webhooks.md#webhooks-event-payloads) when that event is triggered.&#x20;

Your server can parse this JSON and use this payload data however you configure your server.&#x20;

{% hint style="warning" %}
For production environments your listener server should always [verify signatures](/tutorials/webhooks/webhook-signature-verification.md) of requests to confirm they are from Mobile Text Alerts.
{% endhint %}

Your webhook configuration can be updated or deleted after registration by calling the [Update Webhook endpoint](/api-reference/webhooks.md#update-a-webhook) or [Delete Webhook endpoint](/api-reference/webhooks.md#delete-a-webhook). For these requests use the `{webhookId}` returned when you first registered the webhook.
{% endstep %}
{% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.mobile-text-alerts.com/tutorials/webhooks/setting-up-your-first-webhook.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
