Skip to main content
You can choose to be notified about events on your 10DLC Brands, Campaigns and Phone Numbers by configuring webhooks. For this mechanism to work, you’ll need a publicly accessible HTTP server that can receive our webhook requests at one or more specified URLs. We highly recommend using HTTPS (instead of HTTP). This tutorial walks through setting up a basic application for receiving webhooks.

Configuring webhooks

To receive notifications for brands you need to either provide the webhooks at the creation of the brand or you may update an existing brand. In both cases you have to pass your webhooks in the webhookURL and webhookFailoverURL. webhookFailoverURL is optional. Here is an example of updating the webhooks of a brand:
Don’t forget to update YOUR_API_KEY here.
curl -X PUT https://api.telnyx.com/10dlc/brand/:brandid \
  -H 'Content-type: application/json' \
  -H 'Authorization: Bearer <YOUR_API_KEY>' \
  -d '{"webhookURL":"https://mywebhooks.com/c5e5e598-95b3-4076-bfe2-c7d2c58ec57f", "webhookFailoverURL":"https://mywebhooks.com/ae20ec14-1c23-4275-add5-3290706b450f"}'
The same applies for campaign event notifications. Webhooks can be provided either upon campaign creation or through an update. Webhooks configured for a campaign are also leveraged for event notifications with phone numbers associated with that campaign. Phone number notifications are triggered for shared campaigns as well.

Types of events

Overall structure of events

