WhatsApp Business Integration
with Amazon Connect
Complete setup guide for connecting a WhatsApp Business Account (WABA) to Amazon Connect via AWS End User Messaging Social — including IAM configuration, phone number provisioning, CLI commands, and a full troubleshooting playbook.
Overview
AWS End User Messaging Social1 is the service that owns the connection between Meta's WhatsApp Cloud API and your AWS account. Amazon Connect acts as the destination for inbound messages — routing each WhatsApp conversation to an available agent through the Contact Control Panel (CCP) or Agent Workspace, exactly like a chat contact.
This guide walks through the full integration from a clean start, plus a troubleshooting section covering the most common failure modes encountered in real deployments.
connect:SendIntegrationEvent. An SNS topic is only
needed if you want a parallel processing pipeline — which requires a different architecture.
Each WABA supports only one event destination.
Prerequisites
Meta / WhatsApp side
- Meta Business Portfolio (Business Manager account)
- A phone number that can receive an SMS or voice OTP, and is not already registered to a WhatsApp account
- Acceptance of WhatsApp Business Terms, Solution Terms, and Messaging Policy
- Business Verification completed (strongly recommended before go-live — prevents auto-restriction)
AWS side
- An Amazon Connect instance already created2
- IAM permissions to create roles and policies
- Access to AWS End User Messaging Social console (same region as your Connect instance)
- AWS CLI configured with credentials for the account
How it works
When a customer sends a WhatsApp message to your business number, it travels through three layers before reaching an agent:
Setup
Link your WABA to AWS End User Messaging Social
Open the AWS End User Messaging Social console and run the Sign up with WhatsApp embedded flow.3 This is the only correct starting point — do not create the WABA in Meta Business Manager first and then try to import it.
In the embedded flow you will:
- Authorize AWS to act as the billing party for your WhatsApp messages
- Select or create your Meta Business Portfolio
- Select or create a WhatsApp Business Account (WABA)
- Select or create a WhatsApp Business Profile
- Add and verify your phone number via OTP (SMS or voice call)
Under the hood this calls AssociateWhatsAppBusinessAccount on your behalf.
When the flow completes, the WABA appears in the console under
WhatsApp Business accounts with status COMPLETE.
Create the IAM role
You need a customer-managed IAM role that AWS End User Messaging Social can assume to deliver events to Connect and import your phone number. This is a single dual-purpose role — do not create separate roles for delivery and import.
Permission policy — attach this to the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowOperationsForEventDelivery",
"Effect": "Allow",
"Action": ["connect:SendIntegrationEvent"],
"Resource": "*"
},
{
"Sid": "AllowOperationsForPhoneNumberImport",
"Effect": "Allow",
"Action": [
"connect:ImportPhoneNumber",
"social-messaging:GetLinkedWhatsAppBusinessAccountPhoneNumber",
"social-messaging:TagResource"
],
"Resource": "*"
}
]
} Trust policy — allows social-messaging.amazonaws.com to assume the role:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": ["social-messaging.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}]
} aws:SourceAccount — can silently block
the service from assuming the role, causing zero SendIntegrationEvent
events with no obvious error. See trust policy troubleshooting.
Name the role whatever you'd like. The resulting role ARN will be in this format:
arn:aws:iam::123456789012:role/EndUserMessagingSocialWABAConnectDestination
Note the single path segment after role/. The API regex rejects
service-linked role ARNs, which have a multi-segment path. See
wrong role troubleshooting if you hit a 400 error.
Set Amazon Connect as the event destination
In the Social Messaging console → WhatsApp Business accounts → select your WABA → Event destination tab:4
- Click Edit destination
- Toggle the destination to Enable
- Set Destination type to Amazon Connect
- Select your Connect instance from the dropdown
- Under Two-way channel role, select Choose Existing Role and in the dropdown, select the custom role you created in Step 2
- Click Save changes
Saving the event destination triggers ImportPhoneNumber, which pushes
the WhatsApp number into your Connect instance.
Import the phone number into Connect
After saving the destination, confirm the import completed via CLI:
# 1. Find the Social Messaging phone number ARN
aws socialmessaging list-linked-whatsapp-business-accounts --region <region>
aws socialmessaging get-linked-whatsapp-business-account \
--id waba-<your-waba-id> \
--region <region>
# Note the phoneNumbers[].arn value
# 2. If the import didn't fire automatically, run it manually
WHATSAPP_NUMBER_ID=$(aws connect import-phone-number \
--instance-id <your-connect-instance-id> \
--source-phone-number-arn "<social-messaging-phone-arn>" \
--phone-number-description "WhatsApp WABA" \
--region <region> \
--query 'PhoneNumberId' \
--output text)
echo "Phone Number ID: $WHATSAPP_NUMBER_ID"
# 3. Check import status
aws connect describe-phone-number \
--phone-number-id $WHATSAPP_NUMBER_ID \
--region <region> aws connect release-phone-number --phone-number-id <old-phone-number-id> --region <region>Then re-run
import-phone-number. The number is not lost — it comes back as a WhatsApp channel. If you need
voice capability, this can be configured separately in WhatsApp Manager > Phone Numbers > Call Settings.9 Attach a contact flow
The imported number needs an inbound contact flow to route messages — without one, contacts arrive and are dropped silently.
# Find your contact flow ID
aws connect list-contact-flows \
--instance-id <your-connect-instance-id> \
--region <region>
# Attach the flow to the WhatsApp number
aws connect associate-phone-number-contact-flow \
--instance-id <your-connect-instance-id> \
--phone-number-id $WHATSAPP_NUMBER_ID \
--contact-flow-id <your-flow-id> \
--region <region> Alternatively, do this in the Connect console: Channels → Phone numbers → select the WhatsApp number → Edit → Flow/IVR → pick your inbound flow. The number should show WhatsApp in the Active Channels column.
Subtype == connect:WhatsApp to route
WhatsApp contacts separately from voice.
Verify end-to-end
- Open the Agent Workspace (or CCP) in Connect and set your status to Available
- Send a plain text "hi" from a personal phone to your registered WhatsApp number
- The contact should appear as a chat in the Agent Workspace
- Confirm in CloudTrail: look for a
connect:SendIntegrationEventevent — its presence means the full pipeline is working
Phone number options
10DLC and toll-free SMS registration are not required for WhatsApp — those are US carrier compliance requirements for SMS, which WhatsApp bypasses entirely. The only requirement is that the number can receive one OTP during Meta's verification step.5
Customer entry points
Customers can send a WhatsApp message directly to your business number — but don't ask them to type it manually. Publish one of these instead:
wa.me click-to-chat link
https://wa.me/15551234567 Tapping the link on a phone opens a pre-populated WhatsApp chat. Add ?text=Hello to pre-fill the first message. Use on websites, email signatures, and receipts.
QR codes
Generated in Meta Business Manager under WhatsApp Account settings. Scanning opens the same wa.me flow. Good for physical locations, packaging, and business cards.
Click-to-WhatsApp ads
Facebook/Instagram ads with a "Send Message" CTA that drops the user into a WhatsApp chat. Configured in Meta Ads Manager.
SendWhatsAppMessage API.
What message types are supported inbound?6
| Message type | Status |
|---|---|
| Plain text (≤ 1,024 chars) | Supported |
| Images, documents, audio, video (≤ 20 MB) — after contact opens | Supported |
| Interactive message responses (button/list taps) | Supported |
| Text > 1,024 characters | Dropped |
| Attachment as first message (before text) | Dropped |
| Attachment > 20 MB | Dropped |
| Stickers | Dropped |
| Location pin/share | Dropped |
| Contact cards (vCard) | Dropped |
| Emoji reactions | Dropped |
| Threaded reply (quote-reply) — quoted context is stripped | Partial |
Troubleshooting
When messages aren't appearing, CloudTrail is your first stop. Two events tell you which leg is failing:
connect:SendIntegrationEvent— Social Messaging calling Connect when an inbound WhatsApp message arrives. Not present = problem is on the Social/WABA side.AccessDeniedException= IAM role misconfigured.connect:SendChatIntegrationEvent— subsequent events on an existing chat contact.
No SendIntegrationEvent in CloudTrail
If SendIntegrationEvent never fires, Social Messaging either isn't receiving the message from Meta, or can't resolve the phone number. Work through these in order:
Social Messaging console → WABA → Event destination tab. Verify status is Enabled, type = Amazon Connect, correct instance, and role ARN is populated.
In Meta Business Manager → WhatsApp Accounts, confirm the WABA linked to AWS owns the phone number. Numbers registered under a different WABA (e.g. a marketing WABA) will not route inbound to AWS.
Meta Business Manager → WhatsApp Accounts → select WABA → Settings → Webhooks / Subscribed Apps. The subscribed app must be the AWS-controlled one. Under Webhook fields,
messages must be checked.
If not yet Business Verified, only phone numbers added to the allowed test recipients list in Meta can message in. Add the test number or complete Business Verification.
Attachments, stickers, locations, reactions, and emoji-first messages are filtered by Social Messaging before forwarding — none produce a
SendIntegrationEvent.
Always test with a plain-text "hi" as the very first message.
ResourceNotFoundException: "Origination phone number id not found"
This error from GetLinkedWhatsAppBusinessAccountPhoneNumber means Connect
holds a phone-number-id that no longer exists in Social Messaging. The
number shows "Active, WhatsApp" in Connect but points at a ghost record.
Most likely causes:
- The phone number was removed and re-added on the Social side after Connect imported it — the
phone-number-idchanged but Connect still holds the old one. - Cross-account drift — the IAM role belongs to an account where the phone number ID doesn't exist.
- You have two WABAs; the event destination was set on WABA A but the number being tested belongs to WABA B.
Diagnosis:
# What Social actually knows
aws socialmessaging list-linked-whatsapp-business-accounts --region <region>
aws socialmessaging get-linked-whatsapp-business-account \
--id <waba-id> --region <region>
# Note phoneNumbers[].phoneNumberId
# What Connect holds
aws connect list-phone-numbers-v2 \
--instance-id <connect-instance-id> --region <region>
# Check SourcePhoneNumberArn — phone-number-id is embedded Fix: Release the number from Connect, then re-save the event destination in the Social console to re-trigger ImportPhoneNumber with the current ID. Re-attach the contact flow.
DependencyException: "Error while communicating with Meta"
AssociateWhatsAppBusinessAccount has two phases. Phase 1 (OAuth handshake)
almost always succeeds. Phase 2 (setupFinalization) fails with a 502 from
Meta for several reasons:
- Using a Meta-generated virtual number — Meta does not support connecting their virtual numbers to third-party Cloud API providers. Switch to Add a new number and provide a real phone number.
- WABA in a bad state from prior restriction or billing history — repeated failed attempts make this worse. Stop retrying and open an AWS Support ticket with the RequestID from the most recent DependencyException.
- Rate limiting — more than ~40
AssociateWhatsAppBusinessAccountcalls in a day triggers Meta's abuse detection. Stop all attempts and wait before retrying.
AssociateWhatsAppBusinessAccount deepens Meta's
rate limit window for this WABA. If you're hitting consistent DependencyExceptions
after checking all other causes, stop retrying and escalate to AWS Support.
Messages not arriving despite everything looking correct
If the WABA is COMPLETE, the event destination is enabled, and the phone
number is imported — but SendIntegrationEvent never fires — check for a
Condition block in the IAM role's trust policy.
A condition that looks valid (e.g., aws:SourceAccount) can silently block
sts:AssumeRole calls from social-messaging.amazonaws.com. The
trust policy should be exactly:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "social-messaging.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
} No conditions. If you added any, remove them and wait a few minutes for the policy to propagate.
WABA is Account Restricted
A restricted WABA blocks all three things needed for the integration: initiating conversations, responding to messages, and adding phone numbers. This is a Meta enforcement action — no AWS config change can unblock it.
Immediate restriction at account creation (with zero activity) is caused by the Business Portfolio's trust score, not a policy violation. Common triggers:
- The Business Portfolio has prior enforcement history from any associated asset (ad accounts, pages, apps)
- The admin's personal Facebook account is new, thin, or previously flagged
- The selected business category falls into a high-risk group (finance, healthcare, legal, real estate)
- No Business Verification, no verified domain, no ad spend history on the Portfolio
- Account created from an IP Meta associates with fraud or VPN traffic
What to do:
- Check Meta Business Manager → Account quality — if there is a "Request Review" button, submit an appeal with business documentation. This works even for "permanent" restrictions.
- Complete Business Verification: Meta Business Manager → Business Settings → Security Center → Start Verification.
- Verify your domain under Brand Safety → Domains.
- If the Portfolio itself is irrecoverable, create a new one under a clean, established Facebook admin account. A new WABA under a flagged Portfolio will be immediately restricted again.
Billing currency error: "WABA was previously billed in a currency other than USD"
AWS End User Messaging Social invoices in USD and pays Meta. Meta only allows a WABA's billing currency to be set once. If this WABA previously had messages billed in a non-USD currency through any provider, the currency is locked and AWS cannot assume billing.
There is no fix — Meta does not expose a "change billing currency" operation. Options:
- Create a brand new WABA under the same Business Portfolio, do not send any messages through another platform first, then link it to AWS. A fresh WABA will have its currency set to USD when AWS links it.
- Move the phone number to the new WABA in Meta Business Manager before linking to AWS, so customers keep the same number. Meta requires the number to be unregistered from the old WABA first.
400 error: "Value at roleArn failed to satisfy constraint"
This 400 validation error occurs when the service-linked role AWSServiceRoleForSocialMessaging is passed as the event destination role ARN.
Service-linked roles have a multi-segment path (role/aws-service-role/...)
that fails the API regex, which requires a single-segment path.
The two roles serve completely different purposes:
AWSServiceRoleForSocialMessaging— auto-created by AWS for its own internal operations (WABA linking, Meta sign-up plumbing). You cannot and should not use it as a delivery role.- Event destination role — a customer-managed role you create (Step 2 above) that Social Messaging assumes to call
connect:SendIntegrationEvent.
Fix: If you haven't already, create the customer-managed role from Step 2 and switch to Enter IAM role ARN in the console instead of using the dropdown.
Display name changed — number needs to be re-registered
After a WABA display name change is approved by Meta, you may see the following message in the AWS End User Messaging Social console or WhatsApp Manager:
Re-importing the phone number alone is not sufficient. Meta requires the phone number to be fully re-registered under the new display name, which means a complete unlink and re-link cycle through the embedded sign-up flow.
- In the AWS End User Messaging Social console, disassociate (unlink) the WABA.
- Click Link WABA and go through the embedded sign-up flow again. Pay close attention to select the exact same Business Profile, same WABA name, and the registered phone number — do not create new resources or choose a different number.
- Once the WABA is re-linked, release the phone number from Amazon Connect.
-
Re-import the phone number using
import-phone-number(see Step 6 above). - Re-attach the contact flow to the newly imported number.
Once the import completes successfully, the updated display name will be reflected in both WhatsApp Manager and the AWS End User Messaging Social console.
ImportPhoneNumber fails: phone number quota exceeded
Amazon Connect enforces a default limit of 5 phone numbers per instance.7
When this limit is reached, ImportPhoneNumber will fail. This typically
affects numbers that are not already present in your Connect phone
number list, or numbers listed as Display Only. If the WhatsApp
number already appears in your Connect phone number list (for example, previously
claimed as a voice DID), releasing it first and then re-importing it as a WhatsApp
channel works fine — releasing frees the slot before the import reclaims it. You may
also see this error the very first time you claim a number if the instance has a
pre-existing restriction, in which case only AWS Support can resolve it.
ImportPhoneNumber
regardless of your quota. You must register a real phone number through the
embedded sign-up flow to use the Connect integration.
How to check your current usage:
aws connect list-phone-numbers-v2 \
--instance-id <connect-instance-id> \
--region <region> \
--query 'length(ListPhoneNumbersSummaryList)' \
--output text Options to resolve:
- Release an unused number — if you have numbers in Connect that are
no longer in use, release one to free up the slot:
aws connect release-phone-number --phone-number-id <id> --region <region> - Request a quota increase — open the Service Quotas console or use the AWS CLI to request a higher limit for your Connect instance.8 This is a resource-level quota, so the increase applies to the specific instance ARN:
# Find the quota code for "Phone numbers per instance"
aws service-quotas list-service-quotas \
--service-code connect \
--region <region> \
--query 'Quotas[?contains(QuotaName, `Phone number`)].[QuotaName,QuotaCode,Value]' \
--output table
# Request an increase (replace quota-code and desired-value)
aws service-quotas request-service-quota-increase \
--service-code connect \
--quota-code <quota-code> \
--desired-value 10 \
--region <region> CLI reference
All commands use the account and region where both your Connect instance and WABA live. Substitute your own IDs — the values below are illustrative.
Inspect the Social Messaging side
aws socialmessaging list-linked-whatsapp-business-accounts --region <region>
aws socialmessaging get-linked-whatsapp-business-account \
--id waba-<your-waba-id> \
--region <region> Inspect the Connect side
aws connect list-phone-numbers-v2 \
--instance-id <connect-instance-id> \
--region <region> Full release + re-import sequence
# Release the existing voice claim
aws connect release-phone-number \
--phone-number-id <old-voice-phone-number-id> \
--region <region>
# Import the WhatsApp number — capture the returned PhoneNumberId
WHATSAPP_NUMBER_ID=$(aws connect import-phone-number \
--instance-id <connect-instance-id> \
--source-phone-number-arn "<social-messaging-phone-arn>" \
--phone-number-description "WhatsApp WABA" \
--region <region> \
--query 'PhoneNumberId' \
--output text)
# Confirm CLAIMED status
aws connect describe-phone-number \
--phone-number-id $WHATSAPP_NUMBER_ID \
--region <region>
# Attach the inbound contact flow
aws connect associate-phone-number-contact-flow \
--instance-id <connect-instance-id> \
--phone-number-id $WHATSAPP_NUMBER_ID \
--contact-flow-id <contact-flow-id> \
--region <region> Finding your IDs
| Value | How to find it |
|---|---|
--instance-id | Connect console → instance ARN, or aws connect list-instances |
| WABA ID | aws socialmessaging list-linked-whatsapp-business-accounts |
--source-phone-number-arn | get-linked-whatsapp-business-account → phoneNumbers[].arn |
--phone-number-id (release) | aws connect list-phone-numbers-v2 → PhoneNumberId |
--phone-number-id (describe/associate) | Returned by import-phone-number → PhoneNumberId |
--contact-flow-id | aws connect list-contact-flows --instance-id <id> |
References
- 1 AWS End User Messaging Social — What is AWS End User Messaging Social? AWS Documentation
- 2 Amazon Connect — Set up your Amazon Connect instance AWS Documentation
- 3 Getting started with WhatsApp in AWS End User Messaging Social AWS Documentation
- 4 Adding an event destination for a WhatsApp Business Account AWS Documentation
- 5 Amazon Connect WhatsApp integration — Prerequisites AWS Documentation
- 6 WhatsApp messaging capabilities in Amazon Connect AWS Documentation
- 7 Amazon Connect service quotas — Phone numbers per instance (default: 5, adjustable) AWS Documentation
- 8 Requesting a quota increase — AWS Service Quotas AWS Documentation
- 9 WhatsApp Calling — Business Messaging Meta for Developers
Did you find this guide helpful?