At a glance
Capabilities
What you need
- A WhatsApp Business phone number that is not registered on the consumer WhatsApp app. A number the business uses in the WhatsApp Business app can keep running there, see Keep using the WhatsApp Business app. During Embedded Signup you can select an existing number or create one.
- Admin access to a Meta Business (business.facebook.com).
Connecting
WhatsApp connects like every other platform with a consent screen: your backend asks for anauth_url, you send your customer there, and they come back to your redirect_uri with the connected account. Meta’s signup runs on Meta’s own pages, so there is nothing to embed or host on your side and no domain to register: it works from any domain. Your API key stays on your backend the whole time. (You can also connect from our dashboard.)
1. Get the signup link (your backend)
redirect_uri: it is where your customer lands with the result, and the only way to receive the number choice described below. See Redirect URI rules. state is optional and comes back unchanged on the redirect.
onboarding picks the signup Meta shows:
2. Send your customer to auth_url (browser)
Redirect the browser to auth_url, or open it in a new tab. Your customer signs in with Facebook, picks or creates their business portfolio, WhatsApp Business Account and phone number, and verifies the number if it is new.
3. Read the result on your redirect_uri
On success, your customer lands on your redirect_uri with the account appended:
account_id is the ID every WhatsApp call takes from here on. The number’s messages now flow into your inbox.
On failure, the redirect carries status=error with error and error_description. The WhatsApp-specific values are:
See Redirect parameters for the full list.
Choose a number
When the WhatsApp Business Account holds more than one phone number, the redirect carriesstatus=selection_required and a connection_id instead of an account_id. Read the numbers with GET /v1/accounts/pending/{connection_id}:
profiles is one number: platform_account_id is its phone number ID, display_name the verified business name, and username the phone number. Connect one with POST /v1/accounts/pending/{connection_id}/select:
Keep using the WhatsApp Business app
To connect a number the business already uses in the WhatsApp Business app, and keep using it there, send"onboarding": "business_app" in step 1. Meta then walks your customer through linking the app, including scanning a QR code with their phone. The phone needs WhatsApp Business app 2.24.17 or later, and Meta decides during signup whether the number is eligible.
Once the number is connected:
- The chat history the business chooses to share in the app (up to six months) appears in its conversations as WhatsApp delivers it. Imported messages raise no webhook events, and their attachments carry
attachment_typewithout anattachment_url. - Messages the business sends from the phone app appear in the conversation and raise
dm.sent, like messages sent through the API. - Sending is capped at 20 messages per second, Meta’s fixed limit for these numbers.
- The number is already registered, so you never call
registerfor it.statusreports it as registered, andregisterrefuses it with409 whatsapp.business_app_number. - The
deregisterendpoint does not work for these numbers. The business disconnects the number from the WhatsApp Business app’s settings.
The 24-hour service window
WhatsApp only lets a business send free-form messages within 24 hours of the customer’s most recent message. Each new inbound message from that customer resets the 24-hour timer.- Inside the window: you can send a free-form text reply from the inbox.
- Outside the window: free-form replies are rejected with
whatsapp.window_closed. To reach the customer, send an approved message template withsend-template(see Message templates below), which is allowed at any time.
Message templates
Templates are pre-approved messages you can send outside the 24-hour window (order updates, authentication codes, and the like). You create, manage, and send them entirely through the API, scoped to a connected account.Create a template
PENDING; Meta reviews it and the status moves to APPROVED or REJECTED asynchronously. category is one of UTILITY, MARKETING, or AUTHENTICATION (marketing content in a UTILITY template is auto-rejected). Call POST /v1/platforms/whatsapp/templates/validate first to catch field-level problems before you submit.
Send a template
to is E.164 without the leading +. The template must already be APPROVED and language must match an approved variant. This send is allowed whether or not the 24-hour window is open, and the message is recorded in the inbox thread. On the Free plan the request returns 403 whatsapp.paid_plan_required and nothing is sent. Replies to people who messaged you work on every plan. See Plans.
The response includes message_id, the SocialAPI message ID for the send, alongside WhatsApp’s own messages[].id (the wamid). message_id is the same value that arrives as id on the dm.status.sent, dm.status.delivered, dm.status.read, and dm.status.failed webhooks for this message, so you can bind a delivery receipt to the row you created without matching on the wamid.
Listing, editing, and deleting templates, plus phone-number management (request-code, verify-code, register, deregister, status) and the business profile, are also available. See the API reference for the full set of /v1/platforms/whatsapp endpoints and their schemas.
Receiving and replying
WhatsApp has no message-history API, so the inbox covers messages from connect time onward. The exception is a number connected from the WhatsApp Business app, which also brings the chat history the business chooses to share (see Keep using the WhatsApp Business app).List DM conversations
Reply to a message
account_id is required. The reply only succeeds while the 24-hour service window is open.
Sending media
Attach media with theattachments array, either a url WhatsApp can fetch or a media_id from your media library:
file and anything we cannot classify are sent as a document, with the filename taken from the URL’s last path segment. A caption is supported on image, video, and document; on audio it is rejected, since WhatsApp has no caption there.
A url attachment is fetched by WhatsApp’s own servers, so it must be publicly reachable without authentication (a media_id always is). WhatsApp’s limits apply: images 5 MB (JPEG, PNG), video 16 MB (MP4, 3GPP), audio 16 MB (AAC, AMR, MP3, M4A, OGG), documents 100 MB. A file it cannot fetch, or one over a limit, returns whatsapp.media_download_failed.
source_type: "platform_attachment_id" is not supported on WhatsApp.
Interactive messages
Send up to 3 reply buttons, or a list of up to 10 rows, so the recipient answers by tapping instead of typing. Both needtext, which becomes the message body.
Every button carries a payload (a row carries an id) that you choose. WhatsApp never interprets it: it is echoed back to you untouched when the recipient taps, so use it as your own routing key.
list_button is the label on the button that opens it:
list_button 20, and 10 rows in total across at most 10 sections. Payloads and row ids must be unique within a message, since a tap echoes only the id. Buttons and list_sections are mutually exclusive, and neither can be combined with an attachment.
quick_replies and cards are Instagram and Facebook only; sending them to WhatsApp returns a validation error rather than silently dropping them. A url button is available on templates, not on interactive messages.
Interactive messages are free-form, so they are subject to the 24-hour service window. To open a menu outside it, send an approved template with QUICK_REPLY buttons instead; taps on those reach your webhook the same way.
Receiving taps
A tap is delivered as an ordinarydm.received event, not a separate event type: on WhatsApp the tapped title is posted into the conversation as the contact’s own message, and it opens the 24-hour window like any inbound message. The payload you set rides on the event’s metadata:
interactive_type is button_reply (a reply button), list_reply (a list row), or button (a template quick reply). Both fields are absent on an ordinary message, so switch on metadata.payload when it is present and treat the message as text otherwise.
Inbound media
WhatsApp exposes inbound media only to the connected account, never to an external caller, so it cannot be linked directly. For WhatsApp (and Telegram),messages.attachment_url is a SocialAPI URL (/v1/inbox/media/{id}) that you retrieve with your API key, unlike the other connectors where attachment_url is the platform’s own URL. See Inbox media for the endpoint and its response codes.
Errors
See Errors for the full catalog.