Flows
How it fits together
Section titled “How it fits together”- Find the flow’s id with
GET /flows. - Trigger it for a number with
POST /flows/{flow_ref}/trigger. You get anexecution_idback straight away; the flow runs in the background. - Get the result: poll
GET /flows/executions/{execution_id}, pass acallback_urlon the trigger, or subscribe to theflow.completed/flow.step_completedwebhooks.
List flows
Section titled “List flows”curl https://api.whatbot.in/public/v1/flows -H "X-API-Key: wa_live_xxx"{ "flows": [ { "id": "a41b...", "key": null, "name": "Site visit booking", "status": "published" } ]}Every flow in the workspace, most recently edited first, drafts included. key is an
optional stable slug; flows created in the app may not have one, so use id unless
you have set a key.
Trigger a flow
Section titled “Trigger a flow”curl -X POST https://api.whatbot.in/public/v1/flows/a41b.../trigger \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "phone": "9876543210", "variables": { "name": "Ravi", "project": "Tower B" }, "callback_url": "https://your-app.com/whatbot/flow-done" }'flow_ref in the path is the flow’s id or its key. The flow must have been
published at least once — the run uses its latest published version, so later
unpublished edits are not included. A flow that has never been published returns 422.
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Yes | The contact’s number, any format. The conversation is created if it doesn’t exist. |
| variables | object | Starting values for the run’s variables. Message nodes can use them as {{name}}. | |
| callback_url | string | A URL we POST the result to when the run ends. See Callback URL. | |
| from | string | Which of your numbers runs the flow: the number in any format, or its phone number ID. Defaults to the workspace’s default number. |
{ "execution_id": "7d1e...", "flow_id": "a41b...", "conversation_id": "c9e6f0f7-...", "phone": "919876543210", "status": "running"}A triggered flow runs even if the conversation is assigned to an agent.
Trigger errors
Section titled “Trigger errors”| Status | Cause |
|---|---|
400 | from is not one of this workspace’s numbers, or is disconnected |
404 | No flow with that id or key in this workspace |
409 | This number already has a flow running (including one handed off to an agent), or the workspace has no WhatsApp number to send from |
422 | Invalid phone number, or the flow has never been published |
Poll an execution
Section titled “Poll an execution”curl https://api.whatbot.in/public/v1/flows/executions/7d1e... \ -H "X-API-Key: wa_live_xxx"{ "execution_id": "7d1e...", "flow_id": "a41b...", "phone": "919876543210", "status": "completed", "variables": { "name": "Ravi", "budget": "50L", "_responses": [ { "question": "What's your budget?", "answer": "50L" } ] }, "started_at": "2026-09-15T10:00:00+00:00", "completed_at": "2026-09-15T10:03:12+00:00"}| Field | Description |
|---|---|
| status | running, completed or failed. running covers a run waiting for a reply, waiting for the 24-hour window, or handed off to an agent. failed covers every other ending — an error, the idle timeout, or the conversation being closed. |
| variables | Everything collected so far: your starting variables, each answer under its Save answer as name, and the _responses log. Keys starting with _ are internal; _error carries the reason on a failure when one was recorded. |
| completed_at | When the run ended, or null while running. |
| phone | The contact’s number. Masked if your workspace masks the public API. |
An id that isn’t in your workspace returns 404.
Callback URL
Section titled “Callback URL”When a run that was triggered with a callback_url ends, we POST this JSON to it:
{ "execution_id": "7d1e...", "flow_id": "a41b...", "phone": "919876543210", "status": "completed", "variables": { "name": "Ravi", "budget": "50L" }}status is completed or failed. The callback is not signed — unlike
webhooks — so treat it as a hint and confirm with
GET /flows/executions/{id} before acting on it, or use the signed
flow.completed webhook instead. Each attempt times out after 8 seconds; a 5xx or
network error is retried, up to 3 attempts in all, and a 4xx is not retried. It
may arrive more than once — dedupe on execution_id.