aethexDocs
WhatsApp logo
Telephony

WhatsApp

Answer WhatsApp on the number your customers already message. The agent that takes your voice calls replies to WhatsApp messages and, on a number that qualifies, answers WhatsApp calls too. This guide walks through connecting a number, what the agent does once it is live, and the parts Meta controls.

How it works

Connect a WhatsApp Business number once and map it to an agent. From then on the agent reads and replies to every message the number receives, transcribes voice notes, offers quick-reply menus, and sees delivery receipts. On a number Meta allows calls on, the same agent answers when a customer taps the call button and can place calls after asking permission.You also get a shared inbox where a person can take a conversation over and hand it back, approved templates for starting conversations, campaigns to a list, and one memory per customer that spans their chats and calls.

Note
WhatsApp is a Meta product. Each business keeps its own WhatsApp Business account and pays Meta directly: Meta bills the payment method on that account for conversations, and Aethex, as a Meta Tech Provider, has no credit line to extend. Meta sets the limits described below. Aethex connects the number and runs the agent.
BEFORE YOU START · 5 MIN

What you need

A Meta business. Your customer signs in with a Facebook account that administers their business portfolio. If they have none, Meta's dialog creates one as they go.A phone number that can take a verification code. Meta sends a six-digit code by SMS or voice call. The number must not be registered in the WhatsApp or WhatsApp Business phone app at that moment. If it is, delete the account in the app first, or use a spare number. A number already in a WhatsApp Business account with another provider can be picked in the dialog and moves to Aethex.An agent to answer. Any agent in your organisation, by its id (a UUID such as 3f6c2a1e-8b4d-4c7a-9e2f-5d1b0a7c6e94; list them with GET /agents). You can change it later with PATCH /whatsapp-accounts/{id}.A payment method, for business-initiated messages. Your customer adds one to their WhatsApp Business account in WhatsApp Manager. Replies inside the 24-hour window work without one.

Heads up
The number is taken out of the WhatsApp phone app for good. Customers keep messaging the same number; the agent answers instead of a handset.
STEP BY STEP · 10 MIN

Connect a number

There are two ways to connect a number, and which one fits depends on whose Meta app the number runs on.On Aethex's Meta app (most developers). Meta's signup dialog, Embedded Signup, only opens on web domains allowlisted on the Meta app it runs for, with no wildcards. So it cannot run on your site with Aethex's app. You create an onboarding session and send your customer to its link instead. An Aethex-hosted page runs Meta's dialog, connects the number to your organization and sends your customer back to you. Nothing to host, no webhook to wire, no token to handle. The steps below are this path.On your own Meta app. If you are a Meta Tech Provider with your own app and already manage your customers' WhatsApp Business accounts, link numbers with your own tokens. See Use your own Meta app.

