aethexDocs

API Reference

WhatsApp

Connect a WhatsApp Business number, through a hosted onboarding link or your own Meta app, let your agent answer it, manage templates, reply as a person, and run campaigns.

Base URL
https://api.aethexai.com/api/v1
Endpoints
41
Scopes
whatsapp_accounts:readwhatsapp_accounts:writewhatsapp_messages:writewhatsapp_inbox:readwhatsapp_inbox:write
POST/whatsapp-accounts/onboarding-sessions

A single-use link your customer opens to connect their WhatsApp number to your organization.

Create an onboarding link

Meta runs its signup dialog only on domains allowlisted on the Meta app, so it cannot run on your site with Aethex's app. Send your customer to url instead. An Aethex-hosted page runs Meta's dialog, connects the number to your organization with the agent you chose, and sends your customer to return_url with whatsapp_onboarding_session, status, whatsapp_account_id and your state. The agent's webhook receives a signed whatsapp.onboarding.completed event. url is returned only in this response and its secret is stored hashed. The link can be retried until it completes or expires. Links stop working if your organization's account is closed or suspended: they then answer like a link that does not exist.

Request body

5
  • return_urlstring (https URL)required

    Where your customer is sent back, finished or cancelled. HTTPS, with no credentials or #fragment. Aethex adds whatsapp_onboarding_session, status, whatsapp_account_id (when completed) and state.

  • statestringoptional

    Opaque value of yours (up to 512 characters), returned unchanged on return_url and in the event, such as your customer's id.

  • default_agent_idstring (uuid)optional

    The agent that answers messages and calls on this number.

  • labelstringoptional

    A name for this number in your own dashboard. Never shown to customers.

  • expires_in_secondsintegeroptional

    How long the link works: 300 to 604800 seconds (5 minutes to 7 days). Default 86400 (24 hours).

Errors

3
403Not allowed

Code whatsapp_hosted_onboarding_requires_billing: your organization has no payment method on file and is not on a paid plan. The page names your organization on Aethex's domain, so only an accountable account may issue links.

Add a payment method in Billing, or move to a paid plan, then create the link again.

422Invalid request

return_url is not an absolute HTTPS URL, default_agent_id is not a UUID, or expires_in_seconds is out of range.

Correct the field named in fields and send it again.

503Unavailable

Code whatsapp_hosted_onboarding_unavailable: hosted onboarding is not available on this deployment yet. Nothing was created.

Retry later, or link numbers you manage yourself with POST /whatsapp-accounts.

GET/whatsapp-accounts/onboarding-sessions/:session_id

Pending, completed or expired, with the connected number when it completed.

Get an onboarding link's status

The fallback to the redirect and the event. pending carries last_error_code and last_error_message when the customer's latest attempt failed; the link still works until expires_at. last_error_code is one of the connect refusal codes (such as whatsapp_pin_locked, whatsapp_registration_throttled, whatsapp_signup_code_rejected, whatsapp_token_rejected or whatsapp_meta_rejected), or whatsapp_meta_unreachable when Meta could not be reached, in which case trying again usually succeeds. completed carries whatsapp_account_id. url is always null here.

Path & Query

1
  • session_idstring (uuid)required

    The onboarding session's id.

Errors

1
404Not found

No session with this id in your organization.

Use the id from the create response or the whatsapp_onboarding_session parameter on return_url.

POST/whatsapp-accounts/embedded-signup

Redeem the code Meta's dialog returned, when the dialog ran on an Aethex domain.

Complete Embedded Signup on Aethex's domains

Meta returns the dialog's code only to a page on a domain allowlisted on the Meta app, which for Aethex's app means Aethex's own domains, such as the Aethex platform. From anywhere else, create an onboarding link instead. Post the single-use code with the WABA and phone number the customer picked. Aethex exchanges the code, registers the number on the Cloud API, subscribes the WABA to webhooks, and the mapped agent starts answering.

Request body

5
  • codestringrequired

    The single-use code from Meta's dialog (a bearer credential — never log it).

  • waba_idstringrequired

    The WhatsApp Business Account the number belongs to.

  • phone_number_idstringrequired

    Meta's id for the phone number.

  • default_agent_idstring (uuid)optional

    The agent that answers messages and calls on this number.

  • labelstringoptional

    A name for this number in your own dashboard. Never shown to customers.

Errors

3
422Invalid request

The code was already used, expired, or does not cover the number.

