Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

A2P 10DLC Compliance Embeddable Onboarding Guide


(information)

Info


Compliance Embeddable

compliance-embeddable page anchor

With global regulatory requirements frequently changing across jurisdictions, navigating compliance is an expensive, ongoing challenge. Complex requirements lead to customer confusion and registration drop-offs, while maintaining internal compliance tooling consumes significant engineering resources. The Compliance Embeddable helps address these challenges by this by shifting the development and regulatory management burden away from your team, allowing you to scale onboarding effortlessly.

The Compliance Embeddable is a white-label, self-service solution designed to integrate seamlessly into an Independent Software Vendor's (ISV) existing portal or web application. It empowers your end customers to independently manage their registrations and verifications requests while Twilio manages the underlying registration workflow infrastructure".

No Twilio Branding: Twilio manages the UI logic and regulatory question flows behind the scenes, but the entire experience can be fully customized to match your platform's exact design, typography, and color palette. Request Theme: https://forms.gle/tvSuXpvwJE9aPj9B9

Minimize Manual Data Entry: When initializing the Compliance Inquiry, Twillo allows ISV's to pre-fill their customer data for an expedited registration experieince.

The Compliance Embeddable requires two integrations:

  1. Server-side integration: Call Twilio's API to initialize a Compliance Inquiry and retrieve a session token and inquiry ID.
  2. Client-side integration: Embed the UI in an iframe, and include the session token and inquiry ID as URL parameters.

All calls must be authenticated using Twilio's REST API credentials with Basic Auth, where the account SID is either your primary Twilio Account SID or a subaccount SID. The Account SID given in the credentials is the account that the registration will be associated with after completion of the ComplianceInquiry.

Learn more about the Compliance Embeddable in the Compliance Embeddable FAQ(link takes you to an external page)


Before you begin, you must have a Trust Hub Primary Customer Profile for a business whose Business Identity is set to ISV or Reseller. See Create a Trust Hub Primary Customer Profile to learn more.

Only ISV accounts with approved Trust Hub profiles can access the Compliance Embeddable API. Trial accounts are not eligible to use this API.


A2P 10DLC registration is a two-step process that requires both Brand Registration and Campaign Registration. The Compliance Embeddable supports this flow through two separate form submissions:

  1. Brand Registration: First, you initialize a brand inquiry to collect business information. This registers the brand with The Campaign Registry (TCR).
  2. Campaign Registration: After the brand is approved, you initialize a campaign inquiry to register specific messaging campaigns under that brand.

The Compliance Embeddable supports both steps by separately calling the Initialize Inquiry API in your workflow twice:

  • Once to initialize the brand registration inquiry
  • A second time to initialize the campaign registration inquiry after the initial brand approval

Server-side integration

server-side-integration page anchor

The Compliance Embeddable's data collection process is secured via server-side authentication and is triggered by a server-side API call. This API call initializes a ComplianceInquiry and returns a token, which you can then pass to your web client to authenticate into a submission flow. The Compliance Embeddable supports both new submissions and resumption of existing inquiries. If a verification is already in progress, approved, or rejected with an error that cannot be resubmitted, the API returns an error response. See the Error responses table for details.


Create Brand by initializing ComplianceInquiry

create-brand-by-initializing-complianceinquiry page anchor

To initialize a ComplianceInquiry for A2P 10DLC Brand registration, make an HTTPS request to the following API:

POST https://trusthub.twilio.com/v1/A2PBrandRegistrations

Brand Request Body

brand-request-body page anchor

If you provide data for optional fields, they're pre-filled in any of your users' subsequent forms. The body must use the application/json content type.