Tip
Aethex keeps the number's access token and two-step PIN, both encrypted, so the agent keeps answering and a half-finished setup can resume; deleting the account removes them and releases the number. GET /whatsapp-accounts/embedded-signup/config and POST /whatsapp-accounts/embedded-signup are how the dialog is completed on Aethex's own domains, such as the Aethex platform; on any other domain Meta refuses the dialog, so use onboarding sessions.
  1. Create an onboarding session

    From your backend, POST /whatsapp-accounts/onboarding-sessions with the return_url your customer comes back to (HTTPS), an opaque state of your own, such as your customer's id, and the agent that should answer. The response carries url, a single-use link valid for 24 hours by default (expires_in_seconds, 5 minutes to 7 days). url is returned only here, so treat it as a secret until your customer uses it. Links can be created only by an organization with a payment method on file or a paid plan; otherwise the call returns 403 whatsapp_hosted_onboarding_requires_billing. A 503 with code whatsapp_hosted_onboarding_unavailable means hosted onboarding is not available on this deployment yet; nothing was created.

    bash
    curl -X POST 'https://api.aethexai.com/api/v1/whatsapp-accounts/onboarding-sessions' \
      -H "X-API-Key: $AETHEX_API_KEY" -H "Content-Type: application/json" \
      -d '{"return_url": "https://app.example.com/whatsapp/connected", "state": "customer-8841",
           "default_agent_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b0a7c6e94"}'
    
    # {"id": "b2f0c9e4-...", "status": "pending",
    #  "url": "https://api.aethexai.com/whatsapp/onboarding#k3J...", "expires_at": "2026-10-01T09:00:00Z", ...}
  2. Send your customer to the link

    Redirect them to url, or email it to them. The page names your organization, opens Meta's dialog, where your customer signs in with Facebook and picks or creates their business and number, and connects the number the moment the dialog closes. If something fails, such as a number locked by another provider's two-step PIN, the page says why and your customer can try again on the same link until it expires. Each try runs Meta's dialog again: its code is what proves your customer controls the number.

  3. Pick up the result

    When it is done, your customer is sent to return_url with whatsapp_onboarding_session, status (completed, or cancelled if they chose to go back), whatsapp_account_id and your state. The URL carries no secret. Two confirmations don't depend on the browser. The agent's webhook receives a signed whatsapp.onboarding.completed event with the same ids. GET /whatsapp-accounts/onboarding-sessions/{id} returns pending (with the last error, if an attempt failed), completed or expired.

    bash
    # Your customer lands on:
    # https://app.example.com/whatsapp/connected?whatsapp_onboarding_session=b2f0c9e4-...
    #   &status=completed&whatsapp_account_id=9d2e6b7a-...&state=customer-8841
    
    curl 'https://api.aethexai.com/api/v1/whatsapp-accounts/onboarding-sessions/b2f0c9e4-...' -H "X-API-Key: $AETHEX_API_KEY"
    
    # {"status": "completed", "whatsapp_account_id": "9d2e6b7a-...", "state": "customer-8841", ...}
  4. Check the number

    GET /whatsapp-accounts/{id}/health reads Meta's view of the number: status, quality rating, messaging limit, webhook subscription, and any problem in plain words. Poll it after connecting and show it to your users.

    bash
    curl 'https://api.aethexai.com/api/v1/whatsapp-accounts/9d2e6b7a-.../health' -H "X-API-Key: $AETHEX_API_KEY"
    
    # {"status": "CONNECTED", "quality_rating": "GREEN", "messaging_limit_tier": "TIER_250",
    #  "webhook_subscribed": true, "calling_enabled": false, "calling_status": "NOT_SET",
    #  "problems": ["Meta will not switch calling on for this number until its daily
    #   messaging limit reaches 2,000 unique customers (it is TIER_250 today); ..."]}
YOUR OWN META APP · 15 MIN

Use your own Meta app

For a Meta Tech Provider running its own Meta app, whose customers' WhatsApp Business accounts are shared with that app. Aethex uses the number with your app's token, signs every call with your app's secret, and receives the number's messages and calls on a URL of its own. Your app keeps getting everything else.