Codes work once, for 30 seconds after the dialog closes, and only for the Meta app that opened it: run the dialog again and post the new code straight away. The code field of the error says which case it was, such as whatsapp_signup_code_rejected or whatsapp_pin_locked.

422Invalid request

whatsapp_onboarding_unconfigured: self-serve onboarding is not configured on this deployment, so the code cannot be redeemed.

Link numbers you manage yourself with POST /whatsapp-accounts, or ask the operator to configure onboarding.

409Conflict

whatsapp_number_already_linked: the number is already connected, to this organization (including by another request of yours that finished first) or to another Aethex organization. whatsapp_link_abandoned: this link was released or expired while it ran.

If this organization has it, GET /whatsapp-accounts lists it and there is nothing to link again. Otherwise the organization that has it must disconnect it first. For whatsapp_link_abandoned, connect the number again.

GET/whatsapp-accounts/embedded-signup/config

The Meta app and configuration ids your front end needs to launch the signup dialog.

Get the embedded-signup settings

What a page on an Aethex domain passes to the Facebook JavaScript SDK to open Meta's dialog: the app id, configuration id and Graph version. On any other domain Meta refuses to open the dialog with these ids, so use POST /whatsapp-accounts/onboarding-sessions. enabled: false means Embedded Signup is not configured on this deployment.

POST/whatsapp-accounts

Link a Cloud API number with a system-user token from your own Meta app, and that app's secret.

Connect a number on your own Meta app

For a Meta Tech Provider with its own Meta app, linking a WhatsApp Business account shared with that app. Before anything is stored, Aethex asks Meta which app issued the token (GET /app) and proves app_secret is that app's secret. It then subscribes the WABA, checks the number belongs to it, registers it when you send registration_pin, and routes the number's messages and calls to webhook_callback_url, a URL of its own, using Meta's per-number override. The response shows webhook_verify_token once. Your app must subscribe to messages, and to calls for calling (see GET /whatsapp-accounts/:account_id/webhook). The token and app secret are write-only: stored encrypted and never returned.

Request body

7
  • waba_idstringrequired

    The WhatsApp Business Account the number belongs to.

  • phone_number_idstringrequired

    Meta's id for the phone number.

  • access_tokenstringrequired

    Long-lived system-user token from your Meta app with business_management, whatsapp_business_management and whatsapp_business_messaging. Stored encrypted, never returned.

  • app_secretstringoptional

    Secret of the Meta app that issued access_token (App Dashboard > App settings > Basic). Required for a token from your own app: every Graph call for the number is signed with it and its webhooks are verified against it. Omit only for a token issued by Aethex's app. Stored encrypted, never returned.

  • default_agent_idstring (uuid)optional

    The agent that answers messages and calls on this number.

  • labelstringoptional

    A name for this number in your own dashboard. Never shown to customers.

  • registration_pinstringoptional

    Six-digit two-step PIN. Supply it to register the number for Cloud API as part of connecting.

Errors

5
422Invalid request