Here is an example of a webhook event:
{
  "data": {
    "event_type": "10dlc.brand.update",
    "id": "02d4f0e2-7a9d-4ebf-86b9-3df81e862d49",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "brandName": "Some Brand LLC",
      "description": "Brand BBRAND1 is added",
      "eventType": "BRAND_ADD",
      "status": "success",
      "tcrBrandId": "BBRAND1",
      "type": "TCR_BRAND_UPDATE"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Let’s have a closer look at the data key:
FieldDescription
event_typeWe currently support 3 types of events: 10dlc.brand.update, 10dlc.campaign.update and 10dlc.phone_number.update for updates related to brands, campaigns and phone numbers respectively.
idUnique ID of this event.
occurred_atTimestamp of the event.
payloadThe content of the payload varies according to the type of event. Below we listed the different payload types grouped by entity.
record_typeAlways event for webhook events.
The meta object contains delivery metadata:
FieldDescription
attemptThe delivery attempt number, starting at 1. Useful for identifying retries.
delivered_toThe webhook URL where this event was sent.

Brand events

Payload typeDescription
REGISTRATIONFailures during the registration process. The payload will contain a field called reasons with more details about the errors encountered.
REVETSuccess of the revetting request operation. See the revet brand endpoint for more details.
ORDER_EXTERNAL_VETTINGNotification on the process of ordering an external vetting. The status field indicates if the order succeeded or failed.
TCR_BRAND_UPDATENotifications received from TCR. The table below has a list of all TCR events that are included here.
Here is a list of all TCR events under the TCR_BRAND_UPDATE type:
TCR EventDescription
BRAND_ADDBrand successfully added on TCR.
BRAND_APPEAL_ADDA Brand appeal was added.
BRAND_APPEAL_COMPLETEThe result of a brand appeal.
BRAND_REVETResult of a brand revet request.
Here is an example of a REGISTRATION notification:
{
  "data": {
    "event_type": "10dlc.brand.update",
    "id": "456abc67-7a9d-4ebf-86b9-3df81e862d49",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "b0e2ec67-b26f-4c77-affc-d10f4d1780d3",
      "status": "failed",
      "type": "REGISTRATION",
      "reasons": [
        {
          "fields": [
            "ein"
          ],
          "description": "Invalid EIN - EIN is a nine-digit number. The format is XX-XXXXXXX. The \"-\" symbol is also accepted."
        }
      ]
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a TCR_BRAND_UPDATE notification:
{
  "data": {
    "event_type": "10dlc.brand.update",
    "id": "02d4f0e2-7a9d-4ebf-86b9-3df81e862d49",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "brandName": "Some Brand LLC",
      "description": "Brand BBRAND1 is added",
      "eventType": "BRAND_ADD",
      "status": "success",
      "tcrBrandId": "BBRAND1",
      "type": "TCR_BRAND_UPDATE"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of an ORDER_EXTERNAL_VETTING notification:
{
  "data": {
    "event_type": "10dlc.brand.update",
    "id": "a1b2c345-6789-4def-a123-456789abcdef",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "status": "success",
      "type": "ORDER_EXTERNAL_VETTING",
      "reasons": []
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a REVET notification:
{
  "data": {
    "event_type": "10dlc.brand.update",
    "id": "def45678-90ab-cdef-1234-567890abcdef",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "status": "success",
      "type": "REVET",
      "reasons": []
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}

Campaign events

Payload typeDescription
REGISTRATIONNotifications about failures during the registration process. The errors will be listed in the reasons field of the payload.
TELNYX_REVIEWTelnyx internal compliance review notification. Sent when Telnyx approves or rejects a campaign. The status field contains ACCEPTED or REJECTED. The description field contains the TCR campaign ID (e.g., C6X6M95).
NUMBER_POOL_PROVISIONEDSuccess on provisioning a number pool.
NUMBER_POOL_DEPROVISIONEDSuccess on deprovisioning a number pool.
TCR_EVENTNotification received from TCR. See table below for specific event types.
MNO_REVIEWMNO/DCA review results. The status field contains ACCEPTED or REJECTED. In case of rejection, the description field provides a reason.
TELNYX_EVENTTelnyx system events such as campaign suspension. The status field contains DORMANT for suspended campaigns.
VERIFIEDCampaign has been successfully provisioned with MNOs. Sent when campaign reaches MNO_PROVISIONED status.
Here is a list of TCR events under the TCR_EVENT type:
TCR EventDescription
CAMPAIGN_ADDCampaign successfully added to TCR.
CAMPAIGN_BILLEDCampaign billing event from TCR.
CAMPAIGN_DCA_COMPLETEDCA processing complete for campaign.
CAMPAIGN_EXPIREDCampaign has expired.
CAMPAIGN_NUDGENudge event sent by partner CSP to trigger campaign re-review after appeal or rejection.
CAMPAIGN_RESUBMISSIONCampaign has been resubmitted.
CAMPAIGN_UPDATECampaign has been updated.
MNO_CAMPAIGN_OPERATION_APPROVEDMNO has approved the campaign.
MNO_CAMPAIGN_OPERATION_REJECTEDMNO has rejected the campaign.
MNO_CAMPAIGN_OPERATION_REVIEWCampaign is under MNO review.
MNO_CAMPAIGN_OPERATION_SUSPENDEDMNO has suspended the campaign.
MNO_CAMPAIGN_OPERATION_UNSUSPENDEDMNO has unsuspended the campaign.
Here is an example of a campaign REGISTRATION failure notification:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "c3d4e567-8901-4bcd-ef23-456789012345",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "status": "failed",
      "type": "REGISTRATION",
      "reasons": [
        {
          "fields": ["sample1"],
          "description": "Sample message does not contain required opt-out language"
        }
      ]
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a NUMBER_POOL_PROVISIONED notification:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "d4e5f678-9012-4cde-f345-678901234567",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "type": "NUMBER_POOL_PROVISIONED"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a NUMBER_POOL_DEPROVISIONED notification:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "e5f6a789-0123-4def-a456-789012345678",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "type": "NUMBER_POOL_DEPROVISIONED"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a VERIFIED notification:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "456abc67-7a9d-4ebf-86b9-3df81e862d49",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "brandId": "97091164-e814-435c-9c1b-14ab2d18e987",
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "createdDate": "2024-07-06T14:22:37.328+00:00",
      "cspId": "CSPID1",
      "type": "VERIFIED",
      "isTMobileRegistered": true
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a TELNYX_REVIEW notification (approval):
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "789def12-3a4b-5c6d-7e8f-9a0b1c2d3e4f",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "description": "C6X6M95 approved by Telnyx",
      "status": "ACCEPTED",
      "type": "TELNYX_REVIEW"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a TELNYX_EVENT notification (campaign suspension):
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "a1b2c345-6789-4def-a123-456789abcdef",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "description": "Campaign has been marked as dormant",
      "status": "DORMANT",
      "type": "TELNYX_EVENT"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of an MNO_REVIEW notification (rejection):
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "def45678-90ab-cdef-1234-567890abcdef",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "description": "Campaign rejected by T-Mobile due to insufficient opt-out instructions",
      "status": "REJECTED",
      "type": "MNO_REVIEW"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a TCR_EVENT notification:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "fed98765-4321-dcba-9876-543210fedcba",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "type": "TCR_EVENT",
      "eventType": "CAMPAIGN_ADD",
      "description": "Campaign C6X6M95 successfully added to TCR"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Note: The campaignId field in webhooks contains the Telnyx UUID, not the TCR campaign ID. The TCR campaign ID (e.g., C6X6M95) may appear in the description field.

Phone number events

Payload typeDescription
ASSIGNMENTNotifications about the phone number assignment process. In case of failure, an error message is displayed in the reasons field. That field is empty in case of a successful assignment.
DELETIONNotifications about the phone number removal process. In case of failure, an error message is displayed in the reasons field. That field is empty in case of a successful removal.
STATUS_UPDATEThe status of the phone number was updated. The new status is shown in the status field.
Phone numbers in webhook payloads use E.164 format (e.g., +16715455939), which includes the country code prefix.
Here is an example of a successful ASSIGNMENT notification:
{
  "data": {
    "event_type": "10dlc.phone_number.update",
    "id": "123abc67-7a9d-4ebf-86b9-3df81e862d49",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "phoneNumber": "+16715455939",
      "status": "success",
      "type": "ASSIGNMENT",
      "reasons": []
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
Here is an example of a STATUS_UPDATE notification:
{
  "data": {
    "event_type": "10dlc.phone_number.update",
    "id": "789def12-3a4b-5c6d-7e8f-9a0b1c2d3e4f",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "tcrCampaignId": "C6X6M95",
      "phoneNumber": "+16715455939",
      "status": "ADDED",
      "type": "STATUS_UPDATE"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}
The status field in STATUS_UPDATE notifications can be: ADDED, DELETED, PENDING, or FAILED.
Here is an example of a DELETION notification:
{
  "data": {
    "event_type": "10dlc.phone_number.update",
    "id": "b2c3d456-7890-4abc-def1-234567890abc",
    "occurred_at": "2024-08-07T17:22:37.328+00:00",
    "payload": {
      "campaignId": "751c6a5c-907b-43a9-8ada-ba1dc8335b07",
      "phoneNumber": "+16715455939",
      "status": "success",
      "type": "DELETION",
      "reasons": []
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://mywebhooks.com/310fda1a-d415-4827-837b-5f7e72657b65"
  }
}

Campaign Appeals and Nudging Mechanisms

When campaigns are rejected, there are different flows for getting them back into the compliance review queue depending on the campaign type and rejection reason.

Native Campaign Appeals

For native campaigns rejected due to external factors (e.g., website compliance issues), customers can use the campaign appeal endpoint after addressing the issues: API Endpoint:
curl -X POST 'https://api.telnyx.com/10dlc/campaign/{campaignId}/appeal' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "appealReason": "The website has been updated to include the required privacy policy and terms of service."
  }'
This will update the campaign status from TELNYX_FAILED to TCR_ACCEPTED and re-enter the compliance review queue.

Partner Campaign Nudging

For partner campaigns, the appeal process involves the CSP (Campaign Service Provider) sending a CAMPAIGN_NUDGE event after reviewing and approving customer changes: CAMPAIGN_NUDGE Webhook Payload Example:
{
  "data": {
    "event_type": "10dlc.campaign.update",
    "id": "example-event-id",
    "occurred_at": "2025-07-30T11:07:51.259711+00:00",
    "payload": {
      "campaignId": "C4D06C2F",
      "type": "CAMPAIGN_NUDGE",
      "nudgeIntent": "APPEAL_REJECTION",
      "description": "The campaign has been reviewed and approved after appeal.",
      "cspId": "TNX"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://your-webhook-url.com"
  }
}
Note: CAMPAIGN_NUDGE events originate from TCR and use the TCR campaign ID format (e.g., C4D06C2F) in the campaignId field, unlike other campaign webhooks which use the Telnyx UUID.

Campaign Appeal Scenarios

There are several specific scenarios where campaign appeals may be needed:

1. Native Campaign Rejected for Content Issues

When a customer submits a native campaign and Telnyx rejects it due to issues with the campaign content (e.g., unclear sample messages), the customer can make adjustments to their campaign. Using the campaign update endpoint will automatically reset the campaign’s status to TCR_ACCEPTED so it goes back into the compliance team’s review queue.

2. Native Campaign Rejected for External Factors

When a customer submits a native campaign and Telnyx rejects it due to factors outside the campaign object (e.g., website compliance requirements), the customer must:
  • Fix the external issues (e.g., update website with required privacy policy).
  • Use the appeal API endpoint to get their campaign back in the review queue.
Example failure reason:
{
  "reason": "Website does not meet compliance requirements."
}
After fixes are made, the appeal request:
curl -X POST 'https://api.telnyx.com/10dlc/campaign/{campaignId}/appeal' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "appealReason": "The website has been updated to include the required privacy policy and terms of service."
  }'

3. Partner Campaign Rejected (Any Reason)

For partner campaigns rejected for either content issues or external factors, the process involves the CSP:
  • Customer makes required adjustments based on rejection reasons.
  • CSP reviews the changes and approves them.
  • CSP forwards a CAMPAIGN_NUDGE event to Telnyx.
  • Campaign status changes from TELNYX_FAILED to TCR_ACCEPTED and re-enters compliance review.
This nudging mechanism for partner campaigns cannot work with native campaigns.

4. DCA Rejection for External Factors

When Telnyx accepts a campaign but the Direct Connect Aggregator (DCA) rejects it due to external factors:
  • Customer makes required external changes (e.g., website updates).
  • Customer notifies Telnyx via appropriate appeal mechanism (scenarios 2 or 3).
  • Once Telnyx approves the changes, Telnyx generates a nudge webhook that the DCA receives.
  • Campaign re-enters DCA review queue.

5. DCA Rejection for Content Issues

When the DCA rejects a campaign due to campaign content issues:
  • Customer updates campaign content (e.g., sample messages).
  • Customer notifies Telnyx via appropriate appeal mechanism (scenarios 1 or 3).
  • Once Telnyx approves the changes, Telnyx generates a nudge webhook that the DCA receives.
  • Campaign re-enters DCA review queue.

Campaign status flow

The following diagram shows the campaign lifecycle including both success and failure paths:

Success path statuses

StatusDescription
TCR_PENDINGCampaign is pending review at The Campaign Registry (TCR).
TCR_ACCEPTEDCampaign has been accepted by TCR and is ready for Telnyx/MNO review.
MNO_PENDINGCampaign is pending provisioning with Mobile Network Operators (MNOs).
MNO_PROVISIONEDCampaign has been successfully provisioned with all MNOs.

Failure and suspension statuses

StatusDescription
TCR_FAILEDCampaign was rejected by TCR during initial registration.
TELNYX_FAILEDCampaign was rejected by Telnyx compliance review. Can be appealed.
MNO_REJECTEDCampaign was rejected by one or more MNOs. Can be appealed.
TCR_SUSPENDEDCampaign has been suspended due to compliance issues.
TCR_EXPIREDCampaign has expired and is no longer active.

Campaign appeal status flow

The typical status flow for campaign appeals is:
  1. Initial rejection: Campaign status becomes TELNYX_FAILED.
  2. Customer action: Customer addresses the rejection reasons.
  3. Appeal submission:
    • Native campaigns: Use appeal API endpoint or campaign update.
    • Partner campaigns: CSP sends CAMPAIGN_NUDGE.
  4. Re-review: Campaign status changes to TCR_ACCEPTED and re-enters compliance review.
The nudging mechanism for partner campaigns cannot be used with native campaigns. Native campaigns must use the direct appeal API endpoint or campaign update functionality.

Webhook delivery

Retry policy

If your webhook endpoint returns a non-2xx HTTP status code or times out, Telnyx will retry delivery. The meta.attempt field in the webhook payload indicates which delivery attempt this is (starting at 1).
  • Default retry attempts: 5
  • Default retry interval: 30 seconds between attempts
After 5 failed attempts, the webhook will be marked as failed and no further retries will be made.

Best practices

  • Return 2xx quickly: Return a 200 response as soon as possible, then process the webhook asynchronously.
  • Handle duplicates: Webhooks may be delivered more than once. Use the id field to deduplicate.
  • Use HTTPS: Always use HTTPS endpoints to ensure webhook data is encrypted in transit.
  • Verify the source: Consider implementing signature verification for added security.
  • Set up failover: Configure a webhookFailoverURL to receive webhooks if your primary endpoint is unavailable.

Testing webhooks locally

During development, you can use tunneling tools to expose your local server to the internet for webhook testing:
  1. ngrok: Run ngrok http 3000 to create a public URL that forwards to your local port 3000.
  2. Cloudflare Tunnel: Use cloudflared tunnel for a similar tunneling solution.
  3. localtunnel: Run lt --port 3000 for a quick temporary URL.
Update your brand or campaign webhook URL to the tunnel URL, then monitor incoming webhooks as you trigger events in your 10DLC registration flow.

Glossary

TermDefinition
10DLC10-Digit Long Code. Standard 10-digit phone numbers used for application-to-person (A2P) messaging.
CSPCampaign Service Provider. A company authorized to submit and manage campaigns on behalf of brands with The Campaign Registry.
DCADirect Connect Aggregator. An entity that has a direct connection to mobile carriers for message delivery.
MNOMobile Network Operator. Wireless carriers such as T-Mobile, AT&T, and Verizon that deliver SMS/MMS messages to end users.
TCRThe Campaign Registry. The central registry that manages brand and campaign registration for 10DLC messaging in the United States.

See also