Heads up
Template reviews and account-level events (message_template_status_update, account_update, account reviews and alerts) always go to your app's own callback, because Meta does not route them per number. Your app receives them as it does today. Disconnecting the number hands its messages and calls back to your app.
  1. Create a system-user token

    In Meta Business Manager, create a system user on your business with access to the customer's WhatsApp Business account, and generate a token for your app. Choose no expiry, with business_management, whatsapp_business_management and whatsapp_business_messaging. Copy your app's secret from App Dashboard > App settings > Basic.

  2. Link the number with your token and app secret

    POST /whatsapp-accounts with the waba_id, phone_number_id, access_token and app_secret, and registration_pin (six digits) if the number is not yet registered for the Cloud API. Aethex asks Meta which app issued the token and proves the secret is that app's before anything is stored. A wrong secret fails with whatsapp_app_secret_mismatch, and a token from your app sent without its secret fails with whatsapp_app_secret_required. Aethex then subscribes your app to the WhatsApp Business account and routes the number's messages and calls to webhook_callback_url, a URL for this number alone. The response shows webhook_verify_token once; Aethex keeps only a hash of it.

    bash
    curl -X POST 'https://api.aethexai.com/api/v1/whatsapp-accounts' \
      -H "X-API-Key: $AETHEX_API_KEY" -H "Content-Type: application/json" \
      -d '{"waba_id": "1613686663727049", "phone_number_id": "1210656312140303",
           "access_token": "EAAG...", "app_secret": "your-meta-app-secret",
           "default_agent_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b0a7c6e94"}'
    
    # {"id": "9d2e6b7a-...", "status": "active", "link_method": "byo", "meta_app_id": "1043210987654321",
    #  "webhook_callback_url": "https://api.aethexai.com/whatsapp/webhook/9d2e6b7a-...",
    #  "webhook_verify_token": "q8Vn...", ...}
  3. Subscribe your app to messages and calls

    Meta only sends a webhook for a field your app subscribes to. In App Dashboard > WhatsApp > Configuration, your app needs a webhook and a subscription to messages, plus calls if the number takes calls. Your app's callback stays your own server: the route Aethex set applies to this number only. If your app has no webhook yet and this is its only number, you can use webhook_callback_url with the verify token from the link response, or a fresh one from POST /whatsapp-accounts/{id}/webhook/verify-token. That URL answers for this number alone, so an app with several numbers needs its own callback.

  4. Check the wiring

    GET /whatsapp-accounts/{id}/webhook reads from Meta where the number's messages actually go, and which fields your app subscribes to. problems names anything missing. The health endpoint lists the same problems.

    bash
    curl 'https://api.aethexai.com/api/v1/whatsapp-accounts/9d2e6b7a-.../webhook' -H "X-API-Key: $AETHEX_API_KEY"
    
    # {"mode": "own_app", "callback_url": "https://api.aethexai.com/whatsapp/webhook/9d2e6b7a-...",
    #  "required_fields": ["messages", "calls"], "meta_routed_to": "https://api.aethexai.com/whatsapp/webhook/9d2e6b7a-...",
    #  "meta_subscribed_fields": ["messages"], "problems": ["Your Meta app does not subscribe to calls: ..."]}

What you get

One agent across voice and WhatsApp. It replies to messages, answers and places calls where the number allows it, and hands off to a person when asked. The health endpoint gives you Meta's view of the number: status, quality rating, current messaging limit, and any problem in plain words, such as a rejected access token, a red quality rating or a webhook that is not subscribed.

Note
Shortly after linking, Meta sends the number a notice about finishing its own setup. It shows up as a message from Meta and can be ignored.

Messaging

Replies. When a customer writes in, the agent replies as itself; nothing is required from you. Meta allows free-form replies for 24 hours after the customer's last message. Outside that window only an approved template can reach them, which is how a conversation is started rather than continued.Voice notes are transcribed and answered like text. Menus: when the agent offers choices they render as quick-reply buttons, and POST /whatsapp-accounts/{id}/messages/options sends one yourself. Receipts: sent, delivered and read are recorded per message and delivered to your webhook as whatsapp.message.status.What you see. Every conversation is readable through the inbox endpoints below, and your webhook receives whatsapp.message.status for receipts, whatsapp.handoff.requested when a customer asks for a person, whatsapp.template.status when Meta rules on a template, and whatsapp.onboarding.completed when a customer finishes an onboarding link.Opting out. There is no automatic STOP keyword yet. A customer who asks not to be contacted is handled by the agent in conversation, and you keep them off campaign lists yourself.

Note
Business-initiated messages, including templates and campaigns, need a payment method on the WhatsApp Business account in Meta Business Manager. Replies inside the 24-hour window work without one.

Inbox and human handoff

Every customer has one thread per number. GET /whatsapp-accounts/{id}/threads lists them with unread counts and GET …/threads/{thread_id}/messages is the full timeline across chats and calls, in one order.To let a person take over, POST …/threads/{thread_id}/mode with human: the agent goes quiet, new customer messages are stored and raised as whatsapp.message.received, and your operator replies with POST …/threads/{thread_id}/messages (free text inside the 24-hour window) or …/messages/template at any time. Set the mode back to agent to resume with full context. A customer who asks for a person, using phrases the deployment configures, is handed off automatically and whatsapp.handoff.requested reaches your webhook.

Templates and campaigns

Templates are messages Meta approves in advance, with placeholders you fill at send time. Create one with POST /whatsapp-accounts/{id}/templates; list and delete with GET and DELETE on the same path. Meta's decision arrives as whatsapp.template.status, and an approved template is sent with POST /whatsapp-accounts/{id}/messages, inside or outside the 24-hour window.Campaigns send an approved template to a list. POST /whatsapp-accounts/{id}/campaigns validates every recipient row against the template's placeholders before anything is sent, sending runs at the rate_per_minute you set, and you can pause, resume or cancel between messages. Each recipient carries its own delivery status. Campaigns can be scheduled.