Meta rejected the token (whatsapp_token_invalid, whatsapp_token_rejected), the number is not in that WABA (whatsapp_number_not_in_waba) or not registered for the Cloud API (whatsapp_number_not_registered), or Meta refused another step (whatsapp_meta_rejected, with Meta's words).

Act on the code and message: issue a new system-user token with the permissions above, check both ids in WhatsApp Manager, or send registration_pin.

422Invalid request

whatsapp_app_secret_required: the token is from your own Meta app and no app_secret was sent. whatsapp_app_secret_mismatch: the secret belongs to another app.

Send the secret of the app the system user belongs to.

422Invalid request

whatsapp_no_signing_secret: no app_secret was sent and this deployment has no platform secret to verify the number's webhooks with. whatsapp_webhook_route_failed: Meta would not send your own-app number's webhooks to Aethex.

Send your app's app_secret. For a routing refusal, give your Meta app the WhatsApp product with a webhook configured, then link again: the number stays unlinked until routing succeeds, and the retry resumes this link.

422Invalid request

validation_error: the body did not validate, and fields names the field. A common cause is a default_agent_id that is not a UUID.

Send an agent's id (list them with GET /agents), or omit it and set it later with PATCH.

409Conflict

whatsapp_number_already_linked: the number is already connected, to this organization (including by another request of yours that finished first) or to another Aethex organization. whatsapp_link_abandoned: this link was released or expired while it ran.

If this organization has it, GET /whatsapp-accounts lists it and there is nothing to link again. Otherwise the organization that has it must disconnect it first. For whatsapp_link_abandoned, connect the number again.

GET/whatsapp-accounts/:account_id/webhook

Where Meta sends the number's messages, and what your Meta app still needs.

Check a number's webhook

mode: platform_app is a number on Aethex's Meta app, with nothing to configure. mode: own_app is a number on your own app. callback_url is the number's own Aethex URL, and three fields are read live from Meta: meta_routed_to (where Meta sends the number's messages), meta_subscribed_fields (your app's webhook fields) and problems (anything missing, such as routed elsewhere, a field not subscribed, or no webhook at all). required_fields lists what the number needs.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/webhook/verify-token

A new verify token for the number's own webhook URL, shown once.

Rotate a number's webhook verify token

For a number on your own Meta app. The previous token stops working, and Aethex routes the number to callback_url again under the new one. Use it where you configure a callback yourself. Your app's own callback in App Dashboard may point at callback_url only when this is the app's only number, because the URL answers for this number alone. Aethex keeps only a hash.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

3
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

409Conflict

The number is on Aethex's Meta app, whose webhooks Aethex already receives.

Nothing to configure for this number.

422Invalid request

whatsapp_webhook_route_failed: Meta would not route the number to its URL under the new token. whatsapp_webhook_unavailable: this deployment has no public API host to route it to.

For a routing refusal, check that your Meta app has a webhook configured, then rotate again: the previous token still works until one succeeds.

GET/whatsapp-accounts

Every WhatsApp number connected to your workspace.

List your WhatsApp numbers

Returns one row per connected number, newest first. credentials_invalid_since is the field to watch: a non-null value means Meta has stopped accepting our token for that number and nothing will send until you supply a new one. calling_enabled says whether customers can call the number on WhatsApp, from calling_status as Meta last reported it; GET …/health reads it fresh.

Path & Query

2
  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • offsetintegeroptional

    How many rows to skip before the first one returned. Defaults to 0.

GET/whatsapp-accounts/:account_id

The stored record for a single connected number.

Get one WhatsApp number

Returns the same shape as the list, for one number. Use it to read back which agent answers the number (default_agent_id) and whether its credentials are still valid.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

PATCH/whatsapp-accounts/:account_id

Change which agent answers, rename the number, or replace its token.

Update a WhatsApp number

Every field is optional; send only what changes. Passing default_agent_id: null unmaps the number, after which inbound messages are still recorded in the inbox but no agent replies. A replacement access_token is verified against Meta before it is stored, and clears credentials_invalid_since when it works.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

3
  • default_agent_idstring (uuid) | nulloptional

    The agent that answers this number. null unmaps it and stops automatic replies.

  • labelstringoptional

    A name for this number in your own dashboard. Never shown to customers.

  • access_tokenstringoptional

    Replacement system-user token. Verified against Meta before it is stored; write-only.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

DELETE/whatsapp-accounts/:account_id

Remove the number from your workspace and stop all messaging on it.

Disconnect a WhatsApp number

Disconnects the number and deletes the credentials we hold for it. Threads and their message history are kept, so an audit trail survives, but nothing further sends or receives. Returns 204 with no body; deleting an already-deleted number returns 404.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/templates

Submit a template for Meta's review. Approval takes minutes to a day.

Create a message template

Business-initiated messages — anything sent outside the 24-hour window a customer's message opens — must use an approved template. Aethex enforces Meta's structural rules before submission and returns a 422 naming the rule, instead of a rejection minutes later with no reason.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

4
  • namestringrequired

    Lowercase letters, digits and underscores.

  • languagestringrequired

    Locale code, e.g. en_US, fr, pt_BR.

  • categorystringrequired

    UTILITY, MARKETING or AUTHENTICATION.

  • componentsobject[]required

    Meta's component array: BODY (required), optional HEADER, FOOTER, BUTTONS. Every {{n}} variable needs a sample value in example.

Errors

2
422Invalid request

A rule Meta would reject on: a variable at the start or end, variables out of sequence, a variable without a sample, a header over 60 characters, and so on.

The detail names the rule; fix the component and resubmit.

404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/templates

Every template on this WABA and where Meta's review has got to.

List templates

Reads the templates straight from Meta, so status is current: APPROVED is sendable, PENDING is still in review, REJECTED carries a rejected_reason. Results are cursor-paged — when next_cursor is not null, pass it as ?after= for the next page.

Path & Query

3
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • afterstringoptional

    Cursor from a previous response's next_cursor. Omit for the first page.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

DELETE/whatsapp-accounts/:account_id/templates/:template_name

Remove a template from the WABA by name.

Delete a template

Deletes every language version of the named template at Meta. Campaigns that reference it will start failing, so check the template is unused first. Returns 204 with no body.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • template_namestringrequired

    The template's name, exactly as it was created. Not the numeric id.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/messages

Open (or reopen) a conversation with an approved template.

Send a template message

Sends under an approved template, which is the only way to message a customer outside the 24-hour window. Returns 202: Meta accepted the message for delivery. Delivery and read receipts arrive on the thread and, if configured, on your webhook as whatsapp.message.status. Each accepted message is metered.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

4
  • tostringrequired

    Recipient in E.164, with or without the leading +.

  • namestringrequired

    An APPROVED template on this number.

  • languagestringrequired

    The template's language code.

  • componentsobject[]optional

    Values for the template's variables, in Meta's component shape.

Errors

2
422Invalid request

The template is unknown, not approved, or the variable count does not match.

List templates and check the status and body; send exactly one value per variable.

429Rate limited

The per-workspace send budget was exceeded.

Honour Retry-After; for bulk sends use a campaign, which paces itself.

POST/whatsapp-accounts/:account_id/messages/options

Ask a question with up to ten answers the customer taps instead of types.

Send tappable options

Only works inside the 24-hour window a customer's message opens — it is a session message, not a template. One to three options render as buttons; four or more render as a list opened by the list_button label. The customer's tap arrives on your webhook as their reply, carrying the id you set, which is what you match on rather than the visible title.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

9
  • tostringrequired

    Recipient in E.164, with or without the leading +.

  • bodystringrequired

    The question. Up to 1024 characters.

  • optionsobject[]required

    One to ten choices. Three or fewer render as buttons, four or more as a list.

  • options[].idstringrequired

    Your own id for the choice, echoed back when the customer taps it. Up to 200 characters.

  • options[].titlestringrequired

    The visible label, up to 24 characters.

  • options[].descriptionstringoptional

    A second line under the label. Shown only in list form (four or more options).

  • headerstringoptional

    Optional bold line above the question, up to 60 characters.

  • list_buttonstringoptional

    Label on the button that opens the list. Defaults to Choose, up to 20 characters.

Errors

2
422Refused by WhatsApp

The 24-hour window since the customer's last message has closed, so WhatsApp refuses a session message.

Send an approved template instead; once they reply, the window reopens and options work again.

422Invalid request

The options list is empty, longer than ten, or an option exceeds its length limit.

Send between one and ten options, each with a title of 24 characters or fewer.

GET/whatsapp-accounts/:account_id/inbox/summary

Open, unread and waiting-on-a-person counts in one call.

Get inbox counts

The three numbers an operator dashboard needs, without paging the threads. human counts open threads a person has taken over and has yet to close — the queue that needs staffing.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/threads

Every customer on the number, most recent first, with unread counts and who is answering.

List threads (inbox)

A thread is one customer on one number. mode is agent (the agent answers) or human (a person owns it; the agent stays silent). Filter to mode=human to find conversations waiting on a person.

Path & Query

7
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • statusstringoptional

    open or closed.

  • modestringoptional

    agent or human.

  • unreadbooleanoptional

    Only threads with unread customer messages.

  • qstringoptional

    Match on number, name or last message.

  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • offsetintegeroptional

    How many rows to skip before the first one returned. Defaults to 0.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/threads/:thread_id

The full record for a single thread, including whether its window is open.

Get one conversation

mode tells you who is answering: agent for the AI, human once a person takes over. session_open tells you what you may send — free text while it is true, an approved template once it is false.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Errors

1
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

PATCH/whatsapp-accounts/:account_id/threads/:thread_id

Close or reopen a thread, and change who owns it.

Update a conversation

Use this for the bookkeeping around a thread rather than its mode: closing it removes it from the open queue, and assignment records which of your people owns it. Closing does not stop the customer writing back — a new inbound message reopens the thread. To hand the conversation back to the agent, use the mode endpoint instead.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Request body

3
  • statusstringoptional

    open or closed. Closing takes it out of the open queue; a new inbound message reopens it.

  • assigned_tostringoptional

    Who owns the thread, usually an email. Recorded and returned as assigned_to.

  • clear_assignmentbooleanoptional

    Send true to clear the assignment. Takes precedence over assigned_to.

Errors

1
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

GET/whatsapp-accounts/:account_id/threads/:thread_id/messages

The full timeline across chats and calls, oldest first, with delivery state on outbound turns.

Read a thread's messages

Every turn the customer has had with this number: agent replies, operator replies (author operator:<email>), template sends and calls. Outbound turns carry Meta's message id and delivery_status (sent, delivered, read, failed, or unknown when the answer to the send was lost and the message may still have been delivered, so don't re-send it blindly).

