---
"@context": https://schema.org
"@type": TechArticle
"@id": https://www.twilio.com/docs/usage/webhooks/webhook-rules#article
headline: Configure webhook rules
description: Create Webhook Rules that match webhook URLs and apply Webhook Settings to them, including splitting traffic between two settings.
url: https://www.twilio.com/docs/usage/webhooks/webhook-rules
inLanguage: en
dateModified: 2026-09-07T13:32:03.000Z
author:
  "@type": Organization
  name: Twilio Developer Education Team
publisher:
  "@type": Organization
  name: Twilio
---

# Configure webhook rules

> \[!IMPORTANT]
>
> The Webhooks configuration API, including the Webhook Settings and Webhook Rules resources, has been released as a Public Beta product. Before Twilio declares this product as Generally Available, the information contained in this document might change. Twilio might implement additional features or change others. No [Twilio SLA][sla] covers Public Beta products.

[sla]: https://help.twilio.com/articles/115002413087-Twilio-Beta-product-support

A Webhook Rule matches a webhook's destination URL and names the [Webhook Setting][settings] that Twilio applies to it. Any webhook configuration needs a Rule. Without one, Twilio sends the webhook with no Setting applied.

## Rule properties

Every Rule has a `matchType` that determines how it matches URLs and which other fields it needs.

| Property          | Type   | Necessity                   | Description                                                             |
| ----------------- | ------ | --------------------------- | ----------------------------------------------------------------------- |
| `id`              | string | read-only                   | The Rule's identifier, in the form `webhooks_rule_` plus 26 characters. |
| `friendlyName`    | string | optional                    | A name to identify the Rule. Up to 255 characters. Defaults to blank.   |
| `description`     | string | optional                    | What the Rule is for. Up to 1024 characters.                            |
| [`matchType`][mt] | enum   | required                    | `EXACT_MATCH`, `PREFIX_MATCH`, or `DEFAULT`.                            |
| `value`           | string | required for `EXACT_MATCH`  | The exact URL to match. Up to 2048 characters.                          |
| `prefix`          | string | required for `PREFIX_MATCH` | The URL prefix to match. Up to 2048 characters.                         |
| [`settings`][st]  | array  | required                    | One or two Settings with the percentage of traffic each receives.       |
| `createdAt`       | string | read-only                   | When the Rule was created, as an ISO 8601 timestamp.                    |
| `updatedAt`       | string | read-only                   | When the Rule last changed, as an ISO 8601 timestamp.                   |

## Match types

| `matchType`    | Matches                                      | Required field |
| -------------- | -------------------------------------------- | -------------- |
| `EXACT_MATCH`  | One specific URL.                            | `value`        |
| `PREFIX_MATCH` | Every URL that begins with the given prefix. | `prefix`       |
| `DEFAULT`      | Every webhook no other Rule matches.         | none           |

Each `value` and each `prefix` must be unique across your account. A duplicate returns `409 Conflict`. Only one `DEFAULT` Rule is allowed per account.

> \[!WARNING]
>
> `matchType` carries the matching behavior, so patterns don't take a `*` character. A `*` in `value` or `prefix` is treated as a literal character, not a wildcard, so it won't match what you expect. To match everything, use `matchType: DEFAULT`.

```json title="Match one URL exactly"
{
  "matchType": "EXACT_MATCH",
  "value": "https://api.example.com/webhooks/voice/incoming",
  "settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
}
```

```json title="Match a path prefix"
{
  "matchType": "PREFIX_MATCH",
  "prefix": "https://api.example.com/webhooks/",
  "settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
}
```

## Evaluation order

Twilio evaluates your Rules in a fixed order and applies the first one that matches. You don't set or influence the order.

1. Exact-match Rules, longest match first.
2. Prefix-match Rules, longest prefix first.
3. The default Rule.

If no Rule matches, Twilio sends the webhook with no Setting applied: Twilio doesn't authenticate itself to your endpoint, it signs the request with your account authentication token using `HMAC_SHA1`, and it uses default connection behavior.

`GET /v1/Webhooks/Rules` returns your Rules already sorted in this evaluation order.

> \[!NOTE]
>
> Given a prefix Rule for `https://api.example.com/`, a prefix Rule for `https://api.example.com/webhooks/`, and a default Rule:
>
> * A webhook to `https://api.example.com/webhooks/sms` uses the `…/webhooks/` Rule, because it's the longer matching prefix.
> * A webhook to `https://api.example.com/status` uses the `https://api.example.com/` Rule.
> * A webhook to `https://other.example.net/hook` uses the default Rule.

## Settings and traffic distribution

`settings` is an array of one or two entries. Each entry names a Setting and the share of matching traffic it receives.

