Before you begin this process, read and complete the pre-requisites in the WhatsApp Tech Provider Program overview.
The Twilio WhatsApp onboarding team is here to guide you through the process. Reach out for help using the same support ticket created after you submitted the WhatsApp Tech Provider Program request form.
Let's get started!
It is recommended to start with a new Meta app (even if you already have another Meta app). If you already have another Meta app, there is little benefit to reusing it unless you already have completed the Meta App review for the whatsapp_business_management
permission.
Meta Business Manager — sometimes referred to as Facebook Business Manager, Meta BM, or Meta Business Account — has been renamed to Business Portfolio by Meta. All terms refer to the same business entity within Meta's systems and IDs are consistent. We are in process of updating the Twilio documentation to use Meta's new term.
The name of the app, not the name of your business portfolio, will be shown to users in the Embedded Signup pop-up window. Do not include Meta's trademarks, such as WhatsApp, in this name.
Meta requires your business manager to have 2FA enabled to complete the rest of this process. For guidance on how to enable it, follow the steps provided in Meta's official documentation to make sure this is enabled for your business.
Get your coding gloves ready!
At the end of this section, you will have completed a prototype of Embedded Signup. You will need to submit a screen recording of your prototype to Meta as part of App Review in the following section.
First, familiarize yourself with the desired user flow:
Client business will choose the phone number that they wish to use on WhatsApp (unless you assign numbers automatically). The WhatsApp Tech Provider Program supports both Twilio phone numbers and non-Twilio phone numbers (i.e. bringing your own phone number, or BYON) on WhatsApp.
Client business will click the "Login with Facebook" button within your UI and the Embedded Signup popup window will launch.
In the popup window, they will follow Meta's flow and complete the following:
Remember this user flow as you will need to provide Meta with this user flow in the next section.
Let's start by getting permissions to manage WhatsApp business accounts. This is done by creating a "Configuration" with the whatsapp_business_management
permission. It is recommended to use a new configuration for Embedded Signup.
In the Meta app dashboard, navigate to the left menu and click on Add Product. From the options that appear, select Set Up in the Facebook Login for Business card. Once you've done that, go back to the left navigation, and go to Configurations, then click on Create Configuration. Important: Do not switch to "Facebook Login". Only "Facebook Login for Business" is accepted.
Navigate back to the left menu, click Configurations > Create a Configuration.
In this section, assign a name to your configuration. Remember, this name will not be visible to your customers. After you've entered a name, select Next.
In the login variation section, select the WhatsApp Embedded Signup option and click Next.
Choose Access Token: This section refers to your Meta Graph API access token. Since you are working with Twilio and using Twilio's APIs and will not be calling Meta's Graph API directly, you do not need to worry about this page and can use the recommended option. Select the recommended 60 days option and click Next.
Under the Assets section, select the WhatsApp accounts option.
Make sure you have the whatsapp_business_management
permission before you finalize the configuration. Since you are working with Twilio's APIs, you don't need to add other permissions. Adding other permissions may also slow down the Meta app approval process.
Save the Configuration ID that Meta provides. You will need this when adding the JavaScript code to your website.
You should now be able to test the Login button flow.
Finally, set your App Mode to Live in the Meta app dashboard.
The final step in the user flow is to register the number in the customer's WABA using Twilio's Senders API. However, before you can do so, your Meta app needs to be approved by Meta.
Meta requires submitting for Meta app Review so that your App can use the whatsapp_business_management
permission in production with Twilio. This is a required Meta compliance step to safeguard the ecosystem. As part of this process, your business needs to complete a data handling questionnaire.
Review to make sure your Meta app's icon, app category, legal documentation links, and platform are all accurate within App settings > Basic. Updating these details after App Review submission may trigger a re-review.
If you haven't already, use the Graph API explorer tool to make at least 1 successful API call using the whatsapp_business_management
permission no more than 30 days prior to submitting for App Review.
Request advanced access to the whatsapp_business_management
permission: Under App Review > Permissions and Features, look for whatsapp_business_management
and click to "Request advanced access". Follow the steps to continue to App Review. To streamline the App Review process, do not request any advanced access to any additional permissions.
If you're having trouble finding the whatsapp_business_management
permission, try using your browser's find function rather than Meta's search bar.
Navigate to the App Review > Requests section. Scroll down to the bottom of the Request for App Review page, there you will find the Data Handing questions section. Click on the arrow to answer the data handling questions.
Meta will require you to:
The final step prior to submitting is to share a written description and a screen recording of your user flow, along with your prototype. Meta's integrity team's concern is how your business will use the whatsapp_business_management
permission, so focus on the core user flow for WhatsApp onboarding. You do not need to give a complete product demo. Omit audio as Meta's reviewers will not listen to it.
In the App Verification Details, describe the user flow that uses the whatsapp_business_management
permission as noted above.
Share your prototype with Meta. Meta requires that the app be publicly available or with instructions on how to access it (e.g. test credentials). The step by step guide lets reviewers demo your integration.
Next, you will upload the screen recording and provide details on the requested permission. The screen recording should match the descriptions you already provided. Show the user flow that uses the whatsapp_business_management
permission. You must show a user granting your app this permission. Meta recommends that the screen recording be approximately 30 seconds to 2 minutes long, and in high-resolution (1080 or better).
Click to "Submit for Review". Meta generally provides a review decision within a week.
Let Twilio know that you have submitted your App to Meta. Twilio is here to help you along the way and we want to know how it's going!
Once Meta has reviewed your App, you will receive an email and Alert in your Meta app dashboard. Go to Alerts > Inbox and review the submission results.
Once your Meta app is approved, you will need to complete Meta's Access Verification to verify that your business is a Tech Provider. You can do this in your App Dashboard by navigating to App Settings > Basic. There you should see an option to complete Access Verification. Fill out the steps below and submit. Meta typically takes 5 business days to review this, but if it's taking a while then let Twilio know to escalate it on your behalf.
Congratulations on getting all of the Meta approvals completed! Now let's connect your Meta app to Twilio.
If you haven't already, you will need to copy the Meta app ID shown in the top of your App Dashboard to send to Twilio's WhatsApp onboarding team.
This allows you to continue to use Twilio's APIs and platform for WhatsApp.
On the left navigation within the Meta app, select Products > WhatsApp > Partner Solutions. Click to "Accept" Twilio's request.
Copy your unique Solution ID. Find the file where you are calling the FB.login
function. Use your unique Solution ID for the solutionID
field — yes solutionID
not solution_id
as it will not work correctly.
1// Handle WhatsApp Signup2function launchEmbeddedSignup() {3// Launch Facebook login4FB.login(5function (response) {6// Since you are using Twilio's APIs, you do not need to do anything with the response here.7},8{9config_id: "KEEP_IN_QUOTES_BUT_REPLACE_WITH_YOUR_CONFIG_ID",10auth_type: "rerequest", // avoids "user is already logged" in errors if users click the button again before refreshing the page11response_type: "code",12override_default_response_type: true,13extras: {14sessionInfoVersion: 2, // required to get WABA ID15setup: {16solutionID: "KEEP_IN_QUOTES_BUT_REPLACE_WITH_YOUR_SOLUTION_ID",17}18}19}20);21}
Once you add the Solution ID, you should notice that when you go through Embedded Signup, it displays that your company is working with Twilio to enable your customers on WhatsApp during the pop-up window flow. This is required by Meta's legal team, and cannot be removed.
Once your Meta app review is approved, you can finish your integration with Twilio:
Up until this point, when the Embedded Signup window opens, the default configuration for Embedded Signup will have your users do the following:
If you are using Twilio SMS-capable phone numbers for your customers, it's against Twilio policy to display OTPs. As a result, Twilio's Senders API will do (3) automatically when you make the API call to create the WhatsApp Sender and you need to turn off those steps within Embedded Signup.
If you are using a combination of Twilio SMS-capable phone numbers, as well as Twilio voice-only numbers or non-Twilio numbers (i.e. BYON), then you will need to configure Embedded Signup dynamically based on the type of phone number the client business choose.
To configure Embedded Signup to not prompt your customers to provide a phone number and skip those steps, update where you make your FB.login call to include featureType: 'only_waba_sharing'
like so:
1function launchEmbeddedSignup() {2FB.login(3function (response) {4},5{6config_id: "KEEP_IN_QUOTES_BUT_REPLACE_WITH_YOUR_CONFIG_ID",7auth_type: "rerequest",8response_type: "code",9override_default_response_type: true,10extras: {11sessionInfoVersion: 2,12// set the following "featureType" to 'only_waba_sharing'13// if and only if using a Twilio SMS-capable number, otherwise14// do not include it or set it to null15featureType: 'only_waba_sharing', // <---16setup: {17solutionID: "SOLUTION_ID",18}19}20}21);22}
When a new company signs up with WhatsApp, they will create a new WABA. Each WABA is mapped to a Twilio subaccount. If you're not already familiar with Twilio subaccounts, you can learn more in the subaccounts guide. If you don't already have a subaccount for this customer, you will need to create one programmatically.
Create a subaccount programmatically using the Twilio Accounts API
See the example below and make sure to replace the FriendlyName
with your customer's company name. Use your main Twilio account (parent account) credentials to make this request. Refer to the Accounts API docs for an example in your desired programming language.
Do not make this or other Twilio API calls involving a Twilio AuthToken
on the front end of your application, where you implemented Embedded Signup.
1// Download the helper library from https://www.twilio.com/docs/node/install2const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";34// Find your Account SID and Auth Token at twilio.com/console5// and set the environment variables. See http://twil.io/secure6const accountSid = process.env.TWILIO_ACCOUNT_SID;7const authToken = process.env.TWILIO_AUTH_TOKEN;8const client = twilio(accountSid, authToken);910async function createAccount() {11const account = await client.api.v2010.accounts.create({12friendlyName: "Submarine",13});1415console.log(account.authToken);16}1718createAccount();
1{2"auth_token": "auth_token",3"date_created": "Thu, 30 Jul 2015 20:00:00 +0000",4"date_updated": "Thu, 30 Jul 2015 20:00:00 +0000",5"friendly_name": "Submarine",6"owner_account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",7"sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",8"status": "active",9"subresource_uris": {10"available_phone_numbers": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/AvailablePhoneNumbers.json",11"calls": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Calls.json",12"conferences": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Conferences.json",13"incoming_phone_numbers": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/IncomingPhoneNumbers.json",14"notifications": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Notifications.json",15"outgoing_caller_ids": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/OutgoingCallerIds.json",16"recordings": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Recordings.json",17"transcriptions": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Transcriptions.json",18"addresses": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Addresses.json",19"signing_keys": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SigningKeys.json",20"connect_apps": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ConnectApps.json",21"sip": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SIP.json",22"authorized_connect_apps": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/AuthorizedConnectApps.json",23"usage": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Usage.json",24"keys": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Keys.json",25"applications": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Applications.json",26"short_codes": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SMS/ShortCodes.json",27"queues": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Queues.json",28"messages": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages.json",29"balance": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Balance.json"30},31"type": "Full",32"uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"33}
Each WABA can only be mapped to a single account or subaccount. You must keep track of each business or brand and have each onboarded onto a dedicated subaccount. WhatsApp does not allow senders from different businesses to be registered in the same WABA.
When you make the previous request, the subaccount's AccountSid
and AuthToken
will be returned. Save the subaccount's AccountSid
and AuthToken
in your database to use for this customer. You will also use these credentials in the next step when calling the Twilio Senders API to register your customer's phone numbers on WhatsApp.
In your front-end, once the user completes the Embedded Signup flow, pass the WABA ID and Phone Number to the backend of your application and use it with the subaccount's Account SID and Auth Token, to call the Twilio Senders API with the following fields:
sender_id
: provide the phone number that you are registering in the format using e.146waba_id
: provide the WABA ID if this is the first number for the customer. This will connect it to the subaccount. Note that once a WABA ID has been mapped to a subaccount, it will stay connected unless all WhatsApp Senders have been deleted from the account.callback_url
, callback_method
, fallback_url
, fallback_method
, and status_callback_url
: you can set your callback URLs on the sender so you can receive messages and message statuses. Note that status callbacks only support HTTP POST
.profile.name
is only required when using a Twilio SMS-capable number, otherwise Twilio will use the one provided by the customer during Embedded Signup. It's important to note that the profile name will be visible to your customers, and it must comply with certain regulations set by WhatsApp. To make the creation of a WhatsApp Sender smoother, Twilio encourages you to limit the number of different display names for each brand.1## Create Sender2curl -X "POST" "https://messaging.twilio.com/v2/Channels/Senders" \3-H "Content-Type: application/json; charset=utf-8" \4-u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \5-d $'{6"sender_id": "whatsapp:+15017122661",7"configuration": {8"waba_id": "12345678912345"9},10"profile": {11"address": "101 Spear Street, San Francisco, CA",12"emails": [13"support@twilio.com"14],15"vertical": "Other",16"logo_url": "https://www.twilio.com/logo.png",17"description": "We\'re excited to see what you build!",18"about": "Hello! We are Twilio.",19"name": "Twilio",20"websites": [21"https://twilio.com",22"https://help.twilio.com"23]24},25"webhook": {26"callback_method": "POST",27"callback_url": "https://demo.twilio.com/welcome/sms/reply/"28}29}'
1{2"status": "CREATING",3"sender_id": "whatsapp:+15017122661",4"sid": "XEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",5"configuration": {6"waba_id": "12345678912345"7},8"profile": {9"about": "Hello! This is Twilio's official account.",10"name": "Twilio",11"vertical": "Other",12"websites": [13{14"website": "https://twilio.com",15"label": "Website"16},17{18"website": "https://help.twilio.com",19"label": "Website"20}21],22"address": "101 Spear Street, San Francisco, CA",23"logo_url": "https://www.twilio.com/logo.png",24"emails": [25{26"email": "support@twilio.com",27"label": "Email"28}29],30"description": "We're excited to see what you build!"31},32"webhook": {33"callback_method": "POST",34"callback_url": "https://demo.twilio.com/welcome/sms/reply/"35},36"url": "https://messaging.twilio.com/v2/Channels/Senders/XEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",37"properties": null38}
The Senders API registers WhatsApp Senders asynchronously. When you make the POST
call above to create the WhatsApp Sender, the Sender's SID will be returned. WhatsApp Sender SIDs will start with XE
.
To check if the WhatsApp Sender has been successfully registered and is online, fetch the WhatsApp Sender:
1## Fetch Sender2curl -X "GET" "https://messaging.twilio.com/v2/Channels/Senders/XEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \3-H "Content-Type: application/json; charset=utf-8" \4-u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN"
1{2"status": "ONLINE",3"sender_id": "whatsapp:+15017122661",4"sid": "XEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",5"configuration": {6"waba_id": "12345678912345"7},8"profile": {9"about": "Hello! This is Twilio's official account.",10"name": "Twilio",11"vertical": "Other",12"websites": [13{14"website": "https://twilio.com",15"label": "Website"16},17{18"website": "https://help.twilio.com",19"label": "Website"20}21],22"address": "101 Spear Street, San Francisco, CA",23"logo_url": "https://www.twilio.com/logo.png",24"emails": [25{26"email": "support@twilio.com",27"label": "Email"28}29],30"description": "We're excited to see what you build!"31},32"webhook": {33"callback_method": "POST",34"callback_url": "https://demo.twilio.com/welcome/sms/reply/"35},36"url": "https://messaging.twilio.com/v2/Channels/Senders/XEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",37"properties": {38"messaging_limit": "1K Customers/24hr",39"quality_rating": "HIGH"40}41}
When the Sender's Status shows as ONLINE
, you can then use Twilio's APIs to send and receive messages.
Congrats! Don't forget to let the Twilio WhatsApp onboarding team know you successfully completed the flow.
Now that you have completed the integration, here are some other must reads when building your WhatsApp integration using Twilio.