FieldField typeField SpecificsDescription
brandType [required]EnumAllowed Values: STANDARD, SOLE_PROPRIETORA SOLE_PROPRIETOR is an unregistered individual with strict messaging limits and no EIN, while a STANDARD Business is a legally registered entity with an EIN that unlocks high-volume, high-throughput messaging capabilities.
friendlyName [required]StringMax length: 255A descriptive name for this brand or campaign registration inquiry.
notificationEmail [required]StringEmail regex. Max length: 500The email address to which all notifications for the status of the registration will be sent.
themeSetId [optional]StringMax length: 255Theme ID for customized UI styling. To request a customized Theme, follow the instructions in our FAQ(link takes you to an external page).
businessName [optional]StringMax length: 255The name of the business or organization using the phone number.
businessRegistrationAuthority [opt]StringAllowed Values: TBDThe authority that issued the business registration. For US businesses, this is typically EIN. Required for all business types except SOLE_PROPRIETOR.
businessRegistrationNumber [opt]StringMax length: 21A legally recognized business registration number such as an EIN. Required for all business types except SOLE_PROPRIETOR.
businessIndustry [optional]EnumAllowed Values: AGRICULTURE, AUTOMOTIVE, BANKING, COMMUNICATION, CONSTRUCTION, CONSUMER, EDUCATION, ELECTRONICS, ENERGY, ENGINEERING, FAST_MOVING_CONSUMER_GOODS, FINANCIAL, FINTECH, FOOD_AND_BEVERAGE, GAMBLING, GOVERNMENT, HEALTHCARE, HOSPITALITY, INSURANCE, JEWELRY, LEGAL, MANUFACTURING, MEDIA, NOT_FOR_PROFIT, OIL_AND_GAS, ONLINE, PROFESSIONAL_SERVICES, RAW_MATERIALS, REAL_ESTATE, RELIGION, RETAIL, TECHNOLOGY, TELECOMMUNICATIONS, TRANSPORTATION, TRAVEL
businessWebsite [optional]StringURL regex (https://). Max length: 255The website of the business or organization using the phone number.
brandType [required]EnumAllowed Values: PRIVATE_PROFIT, PUBLIC_PROFIT, NON_PROFIT, SOLE_PROPRIETOR, GOVERNMENT
brandExternalVettingToken [opt]StringMax length: 10The unique vetting token from the vetting provider. The token is case sensitive and must match the format provided by the vetting provider exactly.
businessStockSymbol [optional]StringMax length: 10The unique publicly traded company or organization stock or ticker symbol
businessIndustry [optional]EnumAllowed Values: AMEX, AMX, ASX, B3, BME, BSE, FRA, ICEX, JPX, JSE, KRX, LON, NASDAQ, NONE, NYSE, NSE, OMX, OTHER, SEHK, SGX, SSE, STO, SWX, SZSE, TSX, TWSE, VSE
businessTaxExemptStatus [optional]BooleanAllowed Values: TRUE, FALSEA value of true will mark the business as excempt from local government taxes.
businessStreetAddress [optional]StringMax length: 100The address of the business or organization using the phone number.
businessStreetAddress2 [optional]StringMax length: 100The second row of the street address of the business or organization using the phone number.
businessCity [optional]StringMax length: 100The city of the business or organization using the phone number.
businessStateProvinceRegion [opt]StringMax length: 20The state/province or region of the business or organization using the phone number.
businessPostalCode [optional]StringMax length: 10The postal code of the business or organization using the phone number.
businessCountry [optional]StringMax length: 2The ISO country code of the business or organization using the phone number.
businessContactFirstName [opt]StringMax length: 100The first name of the contact for the business or organization using the phone number.
businessContactLastName [opt]StringMax length: 100The last name of the contact for the business or organization using the phone number.
businessContactEmail [optional]StringEmail regex. Max length: 100The email address of the contact for the business or organization using the phone number.
businessContactPhone [optional]StringE.164 regex. Max length: 20The phone number of the contact for the business or organization using the phone number.
authorizedContactVerificationEmail [opt]StringEmail regex. Max length: 255The first and last name of the designated representative for the business or organization.
authorizedContactMobilePhoneNumberE164 [opt]StringE.164 regex. Max length: 20The phone number of the designated representative for the business or organization.
isTest [optional]BooleanAllowed Values: TRUE, FALSEA value of true will mark the bundle as a test bundle. The test bundle will be auto-rejected without verification and cannot be used for phone number purchases. If this field is not provided, by default the bundle will NOT be created as a test bundle
skipAutomaticSecVet [optional]BooleanAllowed Values: TRUE, FALSEA value of true skips the message volume questions in UI
Example Brand Inquiry Initialize Call
example-brand-inquiry-initialize-call page anchor
1
POST https://trusthub.twilio.com/v1/A2PBrandRegistrations
2
3
Auth: Basic auth (AccountSid:AuthToken)
4
5
Request body:
6
{
7
"brandType": "STANDARD",
8
"customerProfileId": "BU1213242784782",
9
"friendlyName": "Acme Corp",
10
\\following fields are optional
11
"themeSetId": "theme_abc123",
12
"statusNotificationEmail": "notify@example.com",
13
"businessName": "Acme Corp",
14
"businessRegistrationAuthority": "EIN",
15
"businessRegistrationNumber": "123456789",
16
"businessIndustry": "TECHNOLOGY",
17
"businessWebsite": "https://acme.com",
18
"businessType": "PRIVATE_PROFIT",
19
"businessStockSymbol": "TWLO",
20
"businessStockExchange": "NYSE",
21
"businessTaxExemptStatus": false,
22
"businessStreetAddress": "123 Main St",
23
"businessStreetAddress2": "Suite 100",
24
"businessCity": "San Francisco",
25
"businessStateProvinceRegion": "CA",
26
"businessPostalCode": "94105",
27
"businessCountry": "US",
28
"businessContactFirstName": "Jane",
29
"businessContactLastName": "Doe",
30
"businessContactEmail": "jane@acme.com",
31
"businessContactPhone": "+14155551234",
32
“authorizedContactVerificationEmail”: “verification@example.com”
33
“authorizedContactMobilePhoneNumberE164”: “+14333045678”,
34
“brandExternalVettingToken”: “cv|10dlctcr|...
35
“isTest”: “true”, (would want to skip the mock option Persona screen asking about Message volume),
36
"skipAutomaticSecVet": true
37
}
38
39
Response (201 Created):
40
{
41
"id": "tri1.us1.account.AC238276e6.registration.BU6469a51f"
42
"sessionId": "inq_XXXXXXXXXXXXXXXXXXXXXXXX",
43
"sessionToken": "eyJhbGciOiJIUzI1NiIs..."
44
}
45
}
46