Path & Query

4
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

  • beforestring (ISO 8601)optional

    Page backwards from this timestamp.

  • limitintegeroptional

    1–200, default 50.

Errors

1
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/threads/:thread_id/mode

Switch who answers. In human mode the agent stays silent and customer messages raise the unread count.

Hand a thread to a person, or back to the agent

Switching to human stops the agent replying on this thread; new customer messages are stored, the thread's unread count rises, and whatsapp.message.received is sent to your webhook. A customer who asks for a person triggers the same switch automatically (with whatsapp.handoff.requested). Switching back to agent resumes the agent with full context.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Request body

3
  • modestringrequired

    human or agent.

  • actorstringoptional

    Who is taking or releasing the thread (an email); recorded on the thread.

  • reasonstringoptional

    Why, shown in the inbox.

Errors

1
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/threads/:thread_id/messages

Send free text inside the 24-hour window. Outside it, use a template.

Reply as a person

Sends a plain text message as an operator and records it on the timeline with the actor's identity. WhatsApp only allows free text within 24 hours of the customer's last message; after that this returns 409 and you should send a template (POST .../threads/{thread_id}/messages/template).

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Request body

2
  • textstringrequired

    Up to 4096 characters.

  • actorstringoptional

    The person replying (an email), shown in the inbox.

