Skip to main content
Messaging connector. WhatsApp is a DM-only connector: you connect a WhatsApp Business phone number through Meta’s Embedded Signup, then use our unified inbox to receive and reply to the messages that number gets. There are no posts, comments, reviews, or mentions.

At a glance

Capabilities

What you need

  • A WhatsApp Business phone number that is not currently registered on the consumer WhatsApp or WhatsApp Business apps. During Embedded Signup you can select an existing number or create one.
  • Admin access to a Meta Business (business.facebook.com).
You do not need to submit your own Meta App Review or complete business verification to connect. We are the Tech Provider, so the app review and provider-side setup are handled on our side. The person connecting signs in with their Meta Business account, picks their WhatsApp Business Account and phone number, and the number is connected.

Connecting

WhatsApp uses Meta’s Embedded Signup, a three-leg flow that you drive from your own backend and frontend with your API key. Your customer only ever interacts with Meta’s hosted popup; your API key stays server-side the whole time. (You can also connect from our dashboard, which runs this same flow for you.)

Leg 1: start the connection (your backend)

Response (HTTP 202):
The metadata is exactly what Meta’s JavaScript SDK needs to launch the popup. Pass state through to your frontend, hold onto it for leg 3. solution_id can come back empty. That is expected: it is optional, and when it is empty you omit the extras object from the FB.login call in leg 2. The rest of the flow is unchanged.

Leg 2: launch the Meta popup (browser)

Load Facebook’s JavaScript SDK and call FB.login with the config_id and solution_id from leg 1:
As the customer completes the popup, Meta fires the WA_EMBEDDED_SIGNUP message event carrying their waba_id and phone_number_id. Capture the code and both IDs, and send them to your backend. See Meta’s Embedded Signup docs for the exact SDK and event wiring.

Leg 3: complete the connection (your backend)

We validate state against the one we issued to your API key, exchange the code for the customer’s token, store the account, and return HTTP 201 with the connected account. The number’s messages now flow into your inbox.

Registering your domain

The popup runs against our Meta app, and Meta’s Login-for-Business SDK enforces an allowlist of domains that are permitted to launch it. To run FB.login from your own domain (for example, app.yourcompany.com), we have to register that domain in our Meta app first, so contact us to add it. If you would rather not host the popup yourself, connect from our dashboard instead. It runs the flow on our domain and works for any customer without a per-domain step.

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 with send-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

A new template starts in 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. 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 we build the inbox from inbound webhook events from connect time onward. There is no backfill of messages sent before you connected.

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 the attachments array, either a url WhatsApp can fetch or a media_id from your media library:
WhatsApp has no generic attachment type, so 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 need text, 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.
For more than 3 options, send a list instead. list_button is the label on the button that opens it:
Limits: button titles 20 characters, row titles 24, row descriptions 72, 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 ordinary dm.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

When a customer sends a photo, voice note, or other attachment, WhatsApp’s webhook hands us a media id, not a URL, and that id is redeemable only with the connected account’s own access token, not your API key. So for WhatsApp, and only WhatsApp, we fetch the bytes ourselves and mirror them into SocialAPI’s storage: messages.attachment_url on a WhatsApp message is a SocialAPI URL (/v1/inbox/media/{id}) that you retrieve with your API key, unlike every other connector 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.