To resume a ComplianceInquiry for A2P 10DLC Brand registration, make an HTTPS request to the following API:

POST https://trusthub.twilio.com/v1/A2PBrandRegistrations/{id}/EmbeddedSessions

The value for id is tri1.us1.account.(AccountSID).registration.(BrandBundleSID)

To retrieve a list of all A2P 10DLC registrations, including their Bundle SIDs, make an HTTPS request to the following API:

GET https://messaging.twilio.com/v1/a2p/BrandRegistrations

To learn more about query parameters for filtering results, see the Brand Registration API docs.


Create Campaign by initializing ComplianceInquiry

create-campaign-by-initializing-complianceinquiry page anchor

To initialize a ComplianceInquiry for A2P 10DLC Campaign registration, make an HTTPS request to the following API:

POST https://trusthub.twilio.com/v1/A2PCampaignRegistrations

If you provide data for optional fields, they're pre-filled in any of your users' subsequent forms.

The body must use the application/json content type.

FieldField typeField SpecificsDescription
a2pBrandRegistrationSid [required]StringBN SIDThe Brand Registration SID from the approved brand registration.
messagingServiceSid [required]StringMG SIDThe Messaging Service SID to associate with this campaign.
themeSetId [optional]StringMax length: 255Theme ID for customized UI styling. To request a customized Theme, follow the instructions in our FAQ(link takes you to an external page).
useCaseCategories [optional]EnumAllowed Values: 2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, MARKETING, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOCIAL, SWEEPSTAKEThe category that best describes the use case for this campaign.
useCaseDescription [optional]StringMin Length: 40 Max length: 4096Detailed description of the campaign's messaging use case.
useCaseSampleMessage1 [optional]StringMin Length: 40 Max length: 1024First sample message demonstrating typical message content for this campaign.
useCaseSampleMessage2 [optional]StringMin Length: 40 Max length: 1024Second sample message demonstrating typical message content for this campaign.
useCaseSampleMessage3 [optional]StringMin Length: 40 Max length: 1024Third sample message demonstrating typical message content for this campaign.
useCaseSampleMessage4 [optional]StringMin Length: 40 Max length: 1024Fourth sample message demonstrating typical message content for this campaign.
useCaseSampleMessage5 [optional]StringMin Length: 40 Max length: 1024Fifth sample message demonstrating typical message content for this campaign.
useCaseCategories [optional]EnumAllowed Values: VERBAL, WEB_FORM, PAPER_FORM, VIA_TEXT, MOBILE_QR_CODEThe method by which end users opt-in to receive messages.
useCaseOptInDescription [optional]StringMin Length: 40 Max length: 2048Description of how end users opt-in to receive messages from this campaign.
hasEmbeddedLinks [optional]BooleanAllowed Values: TRUE, FALSEA value of true indicates that messages will include embedded links.
hasEmbeddedPhone [optional]BooleanAllowed Values: TRUE, FALSEA value of true indicates that messages will include embedded phone numbers.
embeddedUrlSample [optional]StringURL regex (https://). Max length: 255Sample URLs that will be embedded in messages.
directLending [optional]BooleanAllowed Values: TRUE, FALSEA value of true indicates this campaign involves direct lending or loan arrangements.
ageGated [optional]BooleanAllowed Values: TRUE, FALSEA value of true indicates this campaign has age restrictions.
privacyPolicyUrl [optional]StringURL regex (https://). Max length: 2048URL to the privacy policy applicable to this messaging campaign.
termsAndConditionsUrl [optional]StringURL regex (https://). Max length: 2048URL to the terms and conditions applicable to this messaging campaign.
optInKeywords [optional]StringMax length: 255Keywords that users can send to opt-in to messages.
optInMessageSample [optional]Array of StringsMin Length: 20 Max length: 1024Sample message sent to users after they opt-in.
optOutKeywords [optional]Array of StringsMax length: 255Keywords that users can send to opt-out of messages.
optOutMessageSample [optional]StringMin Length: 20 Max length: 1024Sample message sent to users after they opt-out.
helpKeywords [optional]Array of StringsMax length: 255Keywords that users can send to request help.
helpMessageSample [optional]StringMin Length: 20 Max length: 1024Sample message sent to users when they request help.
Example Campaign Inquiry Initialize Call
example-campaign-inquiry-initialize-call page anchor
1
POST https://trusthub.twilio.com/v1/A2PCampaignRegistrations
2
Auth: Basic auth (AccountSid:AuthToken)
3
4
Request body:
5
{
6
"a2pBrandRegistrationSid": "BN01cab0515ca623fc3d3bc9ee0879b50f",
7
\\following fields are optional
8
"messagingServiceSid": "MG12345678901234567890123456789000",
9
"themeSetId": "theme_abc123",
10
"useCaseCategories": ["ACCOUNT_NOTIFICATIONS", "CUSTOMER_CARE"],
11
"useCaseDescription": "Order status updates and customer support responses",
12
"useCaseSampleMessage1": "Hi Jane, your order #4821 has shipped and will arrive by Thursday. Track at acme.com/track/4821",
13
"useCaseSampleMessage2": "Hi Jane, your order #4821 has shipped and will arrive by Thursday. Track at acme.com/track/4821",
14
"useCaseSampleMessage3": "Hi Jane, your order #4821 has shipped and will arrive by Thursday. Track at acme.com/track/4821",
15
"useCaseSampleMessage4": "Hi Jane, your order #4821 has shipped and will arrive by Thursday. Track at acme.com/track/4821",
16
"useCaseSampleMessage5": "Hi Jane, your order #4821 has shipped and will arrive by Thursday. Track at acme.com/track/4821",
17
"useCaseOptInTypes": ["WEB_FORM"],
18
"useCaseOptInDescription": "End users opt-in by visiting www.acme.com and adding their phone number. They then check a box agreeing to receive text messages from Acme, Inc. Additionally, end users can also opt-in by texting START to (111) 555-3333 to opt in. Terms and Conditions at www.acme.com/tc. Privacy Policy at www.acme.com/privacy.",
19
"hasEmbeddedLinks": false,
20
"hasEmbeddedPhone": false,
21
"embeddedUrlSample": "https://acme.com/privacy",
22
"directLending": false,
23
"ageGated": false,
24
"privacyPolicyUrl": "https://acme.com/privacy",
25
"termsAndConditionsUrl": "https://acme.com/terms",
26
"optInKeywords": ["START", "SUBSCRIBE"],
27
"optInMessageSample": "For help, visit acme.com/support or call 1-800-555-0123. Reply STOP to opt out.",
28
"optOutKeywords": ["START", "SUBSCRIBE"],
29
"optOutMessageSample": "For help, visit acme.com/support or call 1-800-555-0123. Reply STOP to opt out.",
30
"helpKeywords": ["START", "SUBSCRIBE"],
31
"helpMessageSample": "For help, visit acme.com/support or call 1-800-555-0123. Reply STOP to opt out."
32
}
33
34
Response (201 Created):
35
{
36
"id": "tri1.us1.account.AC238276e6.registration.BU6469a51f"
37
"sessionId": "inq_XXXXXXXXXXXXXXXXXXXXXXXX",
38
"sessionToken": "eyJhbGciOiJIUzI1NiIs..."
39
}
40

To resume a ComplianceInquiry for A2P 10DLC Campaign registration, make an HTTPS request to the following API:

POST https://trusthub.twilio.com/v1/A2PCampaignRegistrations/{id}/EmbeddedSessions

Tracking Campaign Submission via Message Service

tracking-campaign-submission-via-message-service page anchor

Once the campaign is created, its associated Bundle SID will be removed. Going forward, delivery status and errors by using the Messaging Service API.

Receive Campaign Status updates via webhook

receive-campaign-status-updates-via-webhook page anchor

By default, Twilio sets your Messaging Service to "Defer to sender's webhook," meaning inbound messages to any sender within the Messaging Service's sender pool hit the webhook configured on each sender. The delivery status of your message, including any delivery errors, is sent asynchronously to your status callback URL.

Fetch Campaign status via API

fetch-campaign-status-via-api page anchor

GET https://messaging.twilio.com/v1/Services/{MessagingServiceSid}/Compliance/Usa2p/QE2c6890da8086d771620e9b13fadeba0b

This endpoint returns the following details:

  • sid
  • campaign_status (for example, IN_PROGRESS, VERIFIED, or FAILED)
  • failure_reason (if any)

Track your A2P registration status automatically with Twilio Event Streams. You can now get instant webhook notifications for any changes to your Brands, Campaigns, or 10DLC numbers without having to manually poll APIs or refresh the console. To learn more, see the Event Streams docs.


After initializing a ComplianceInquiry, you may embed the ComplianceInquiry UI in your website using the TwilioComplianceEmbed React client.

Install the package in your React project using your preferred package manager.

NPM:

npm install @twilio/twilio-compliance-embed

Yarn:

yarn add @twilio/twilio-compliance-embed

The ComplianceInquiry UI can be embedded in your site using following code snippet:

1
import * as React from "react";
2
import { TwilioComplianceEmbed } from "@twilio/twilio-compliance-embed";
3
4
const ComplianceInquiry = () => {
5
return (
6
<TwilioComplianceEmbed
7
inquiryId='<your inquiry ID from calling the Initialize ComplianceInquiry API>'
8
inquirySessionToken='<your inquiry session token from calling the Initialize ComplianceInquiry API>'
9
/>
10
);
11
};

The ComplianceInquiry UI may take a few seconds to load and render.

NameTypeDescription
inquiryId(Required) StringA valid inquiryId returned by calling the Initialize ComplianceInquiry API.
inquirySessionToken(Required) StringA valid inquirySessionToken returned by calling the Initialize ComplianceInquiry API.
onInquirySubmitted() => voidAn event handler that fires when the user has completed the ComplianceInquiry process. This event is fired when the user lands on the last screen.
onComplete() => voidAn event handler that fires when a user completes the ComplianceInquiry process. This event is fired when the user clicks the Done or Exit button on the last page.
Note: This event is not guaranteed to be fired as the user could choose not to click the button on the last page. If you wish to track when a user has finished the flow and submitted the bundle, use onInquirySubmitted instead.
onCancel() => voidAn event handler that fires when the user has canceled the ComplianceInquiry process.
onError() => voidAn event handler that fires when an unexpected error occurs during the ComplianceInquiry process.
onReady() => voidAn event handler that fires when the ComplianceInquiry UI has finished loading.
widgetPadding{ top?: number; bottom?: number; left?: number; right?: number; }Allows customizing the internal padding inside the iframe. If you omit the property, the component applies the default padding: {top: 74, left: 24, right: 24, bottom: 24}. The value should be an object with the following structure: {top?: number; bottom?: number; left?: number; right?: number;}
1
import * as React from "react";
2
import { Spinner } from "@twilio-paste/core/spinner";
3
import { TwilioComplianceEmbed } from "@twilio/twilio-compliance-embed";
4
5
function MyComplianceInquiry() {
6
const [data, setData] = React.useState(null);
7
const [isLoading, setLoading] = React.useState(true);
8
9
React.useEffect(() => {
10
fetch("https://trusthub.twilio.com/v1/ComplianceInquiries/Tollfree/Initialize", {
11
method: "POST",
12
})
13
.then((res) => res.json())
14
.then((data) => {
15
setData(data);
16
setLoading(false);
17
});
18
}, []);
19
20
return !isLoading ? (
21
<TwilioComplianceEmbed
22
inquiryId={data.inquiry_id}
23
sessionToken={data.inquiry_session_token}
24
onReady={() => {
25
console.log("Ready!");
26
}}
27
onInquirySubmitted={() => {
28
console.log("Registration complete");
29
}}
30
widgetPadding={{top: 0, left: 100, right: 100, bottom: 0}}
31
/>
32
) : (
33
<Spinner decorative={false} title="Loading" />
34
);
35
}
36
37
export default MyComplianceInquiry;

We don't yet provide native integrations for frontend frameworks other than React. However, we are releasing a JS SDK soon, so customers using non-React frameworks or older versions of React can also use the Compliance Embeddable.