Calls

Inbound. When calls are on, customers see a call button in the chat. Tapping it rings the agent, which answers with the same voice it uses on the phone.Outbound. WhatsApp only connects a business's call to someone who has allowed that business to call them, and POST /whatsapp-accounts/{id}/calls handles both halves. If they already allow calls, it rings them now. If not, pass permission_template — an approved template with a call-permission request — and they are sent the request; the call is placed the moment they tap Allow. Inside their 24-hour window, request_permission: true asks with the free-form request instead. To call a whole list, send POST /calls/batch with whatsapp_params. Meta does not allow business-initiated calls from numbers registered in Nigeria, the United States, Canada, Egypt or Vietnam; the person you call can be anywhere, and inbound calls work everywhere. A number whose calling is off at Meta is refused up front too (whatsapp_calling_off), before anyone is asked to allow a call it could not place.Turning calls on. Calling is a switch Meta keeps for each number, and Aethex asks Meta to turn it on as the number connects. Meta only agrees once the number's daily messaging limit has reached 2,000 unique customers. A newly connected number starts at 250 and grows as the business is verified and the number keeps messaging, so on a new number the link succeeds, messaging works, and calling_enabled on the number reads false until the limit has grown; the health endpoint says why. When Meta raises the limit to 2,000 or more, Aethex switches calling on by itself for every number that was never switched on; a number someone switched off stays off. To ask again sooner, use POST /whatsapp-accounts/{id}/calling and Meta's answer comes straight back.

Heads up
calling_enabled on the number and in its health is true only when Meta has calling switched on for the number and this deployment allows calls. calling_status is Meta's own word for the switch: ENABLED, DISABLED (someone switched it off in WhatsApp Manager) or NOT_SET (never switched on). Health reads it fresh from Meta, and Meta's settings-update webhook keeps the stored copy current. On a self-hosted deployment calling is also a deployment switch, app.whatsapp.callingEnabled in the chart; while it is off, inbound calls are refused and outbound calls return 409 whatever the number's limit.

One memory across chats and calls

The agent remembers each customer on a number across everything they have done with it, typed or spoken. A call opens as a continuation of the chat, and a message sent during or straight after a call sees what was said on it, including the outcome of anything the agent booked. Memory is per agent and per number: pointing the number at another agent starts fresh, and the same person on two of your numbers is two customers.

What Meta controls

Three things sit with Meta, not Aethex.Business verification in Meta Business Manager raises the messaging limit and is the gate to calling. The current limit is in the health response.Payment method on the WhatsApp Business account. Meta bills each business directly, and without one, templates and campaigns are refused; health lists it under problems as Meta error 141006. Aethex, as a Meta Tech Provider, has no credit line to share, so every business adds its own in WhatsApp Manager.Quality rating, which Meta derives from how customers react. A red rating lowers the limit and is surfaced as a problem in the health response.

Daily limitHow a number gets thereWhat it means
250 business-initiated conversationsEvery new number, business not yet verifiedReplies unlimited; templates and campaigns capped; calls unavailable
1,000Business verified, display name approvedCampaigns to a small list; calls still unavailable
2,000 and aboveVerified business with sustained good-quality messagingCalls can be switched on; limit keeps rising with volume

Two-step verification PIN

Every WhatsApp Business number carries a six-digit two-step verification PIN, and Meta asks for it whenever the number is registered.When Aethex connects a number, it sets the PIN and keeps it, encrypted, even after the number is disconnected. Your organization can disconnect a number and connect it again without any extra step.The PIN stays on the number when it leaves, and Aethex never hands one organization's PIN to another. So if the number was last connected by another organization or another provider, or someone set the PIN in WhatsApp Manager, connecting fails with a message that links here.To fix it, the number's owner turns two-step verification off. In WhatsApp Manager in Meta Business Manager, open Phone numbers, select the number, open Two-step verification, and turn it off. Then connect the number again, and Aethex sets a new PIN as it connects. Changing the PIN instead does not help, because Aethex connects with a PIN of its own. Meta requires this whenever a number moves between businesses or providers, and only the owner can do it.