Errors

2
409Window closed

More than 24 hours since the customer last wrote.

Send an approved template to reopen the conversation.

404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/threads/:thread_id/messages/template

Restart a conversation whose 24-hour window has closed.

Reply with a template

The operator's counterpart to a free-text reply, for when session_open is false and WhatsApp will no longer accept plain text. Sends an approved template into the existing thread and records it as an operator turn, so the transcript stays in one place. Sending it reopens nothing by itself — the window reopens when the customer replies.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Request body

4
  • namestringrequired

    The approved template's name.

  • languagestringrequired

    The template's language code, for example en_US.

  • paramsstring[]optional

    Values for the template's {{1}}, {{2}} … variables, in order.

  • actorstringoptional

    The person replying (an email), shown in the inbox.

Errors

2
422Invalid request

The template is unknown, not approved, or the variable count does not match.

List templates and check the status and body; send exactly one value per variable.

404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/threads/:thread_id/read

Reset the thread's unread count to zero.

Mark a conversation read

Call it when one of your people opens the thread in your own interface. It clears unread_count on our side only — it does not send a read receipt to the customer.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

Errors

1
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

DELETE/whatsapp-accounts/:account_id/threads/:thread_id

Deletes this customer's messages, call transcripts and recordings, and the agent's memory of them on this number, so their next message starts fresh.

Erase a conversation

Deletes the thread, every chat and call transcript with this customer on this number, the call recordings, and what every agent on the number remembers about them (its summary and search memory). Their next message opens a new thread, answered by an agent that doesn't know them yet. Call records (duration, cost, status) stay for billing and usage, without their transcripts or recordings. Recordings stop playing at once and are purged from storage and its backup within 30 days. This cannot be undone. Pass actor to record who erased it.

Path & Query

3
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • thread_idstring (uuid)required

    The conversation's id.

  • actorstring (query)optional

    Operator erasing the conversation, logged with the erase.

Errors

2
404Not found

No thread with that id exists on this WhatsApp number.

List the threads for the number and use an id from the response.

409Conflict

The agent is replying to this customer right now, or a call with them is still going or its recording is still being saved.

Try again in a few moments (up to a few minutes after a call ends).

POST/whatsapp-accounts/:account_id/campaigns

One approved template to many customers, paced, with per-recipient outcome.

Create a campaign

Recipients are validated up front — every row must carry exactly the template's variable count, numbers are normalised and de-duplicated, and the row that fails is named. The worker sends at no more than rate_per_minute, records Meta's id per recipient, and receipts roll up to delivered and read counts. Pause, resume or cancel with POST .../campaigns/{campaign_id}/{pause|start|cancel}.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

