Skip to main content

10DLC Status Callbacks

10DLC status callbacks allow you to receive real-time notifications when the state of your 10DLC registration changes. This feature enables you to monitor the lifecycle of your messaging brands, campaigns, number assignment orders, and number assignments.

10DLC Status Callback Parameters

The following parameters will be posted via an HTTP POST request to your webhook - you can use one or all of them depending on what type of information you are looking for.

Parameter NameParameter DescriptionParameter Type
project_idThe unique ID of the project this object is associated with.string
event_atThe timestamp of when the event occurred, in ISO 8601 format.string
event_categoryThe category of the event. Can be one of: brand, campaign, number_assignment_order, or number_assignment.string
event_typeThe specific type of event that occurred. See the Event Types section below for all possible values.string
stateThe current state of the object after the event. Possible values depend on the object type.string
brand_idThe unique identifier for the brand. Present in all event types.string
campaign_idThe unique identifier for the campaign. Present in campaign, number assignment order, and number assignment events.string
number_assignment_order_idThe unique identifier for the number assignment order. Present in number assignment order and number assignment events.string
number_assignment_idThe unique identifier for the number assignment. Present only in number assignment events.string
phone_number_idThe unique identifier for the phone route itself. Present only in number assignment events.string
phone_numberThe phone number in E.164 format. Present only in number assignment events.string

Event Types and State Changes

Brand Events

Brands can transition through the following states:

State TransitionEvent TypeDescription
pendingcompletedbrand_activatedThe brand has been successfully verified and activated.
pendingunverifiedbrand_unverifiedThe brand verification failed or additional information is required.
unverifiedcompletedbrand_activatedThe brand was previously unverified but is now active.

Campaign Events

Campaigns can transition through the following states:

State TransitionEvent TypeDescription
pendingactivecampaign_activatedThe campaign has been approved and is now active.
activeinactivecampaign_deactivatedThe campaign has been deactivated and can no longer send.

Number Assignment Order Events

Number assignment orders have only one possible state change:

State TransitionEvent TypeDescription
pendingprocessednumber_assignment_order_processedThe number assignment order has been processed and numbers assigned.

Number Assignment Events

Number assignments can transition through the following states:

State TransitionEvent TypeDescription
pendingfailednumber_assignment_failedThe number assignment failed and the number was not assigned to campaign.
failedpendingnumber_assignment_pendingA failed number assignment is being retried.
pendingcompletednumber_assignment_activatedThe number has been successfully assigned to the campaign.

10DLC Status Callbacks Application Example

Below is an example of a simple 10DLC status tracker that will log every state change event to the console and store them in separate tables based on the event category. This example monitors brands, campaigns, and number assignments, providing real-time visibility into your 10DLC registration pipeline.

The application will categorize events by type and log them to appropriate tables. For number assignment events, if any failures are detected, they will be logged to a separate failed assignments table for investigation. This allows you to quickly identify and address any issues with number provisioning.

from flask import Flask, request
import logging
import pandas as pd
from datetime import datetime

logging.basicConfig(level=logging.INFO)
app = Flask(__name__)

brandEvents = []
campaignEvents = []
numberAssignmentOrderEvents = []
numberAssignmentEvents = []
failedAssignments = []

@app.route("/10dlc-status", methods=['POST'])
def handle_10dlc_callback():
project_id = request.values.get('project_id', None)
event_at = request.values.get('event_at', None)
event_category = request.values.get('event_category', None)
event_type = request.values.get('event_type', None)
state = request.values.get('state', None)
brand_id = request.values.get('brand_id', None)
campaign_id = request.values.get('campaign_id', None)
number_assignment_order_id = request.values.get('number_assignment_order_id', None)
number_assignment_id = request.values.get('number_assignment_id', None)
phone_number_id = request.values.get('phone_number_id', None)
phone_number = request.values.get('phone_number', None)

logging.info('10DLC Event - Category: {}, Type: {}, State: {}, Time: {}'.format(
event_category, event_type, state, event_at))

if event_category == 'brand':
brandEvents.append([brand_id, event_type, state, event_at, project_id])
df = pd.DataFrame(brandEvents, columns=('Brand ID', 'Event Type', 'State', 'Event Time', 'Project ID'))
print("\nBrand Events")
print(df.to_string())

elif event_category == 'campaign':
campaignEvents.append([campaign_id, brand_id, event_type, state, event_at, project_id])
df = pd.DataFrame(campaignEvents, columns=('Campaign ID', 'Brand ID', 'Event Type', 'State', 'Event Time', 'Project ID'))
print("\nCampaign Events")
print(df.to_string())

elif event_category == 'number_assignment_order':
numberAssignmentOrderEvents.append([number_assignment_order_id, campaign_id, brand_id, state, event_at, project_id])
df = pd.DataFrame(numberAssignmentOrderEvents, columns=('Order ID', 'Campaign ID', 'Brand ID', 'State', 'Event Time', 'Project ID'))
print("\nNumber Assignment Order Events")
print(df.to_string())

elif event_category == 'number_assignment':
numberAssignmentEvents.append([number_assignment_id, phone_number, phone_number_id, campaign_id, event_type, state, event_at, project_id])
df = pd.DataFrame(numberAssignmentEvents, columns=('Assignment ID', 'Phone Number', 'Phone Number ID', 'Campaign ID', 'Event Type', 'State', 'Event Time', 'Project ID'))
print("\nNumber Assignment Events")
print(df.to_string())

if state == 'failed':
failedAssignments.append([number_assignment_id, phone_number, campaign_id, event_at, project_id])
failed_df = pd.DataFrame(failedAssignments, columns=('Assignment ID', 'Phone Number', 'Campaign ID', 'Failed At', 'Project ID'))
print("\nFailed Number Assignments")
print(failed_df.to_string())

if len(failedAssignments) >= 10:
failed_df.to_csv('failed_10dlc_assignments.csv', index=False, encoding='utf-8')
logging.warning('10 or more number assignment failures detected. CSV report generated.')
failedAssignments.clear()

return ('', 200)

if __name__ == "__main__":
app.run()