| Property     | Type    | Necessity | Description                                        |
| ------------ | ------- | --------- | -------------------------------------------------- |
| `settingId`  | string  | required  | The Setting to apply.                              |
| `percentage` | integer | required  | The share of matching webhooks, from `0` to `100`. |

The percentages across the array **must sum to exactly 100**. Anything else returns a `400` validation error.

```json title="One setting for all matching traffic"
{ "settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ] }
```

### Shift traffic between settings

Because [Settings are immutable][settings], you roll out a configuration change by splitting a Rule's traffic across the old and new Setting, then moving the split.

1. Create the new Setting and [test][testing] it.
2. `PATCH` the Rule to send a small share to the new Setting.

   ```bash
   curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
        -H 'Content-Type: application/json' \
        -u {API_KEY_SID}:{API_KEY_SECRET} \
        -d '{
              "settings": [
                { "settingId": "{OLD_SETTING_ID}", "percentage": 90 },
                { "settingId": "{NEW_SETTING_ID}", "percentage": 10 }
              ]
            }'
   ```
3. Wait for the [Operation][operations] to reach `COMPLETED`, then confirm your endpoint is handling the new configuration.
4. Repeat with a larger share, for example `50`/`50`, then `0`/`100`.
5. Once the new Setting takes all traffic, `PATCH` the Rule to a single-entry array and delete the old Setting.

To roll back, `PATCH` the percentages the other way. Because the array holds at most two Settings, stage one change at a time.

## Manage webhook rules

`POST`, `PATCH`, and `DELETE` return `202 Accepted` with an `Operation-Id` header, a `Location` header pointing at the Operation, and a `Retry-After` header. The write is saved immediately, then takes 30 to 60 seconds to propagate to the plane that delivers your webhooks. See [Operations][operations].

### Create a rule

```bash
curl -X POST https://webhooks.twilio.com/v1/Webhooks/Rules \
     -H 'Content-Type: application/json' \
     -u {API_KEY_SID}:{API_KEY_SECRET} \
     -d '{
           "friendlyName": "Production webhooks",
           "matchType": "PREFIX_MATCH",
           "prefix": "https://api.example.com/webhooks/",
           "settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
         }'
```

### List all rules

Returns Rules in evaluation order. Filter by Setting with `settingId`.

```bash
curl -X GET 'https://webhooks.twilio.com/v1/Webhooks/Rules?settingId={SETTING_ID}' \
     -u {API_KEY_SID}:{API_KEY_SECRET}
```

### Fetch one rule

```bash
curl -X GET https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
     -u {API_KEY_SID}:{API_KEY_SECRET}
```

### Update a rule

Omit `matchType` to change only `friendlyName`, `description`, or `settings`. Include `matchType` to change how the Rule matches, and send the companion field for that type in the same request.

```bash title="Change the settings only"
curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
     -H 'Content-Type: application/json' \
     -u {API_KEY_SID}:{API_KEY_SECRET} \
     -d '{
           "settings": [ { "settingId": "{NEW_SETTING_ID}", "percentage": 100 } ]
         }'
```

```bash title="Change the match pattern"
curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
     -H 'Content-Type: application/json' \
     -u {API_KEY_SID}:{API_KEY_SECRET} \
     -d '{
           "matchType": "PREFIX_MATCH",
           "prefix": "https://api.example.com/v2/webhooks/"
         }'
```

### Delete a rule

```bash
curl -X DELETE https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
     -u {API_KEY_SID}:{API_KEY_SECRET}
```

Returns `202 Accepted`. Webhooks that the Rule used to match fall through to the next matching Rule, or to no Setting at all.

## Constraints

* Up to 50 Rules per account. See [error 59200][59200].
* One `DEFAULT` Rule per account.
* Each `value` and each `prefix` unique across the account.
* One or two Settings per Rule, with percentages summing to 100.
* Basic authentication isn't allowed on the default Rule. See [error 59202][59202].

> \[!WARNING]
>
> Because a default Rule matches every otherwise-unmatched webhook URL, a Setting using Basic authentication on it would send your credentials to any destination Twilio calls. Twilio rejects that configuration with [error 59202][59202]. Scope Basic authentication to an exact-match or prefix-match Rule, or use OAuth 2.0 or Digest on the default Rule.

## What's next?

* [Track webhook rule changes][operations], to confirm your change propagated
* [Configuration API FAQs][faq]

[59200]: /docs/api/errors/59200

[59202]: /docs/api/errors/59202

[mt]: #match-types

[operations]: /docs/usage/webhooks/webhook-operations

[settings]: /docs/usage/webhooks/webhook-settings

[st]: #settings-and-traffic-distribution

[testing]: /docs/usage/webhooks/webhook-testing

[faq]: /docs/usage/webhooks/webhook-configuration-faq