8
  • namestringrequired

    A label for the campaign.

  • template_namestringrequired

    An APPROVED template on this number.

  • template_languagestringrequired

    The template's language code.

  • recipientsobject[]required

    Objects of {to, params}; params in the order of the template's variables.

  • rate_per_minuteintegeroptional

    1–600 sends per minute (default 60).

  • scheduled_atstring (ISO 8601)optional

    Start automatically at this time (with timezone offset).

  • start_nowbooleanoptional

    Start immediately.

  • webhook_urlstringoptional

    HTTPS URL that receives a signed whatsapp.campaign.paused if the worker stops this campaign on its own (today: the account out of credit). A pause you ask for is not reported. Needs your account webhook secret. Omit and nobody is told.

Errors

2
422Invalid request

A recipient row has the wrong number of values or an invalid number, or the template is not approved.

The detail names the row; fix it and resubmit.

404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/campaigns

Every campaign on this number, newest first.

List campaigns

Filter with ?status= to poll only what is live. The counts on each row (sent_count, delivered_count, read_count, failed_count) update as the campaign walks its recipients, so this is the cheap way to track progress without paging recipients.

Path & Query

4
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • statusstringoptional

    Return only campaigns in this state: draft, scheduled, running, paused, completed, cancelled or failed.

  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • offsetintegeroptional

    How many rows to skip before the first one returned. Defaults to 0.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/campaigns/:campaign_id

Status and counts for a single campaign.

Get one campaign

The same row as the list, for one campaign. error is set when a campaign stopped for a reason you can fix — it pauses rather than fails wherever the run can be resumed.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • campaign_idstring (uuid)required

    The campaign's id.

Errors

1
404Not found

No campaign with that id exists on this WhatsApp number.

List the campaigns for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/campaigns/:campaign_id/start

Begin sending, or resume a paused run.

Start a campaign

Starts a draft or scheduled campaign and resumes a paused one from where it stopped — already-sent recipients are not sent again. Sending begins within a few seconds of the call returning.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • campaign_idstring (uuid)required

    The campaign's id.

Errors

2
409Conflict

The campaign is already running, or has finished or been cancelled.

Only a draft, scheduled or paused campaign can be started. Read its status first.

404Not found

No campaign with that id exists on this WhatsApp number.

List the campaigns for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/campaigns/:campaign_id/pause

Stop sending, keeping the remaining recipients for later.

Pause a campaign

Stops the walk after the message in flight. Recipients still pending stay pending, so starting the campaign again resumes from the same place. Use this rather than cancel whenever you might continue.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • campaign_idstring (uuid)required

    The campaign's id.

Errors

2
409Conflict

The campaign is not running, so there is nothing to pause.

Only a running campaign can be paused.

404Not found

No campaign with that id exists on this WhatsApp number.

List the campaigns for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/campaigns/:campaign_id/cancel

Abandon the remaining recipients for good.

Cancel a campaign

Ends the run and abandons every pending recipient. This is terminal — a cancelled campaign cannot be started again. Messages already accepted by WhatsApp still deliver.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • campaign_idstring (uuid)required

    The campaign's id.

Errors

2
409Conflict

The campaign has already finished or been cancelled.

Nothing to do — a completed or cancelled campaign is already terminal.

404Not found

No campaign with that id exists on this WhatsApp number.

List the campaigns for the number and use an id from the response.

GET/whatsapp-accounts/:account_id/campaigns/:campaign_id/recipients

Row-by-row outcome for every number in a campaign.

List campaign recipients

The per-recipient detail behind the campaign counts. Filter with ?status=failed to pull only what went wrong: each failed row carries the reason in error, and each sent row carries the message_id to quote to WhatsApp support or match against delivery webhooks.

Path & Query

5
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • campaign_idstring (uuid)required

    The campaign's id.

  • statusstringoptional

    Return only recipients in this state: pending, sending, sent, failed or skipped.

  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • offsetintegeroptional

    How many rows to skip before the first one returned. Defaults to 0.

Errors

1
404Not found

No campaign with that id exists on this WhatsApp number.

List the campaigns for the number and use an id from the response.

POST/whatsapp-accounts/:account_id/calling

Ask Meta to switch calling on for the number, and get its answer.

Turn calling on

