Skip to main content
Endpoint · POST /conversation/actions
The POST /conversation/actions endpoint runs a group of up to 10 actions on a single conversation, in the order you send them. Instead of making N requests to label, leave a note, and run the AI, you chain them into a single request. It’s the recommended way to mutate a conversation from an external client. Each element of the actions array carries a type field. send_message unifies the four send modes (text, media, quick reply, template). send_quick_reply_or_template is the only one whose mode the server decides: it sends the quick reply if the 24h window is open, or the template if it’s closed.
A group allows up to 10 actions, of which at most 3 can trigger the AI. Exceeding it fails with BATCH_LIMIT_EXCEEDED.
Each action has its own page with its fields and an example — open the one you need from the table or the nav. To send media, first upload it with the Upload media flow.

Identify the conversation

The group runs on one conversation: you identify it with the conversation object, which carries exactly one of uuid, whatsapp_user_id, username, or phone, plus channel (required).
string
Stable key of a conversation you already know. The most direct path.
string
The contact’s BSUID (Meta’s opaque identity). Resolves by exact match; recommended identifier going forward.
string
Public WhatsApp username, with or without @ and case-insensitive. If several contacts share it, the API returns 409 (USERNAME_AMBIGUOUS).
string
Phone in E.164 format. If it is duplicated across contacts, the API returns 409 (PHONE_NUMBER_AMBIGUOUS) instead of guessing.
string
required
The channel’s public key — copy it from the dashboard under Settings → Channels (the Channel key field), or list them with GET /channels. Required in every request: it sets the target channel. On the contact-based paths (phone, username, whatsapp_user_id) it restricts resolution to that channel; with uuid the engine ignores it, but the contract still requires it. A key that does not exist → 404 (CHANNEL_NOT_FOUND).
Full reference (resolution order, conversation merging, and contact ambiguities) in Identify a conversation.

How it runs

1

Synchronous validation

The API validates the request. If the preflight rejects it (e.g. the AI has no tokens), it returns a synchronous 4xx and no action runs.
2

202 Accepted

If validation passes, it returns 202 immediately; the group runs in the background.
3

Execution in order

The actions run one by one, in the order sent.
The 202 confirms the group was accepted, not that every action succeeded. The per-action result does not travel in the response — query it in the conversation status or in the business’s activity log.

Stop on error

stop_on_error controls what happens when an action fails during execution:

Escalation to pending

escalate_on_error controls whether a group failure escalates the conversation to inbox_status='pending' for a human to review:
Integrator input errors (*_NOT_FOUND, *_AMBIGUOUS, WINDOW_CLOSED, TEMPLATE_NOT_APPROVED, etc.), billing guards (WALLET_BLOCKED, VISION_WALLET_BLOCKED), and the mark_resolved integrity guard (TRANSCRIPTION_REQUIRED_TO_RESOLVE) never escalate — fix them and retry without human intervention.

Assembling an action list

Each action is an object in the actions array, identified by its type. A request groups several actions on the same conversation, run in the order sent. The conversation object always includes channel. Example — label, leave a note, and run the AI, without halting on failures:

Identify by different fields

Change only the identifier inside conversation (channel is always included); the rest of the request does not change:
Hand off to a human — a single unassign_ai action, no fields. It’s idempotent: if the conversation already has no AI, it’s a successful no-op.
If the preflight rejects the group, the response is a synchronous 4xx and no action runs. See Errors.