Authenticate webhooks with OAuth 2.0, Basic, or Digest
Your webhook endpoint can require Twilio to authenticate itself as any other API client would. Twilio supports OAuth 2.0 client credentials, HTTP Basic, and HTTP Digest.
Set the default rule to use anything but HTTP Basic authentication
A default Rule matches every otherwise-unmatched webhook URL. This results in sending Basic credentials to every destination that Twilio calls. Twilio rejects that with error 59202. Scope Basic authentication to an exact-match or prefix-match Rule, or use OAuth 2.0 or HTTP Digest on the default Rule.
Authentication and signing solve different problems and work independently. Authentication proves Twilio can call your endpoint. A signature proves the integrity of request body in transit. Use authentication, signatures, of both over secure HTTP.
Twilio stores credentials in a required Webhook Setting auth object in one of two forms.
| Form | When to use it |
|---|---|
Inline (source: INLINE) | Each Setting has its own credentials. Recommended for most accounts. |
AuthProfile (source: REFERENCE) | Several Settings share one set of credentials, so you rotate them in one place. |
The standalone resource AuthProfile stores one set of credentials. To access these settings, get the authProfileId.
To fetch an access token from your authorization server, Twilio uses the client credentials flow. Twilio then sends the token as a Bearer token in the Authorization header of each webhook. When a token nears expiry, Twilio requests a replacement.
An OAuth 2.0 authorization server with client credentials support, and from it:
- The token endpoint URL
- A client ID
- A client secret
- Optionally, a scope
- Optionally, an audience
| Field | Necessity | Description |
|---|---|---|
scheme or type | required | OAUTH2. Use scheme for inline credentials, type for an AuthProfile. |
tokenUrl | required | Your authorization server's token endpoint. |
clientId | required | The OAuth 2.0 client identifier. |
clientSecret | required | The OAuth 2.0 client secret. Write-only, and never returned in a response. |
scope | optional | The scope Twilio requests. |
audience | optional | The audience Twilio requests. |
clientCredentialsAuthMethod | optional | CLIENT_SECRET_POST (default) or CLIENT_SECRET_BASIC. |
Make a POST request to the AuthProfiles resource.
1curl -X POST https://webhooks.twilio.com/v1/Webhooks/AuthProfiles \2-H 'Content-Type: application/json' \3-u {API_KEY_SID}:{API_KEY_SECRET} \4-d '{5"type": "OAUTH2",6"friendlyName": "Example authorization server",7"tokenUrl": "https://auth.example.com/oauth2/token",8"clientId": "{CLIENT_ID}",9"clientSecret": "{CLIENT_SECRET}",10"scope": "webhooks:write",11"clientCredentialsAuthMethod": "CLIENT_SECRET_POST"12}'
Returns 201 Created.
Save the returned id. Reference it from a Setting's auth object, then apply that Setting with a Webhook Rule.
If Twilio can't exchange your credentials for a token, it retries twice, 250 milliseconds apart. If those also fail, Twilio drops the webhook and logs error 97001 in the Twilio Debugger. Twilio tries again after 300 seconds, and webhooks matching that Setting may be dropped during that window.
Common causes are an unreachable authorization server, rotated or removed credentials, and a token issued with a type other than Bearer.
| Field | Necessity | Description |
|---|---|---|
scheme or type | required | BASIC. |
username | required | The username Twilio sends. |
password | required | The password. Write-only, never returned. |
1curl -X POST https://webhooks.twilio.com/v1/Webhooks/AuthProfiles \2-H 'Content-Type: application/json' \3-u {API_KEY_SID}:{API_KEY_SECRET} \4-d '{5"type": "BASIC",6"friendlyName": "Partner endpoint",7"username": "{USERNAME}",8"password": "{PASSWORD}"9}'
To use HTTP Digest, include the same username and password fields as Basic but set "type": "DIGEST".
1curl -X POST https://webhooks.twilio.com/v1/Webhooks/AuthProfiles \2-H 'Content-Type: application/json' \3-u {API_KEY_SID}:{API_KEY_SECRET} \4-d '{5"type": "DIGEST",6"friendlyName": "Legacy endpoint",7"username": "{USERNAME}",8"password": "{PASSWORD}"9}'
Every setting requires the auth parameter. When Twilio shouldn't authenticate itself, set the scheme to NONE.
{ "auth": { "source": "INLINE", "value": { "scheme": "NONE" } } }
Never include Secrets.
1curl -X GET https://webhooks.twilio.com/v1/Webhooks/AuthProfiles \2-u {API_KEY_SID}:{API_KEY_SECRET}
1curl -X GET https://webhooks.twilio.com/v1/Webhooks/AuthProfiles/{AUTH_PROFILE_ID} \2-u {API_KEY_SID}:{API_KEY_SECRET}
Only friendlyName is editable.
1curl -X PATCH https://webhooks.twilio.com/v1/Webhooks/AuthProfiles/{AUTH_PROFILE_ID} \2-H 'Content-Type: application/json' \3-u {API_KEY_SID}:{API_KEY_SECRET} \4-d '{ "friendlyName": "Example authorization server (EU)" }'
To change tokenUrl, clientId, clientSecret, or any other credential field, create a different AuthProfile and point your Settings to the created AuthProfile.
To delete one AuthProfile, make a DELETE request of the AuthProfiles resource with its ID.
1curl -X DELETE https://webhooks.twilio.com/v1/Webhooks/AuthProfiles/{AUTH_PROFILE_ID} \2-u {API_KEY_SID}:{API_KEY_SECRET}
A successful request returns 204 No Content. A failed request returns 409 Conflict as a Setting still references it. To resolve the error, find the dependent Settings, then change where they point or delete them.
1curl -X GET 'https://webhooks.twilio.com/v1/Webhooks/Settings?authProfileId={AUTH_PROFILE_ID}' \2-u {API_KEY_SID}:{API_KEY_SECRET}
You can't change anything in an AuthProfile except its friendlyName. To rotate credentials, replace the resource.
- Create a AuthProfile with the updated credentials.
- Create a Setting that references the AuthProfile.
- Test the added Setting against your endpoint.
- Shift your Rule onto the added Setting. If you want to validate on live traffic first, make the shift gradually.
- Delete the old Setting.
- Delete the old AuthProfile.
- Sign webhooks with shared keys, to sign requests as well as authenticate them
- Configure webhook settings, to reference these credentials from a Setting
- Test webhook delivery, to check the credentials against your endpoint
- Configure webhook rules, to apply that Setting to your webhooks
- Configuration API FAQs