Connecting a number already asks Meta to switch calling on, unless someone switched it off in WhatsApp Manager. Aethex also asks by itself when Meta raises the limit. Use this to ask sooner once a number Meta turned down has qualified, which usually means its daily messaging limit has reached 2,000 unique customers, or for a number connected before connecting asked. A refusal from Meta is an answer, not an error: the response is 200 with calling_enabled: false and the reason in detail. The answer is also stored on the number as calling_status. It uses the same per-organization budget as connecting numbers.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

2
409Conflict

Calling is turned off on this deployment.

Ask the operator to enable WhatsApp calling (app.whatsapp.callingEnabled in the chart).

404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/calls/permission

Send the request a customer must accept before you can call them.

Ask permission to call

WhatsApp refuses business-initiated calls until the person has granted permission. This sends the free-form request, so it reaches them only inside their 24-hour window, and it only asks: nothing calls them when they say yes. To ask *and* call the moment they allow it — and to reach someone outside the window, with a template — use POST /calls with permission_template. The grant arrives later on your webhook; a 202 means the request reached them, not that they said yes.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

1
  • tostringrequired

    The customer's number in E.164, with or without the leading +.

Errors

4
422Refused by WhatsApp

WhatsApp refused the request — commonly the number is not on WhatsApp, or the 24-hour session window has closed.

Check the number reaches WhatsApp, and ask inside the window a customer's own message opens.

422Calling unavailable from this number

WhatsApp does not let businesses place calls from numbers registered in the United States, Canada, Egypt, Vietnam or Nigeria (code: whatsapp_calling_unavailable_in_country). People can still call the number.

Call from a number registered in another country. outbound_calling_available on the number says this up front.

422Calling is off for this number

Meta has calling switched off for this number (calling_status DISABLED), or has not switched it on yet (NOT_SET, usually a daily messaging limit under 2,000) (code: whatsapp_calling_off). Nobody is asked to allow a call it could not place.

Turn calling on with POST /whatsapp-accounts/:account_id/calling (or under Phone numbers > Calls in WhatsApp Manager). Under the limit it switches on by itself once Meta raises it. outbound_calling_available on the number says this up front.

404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/calls/permission

Whether you may call someone now — and if not, how to ask.

Check call permission

Asks WhatsApp, not a cache: whether this person has allowed calls from the number and until when (a temporary permission lasts 7 days), whether a call or a call request is allowed under WhatsApp's limits right now, when a spent limit frees, and whether their 24-hour chat window is open — which decides whether request_permission can be used instead of a template.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • tostringrequired

    The number you want to call, in E.164.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/calls

Ring someone on WhatsApp now — or ask first, and call the moment they allow it.

Call anyone

WhatsApp only connects a business's call to someone who has allowed that business to call them. If they already have, this rings them now: status is ringing, call_id is WhatsApp's id for the call and call_record_id the Aethex call record. If they have not, pass permission_template (or, inside their 24-hour window, request_permission) and they are sent a call-permission request: status is awaiting_permission, request_id names the request, and the call is placed the moment they tap Allow. Without either, calling someone who has not allowed it is refused rather than messaging them unasked. Either way 202 means ringing or asked, not connected. Business-initiated calls are unavailable from numbers registered in the US, Canada, Egypt, Vietnam and Nigeria; the person you call can be anywhere.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Request body

5
  • tostringrequired

    The customer's number in E.164, with or without the leading +.

  • agent_idstring (uuid)optional

    The agent that answers when the call connects. Defaults to the number's own agent.

  • permission_templateobjectoptional

    If they have not allowed calls yet: an approved template with a call-permission request (name, language, and optional send-time components). They are sent it, and called the moment they tap Allow. Reaches them whether or not their 24-hour window is open.

  • request_permissionbooleanoptional

    If they have not allowed calls yet, ask with the free-form request instead of a template. Only possible while their 24-hour chat window is open.

  • permission_messagestringoptional

    The line of context shown above the free-form request's Allow button — why you want to call.

Errors

11
403Number suppressed

to is on your account's do-not-call list. Checked before the call permission request, so they are neither called nor texted.

Do not retry. Remove the number, or release the entry through POST /suppressions/{id}/release if it is yours to lift.

422Refused by WhatsApp

They have not allowed calls from this number and no way to ask was given (detail.code is call_permission_required), or WhatsApp refused the call.

Pass permission_template (or request_permission inside their window) to ask and call on Allow. GET /calls/permission says which applies.