WHEN SOMETHING IS OFF

Troubleshooting

Most problems are visible on the number's page under health. problems lists Meta's own reasons first, each with Meta's suggested fix and error code, then what Aethex checks itself; meta_checks has the same per entity (number, WhatsApp Business account, business). These are the cases that come up most.

SymptomCause and fix
The dialog says the number is already in useIt is registered in the WhatsApp phone app, or in another WhatsApp Business account. Delete the account in the app, or pick the existing business account in the dialog so the number moves.
Connecting returns 409 whatsapp_number_already_linkedIt is connected to this organization already, so list it with GET /whatsapp-accounts, or to another Aethex organization, which has to disconnect it first.
Connecting returns 422 validation_errorThe body did not validate; fields names the field. The usual cause is default_agent_id, which must be an agent's id (a UUID such as 3f6c2a1e-8b4d-4c7a-9e2f-5d1b0a7c6e94), not a name or a placeholder. Omit it to connect without an agent and set one later.
Connecting returns 422 whatsapp_app_secret_required or whatsapp_app_secret_mismatchThe token was issued by your own Meta app. Send that app's secret as app_secret, from App Dashboard > App settings > Basic of the app the system user belongs to. A mismatch means the secret is another app's.
Creating an onboarding session returns 503 whatsapp_hosted_onboarding_unavailableHosted onboarding is not available on this deployment yet. Nothing was created. Retry later, or link numbers you manage yourself with POST /whatsapp-accounts.
Connecting returns 422: the number's two-step verification must be turned offThe number was last connected by another organization or provider, or someone set its PIN in WhatsApp Manager. The owner turns two-step verification off as described in Two-step verification PIN, then you connect again.
The verification code does not arriveMeta limits attempts per number per day. Wait, then choose the voice-call option instead of SMS.
Display name shows as in reviewNormal for a new number and usually cleared within a day. Most numbers message meanwhile, and customers see the number until the name is approved. A number Meta provided, such as a free +1 555 test number, cannot reply until the name is approved: messages arrive and are marked read, but every reply is refused.
Messages show as read but the agent never repliesOn a number Meta provided, such as a free +1 555 test number, Meta refuses every reply until the display name is approved (error 131037). Each refused reply is kept in the thread with delivery_status failed and Meta's reason in delivery_error, and the health response counts them in undelivered_24h and lists the latest reason under problems. Wait for the approval, or connect a number of your own.
Health reports the number as DISCONNECTEDIt can neither send nor receive. Connect it again; if that returns the two-step verification error, follow Two-step verification PIN.
Health reports the number as BANNED, or templates are refused because the account is restrictedMeta rejected the WhatsApp Business account in its review, usually because it was created for a business Meta cannot match to a real one; health lists it first as account_review_status REJECTED. Connecting again does not help. Request a review under Account quality in WhatsApp Manager, or connect a different number under a business Meta can verify. In Meta's window, pick the existing business portfolio rather than creating a new one.
Replies work but templates and campaigns are refusedNo payment method on the WhatsApp Business account. Open WhatsApp Manager in Meta Business Manager, add one under Payment settings, and retry. The health endpoint lists it under problems as Meta error 141006.
No call button in the customer's chatCalling is not switched on at Meta for this number, and health says why. Usually the daily limit is still below 2,000: verify the business and keep messaging. Calling switches on by itself once Meta raises the limit, or ask again with POST …/calling. calling_status: DISABLED means someone switched it off in WhatsApp Manager.
Customers write in but the agent never answersCheck webhook_subscribed and problems in the health response. On Aethex's app, deleting the account and connecting the number again restores the subscription. On your own app, GET /whatsapp-accounts/{id}/webhook shows where Meta sends the number's messages and which fields your app subscribes to.
The agent replied to a message from MetaMeta's own setup reminders arrive as messages to the number. Harmless; nothing is sent to a customer.

API reference

For the connect, template, messaging, inbox, calling and campaign calls, see the WhatsApp API reference. Events the channel emits are listed under Webhooks.

Note
Use the Aethex platform rather than the API? Its own guide walks through the same connection from Integrations → WhatsApp, with the inbox, templates and recordings: WhatsApp on the Aethex platform.