Skip to contentSkip to navigationSkip to topbar
Page tools
Useful for sharing or LLM
Accelerate development with AI

On this page
Looking for more inspiration?Visit the

Configure webhook rules


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


Rule properties

rule-properties page anchor

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

PropertyTypeNecessityDescription
idstringread-onlyThe Rule's identifier, in the form webhooks_rule_ plus 26 characters.
friendlyNamestringoptionalA name to identify the Rule. Up to 255 characters. Defaults to blank.
descriptionstringoptionalWhat the Rule is for. Up to 1024 characters.
matchTypeenumrequiredEXACT_MATCH, PREFIX_MATCH, or DEFAULT.
valuestringrequired for EXACT_MATCHThe exact URL to match. Up to 2048 characters.
prefixstringrequired for PREFIX_MATCHThe URL prefix to match. Up to 2048 characters.
settingsarrayrequiredOne or two Settings with the percentage of traffic each receives.
createdAtstringread-onlyWhen the Rule was created, as an ISO 8601 timestamp.
updatedAtstringread-onlyWhen the Rule last changed, as an ISO 8601 timestamp.

matchTypeMatchesRequired field
EXACT_MATCHOne specific URL without a trailing slash.value
PREFIX_MATCHEvery URL that begins with the given prefix. The prefix must end with /.prefix
DEFAULTEvery webhook no other Rule matches.none
(warning)

The default Rule applies to every webhook in your account

A default Rule catches every webhook that no other Rule matches. Start with an exact match or a narrow prefix, and add a default Rule only after you've proven the Setting.

(information)

Scope Rules to endpoints you own

A Rule decides which destinations receive the credentials in its Setting. Match only URLs you control. Twilio recommends that you set an exact match or a narrow prefix over a broad one.

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

Write value and prefix as full URLs starting with http:// or https://, and without query parameters or fragments. A pattern containing either fails validation.

Twilio might store your pattern differently from the way you wrote it. It adjusts each incoming webhook URL in the same way before comparing, so a GET returns exactly what Twilio compares against.

PartWhat Twilio does
Scheme and hostLowercases them
Default port for the schemeRemoves it
Query and fragmentRemoves them
PathKeeps your capitalization, percent-encoded with uppercase hex

Submit https://A.com:443/Hook and Twilio stores and matches https://a.com/Hook. Because the path keeps its case, a Rule for /hook doesn't match a webhook sent to /Hook.

An http:// pattern and an https:// pattern are different. Write the scheme your webhook URL uses.

A pattern containing a . or .. path segment fails validation, including percent-encoded forms such as %2e%2e. Twilio doesn't resolve those segments in an incoming URL either, so a webhook URL containing one matches no exact or prefix Rule and falls through to the default Rule.

(warning)

Wildcards aren't valid

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.

Match one URL exactly

match-one-url-exactly page anchor
1
{
2
"matchType": "EXACT_MATCH",
3
"value": "https://api.example.com/webhooks/voice/incoming",
4
"settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
5
}
1
{
2
"matchType": "PREFIX_MATCH",
3
"prefix": "https://api.example.com/webhooks/",
4
"settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
5
}

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.

(information)

Worked example

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-and-traffic-distribution page anchor

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

PropertyTypeNecessityDescription
settingIdstringrequiredThe Setting to apply.
percentageintegerrequiredThe 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.

One setting for all matching traffic

one-setting-for-all-matching-traffic page anchor
{ "settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ] }

Shift traffic between settings

shift-traffic-between-settings page anchor

Because Settings are immutable, 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 it.

  2. PATCH the Rule to send a small share to the new Setting.

    1
    curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
    2
    -H 'Content-Type: application/json' \
    3
    -u {API_KEY_SID}:{API_KEY_SECRET} \
    4
    -d '{
    5
    "settings": [
    6
    { "settingId": "{OLD_SETTING_ID}", "percentage": 90 },
    7
    { "settingId": "{NEW_SETTING_ID}", "percentage": 10 }
    8
    ]
    9
    }'
  3. Wait for the Operation 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.


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 90 seconds to propagate to the plane that delivers your webhooks. See Operations.

1
curl -X POST https://webhooks.twilio.com/v1/Webhooks/Rules \
2
-H 'Content-Type: application/json' \
3
-u {API_KEY_SID}:{API_KEY_SECRET} \
4
-d '{
5
"friendlyName": "Production webhooks",
6
"matchType": "PREFIX_MATCH",
7
"prefix": "https://api.example.com/webhooks/",
8
"settings": [ { "settingId": "{SETTING_ID}", "percentage": 100 } ]
9
}'
(warning)

A Rule changes live traffic

Once its Operation completes, a Rule applies to real webhooks, and undoing it also takes 30 to 90 seconds. Test the Setting first, and use the migration guide gradually to bring a URL over to your new Rule.

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

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

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.

Settings are immutable, but Rules aren't. Editing a Rule changes which Setting live webhooks use.

Change the settings only

change-the-settings-only page anchor
1
curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
2
-H 'Content-Type: application/json' \
3
-u {API_KEY_SID}:{API_KEY_SECRET} \
4
-d '{
5
"settings": [ { "settingId": "{NEW_SETTING_ID}", "percentage": 100 } ]
6
}'

Change the match pattern

change-the-match-pattern page anchor
1
curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
2
-H 'Content-Type: application/json' \
3
-u {API_KEY_SID}:{API_KEY_SECRET} \
4
-d '{
5
"matchType": "PREFIX_MATCH",
6
"prefix": "https://api.example.com/v2/webhooks/"
7
}'
1
curl -X DELETE https://webhooks.twilio.com/v1/Webhooks/Rules/{RULE_ID} \
2
-u {API_KEY_SID}:{API_KEY_SECRET}

Returns 202 Accepted.

(warning)

When you delete a Rule, traffic is then routed to the next most specific Rule

Webhooks the Rule matched go to the next most specific Rule that matches them, then to the default Rule, and otherwise to legacy delivery. Check that the Setting they land on authenticates and signs in a way your endpoint accepts.


  • Up to 50 Rules per account. See error 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.
(warning)

Basic authentication on the default rule

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. Scope Basic authentication to an exact-match or prefix-match Rule, or use OAuth 2.0 or Digest on the default Rule.