422Invalid request

The template is not approved or has no call-permission request — or, with request_permission, their 24-hour window is closed.

Use an approved template whose components include a call-permission request. Outside the window a template is the only way to ask.

409Conflict

A call request to this person is already waiting on their answer.

Wait for their answer — detail.request_id names the request — or withdraw it with POST /call-requests/:request_id/cancel.

429Rate limited

WhatsApp's limits are spent for now: one call request per person every 24 hours and two in 7 days, or 100 connected calls a day.

Try again after Retry-After, also given as detail.retry_at.

404Not found

The number is not this workspace's, or no agent is mapped to it.

Set default_agent_id on the number with PATCH /whatsapp-accounts/:account_id, then call again.

422Calling unavailable from this number

WhatsApp does not let businesses place calls from numbers registered in the United States, Canada, Egypt, Vietnam or Nigeria (code: whatsapp_calling_unavailable_in_country). People can still call the number.

Call from a number registered in another country. outbound_calling_available on the number says this up front.

422Calling is off for this number

Meta has calling switched off for this number (calling_status DISABLED), or has not switched it on yet (NOT_SET, usually a daily messaging limit under 2,000) (code: whatsapp_calling_off). Nobody is asked to allow a call it could not place.

Turn calling on with POST /whatsapp-accounts/:account_id/calling (or under Phone numbers > Calls in WhatsApp Manager). Under the limit it switches on by itself once Meta raises it. outbound_calling_available on the number says this up front.

502Call abandoned

The call may already have reached their phone, but it could not be set up on our side, so it was hung up.

Do not retry straight away — it could ring them twice, and four unanswered calls in a row withdraw their permission. GET /call-requests and the call log show what happened.

503Try again

No voice capacity right now, or WhatsApp could not be reached. Nothing was sent.

Retry after Retry-After seconds; the same request is safe to send again.

503Suppression list unreadable

The do-not-call list could not be read, so nothing was sent and no call was placed.

Retry after a short back-off; the same request is safe to send again.

GET/whatsapp-accounts/:account_id/call-requests

Everyone you asked to allow a call, and what became of each request.

List call requests

Newest first. awaiting_permission — sent, waiting on their answer; calling — allowed, the call is being placed; called — placed, with call_record_id for the transcript; then declined, expired (no answer in time: 24 hours, or the batch's end_at), failed (with error), or cancelled. Requests sent for a batch carry its batch_id.

Path & Query

4
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • statusstringoptional

    Only requests in this status.

  • limitintegeroptional

    How many rows to return. 1–200, defaults to 50.

  • offsetintegeroptional

    How many rows to skip before the first one returned. Defaults to 0.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/call-requests/:request_id

One call request and what became of it.

Get a call request

Everything the list shows for one request: whether it is still waiting on their answer, the call it placed (call_record_id, for the transcript), or why it closed (error).

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • request_idstring (uuid)required

    The call request's id.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

POST/whatsapp-accounts/:account_id/call-requests/:request_id/cancel

Withdraw it: no call follows, even if they allow it later.

Cancel a call request

Withdraws a request that is still waiting on them. If they tap Allow afterwards nothing calls them — though their permission stays with WhatsApp, so a later call to them rings straight away. Once they have allowed it, it can no longer be withdrawn (409): the call is being placed.

Path & Query

2
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

  • request_idstring (uuid)required

    The call request's id.

Errors

2
409Conflict

They already allowed it and the call is being placed, or the request is already called, declined, expired or cancelled.

There is nothing to withdraw; GET /call-requests/:request_id shows what became of it.

404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.

GET/whatsapp-accounts/:account_id/health

Meta's view of the number plus ours, with problems spelled out.

Number health

quality_rating and messaging_limit_tier come from Meta and decide whether campaigns are safe to run; webhook_subscribed confirms inbound will arrive; credentials_valid and problems tell you what to fix, in plain English. account_review_status, can_send_message and meta_checks carry Meta's own verdict: its review of the account, whether it will send, and each error with Meta's reason, fix and code. They are null or empty when Meta could not be read. calling_enabled is true only when Meta has calling switched on for the number (calling_status, read fresh on every call) and this deployment allows calls; when it is off, problems says why.

Path & Query

1
  • account_idstring (uuid)required

    The WhatsApp number's id, as returned when you connected it.

Errors

1
404Not found

No WhatsApp number with that id belongs to your workspace.

List your numbers and use an id from the response.