Automations
Start an automation from your own system — an order, a signup, a form — and track what happened next. Build the flow in the MYWA app; the API decides who goes through it and when.
List automations
/automationsRequires automations:read. Returns every automation you can start, with how many people it has enrolled and when it last ran. Archived automations aren’t listed.
curl "$MYWA_API/automations" -H "Authorization: Bearer $MYWA_KEY"{
"automations": [
{
"id": "wf_9f2",
"name": "Order follow-up",
"description": "Thank the customer, then ask for a review after delivery",
"status": "ACTIVE",
"trigger": "From another app",
"enrolled": 412,
"lastRunAt": "2026-08-27T09:14:02.000Z"
}
]
}Start an automation for a contact
/automations/:id/enrollRequires automations:write. Identify the person by phone or contactId — one of them is required.
Body parameters
| Field | Type | Description |
|---|---|---|
phone | string | E.164 phone number. A number that is new to your workspace creates the contact. Required unless you send contactId. |
contactId | string | An existing contact id. Required unless you send phone. |
name | string | Contact display name. |
attributes | object | Key→value pairs (string, number, or boolean). Merged into the contact, not replaced. |
vars | object | Data for this run only — not saved on the contact. Steps read it as {{vars.hook.<key>}}. |
Unknown fields are rejected with 400 validation_error, so a typo never silently drops data.
curl -X POST "$MYWA_API/automations/wf_9f2/enroll" \
-H "Authorization: Bearer $MYWA_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+15551234567",
"name": "Jane Doe",
"attributes": { "city": "Austin" },
"vars": { "orderId": "A-1049", "amount": 49.99 }
}'Returns 202 Accepted — the run is queued, not finished. contactCreated tells you whether the phone number was new.
{ "runId": "run_7c1", "contactId": "cts_31a…", "contactCreated": true }Using vars in your steps
vars is available to the automation’s steps. With the request above, a message step can say Thanks for order {{vars.hook.orderId}}!.The automation must be live
409 not_published or 409 no_trigger. Your workspace’s guardrails (re-entry, opt-outs, plan limits) still apply — see automation errors for which ones are worth retrying.List runs
/automations/:id/runsRequires automations:read. Test runs from the builder aren’t included.
Query parameters
| Field | Type | Description |
|---|---|---|
status | string | One of PENDING, RUNNING, WAITING_REPLY, SLEEPING, WAITING_EVENT, COMPLETED, FAILED, CANCELLED. |
contactId | string | Only runs for this contact. |
limit | number | 1–100. Defaults to 25. |
cursor | string | The nextCursor from the previous page. |
curl "$MYWA_API/automations/wf_9f2/runs?status=COMPLETED&limit=25" \
-H "Authorization: Bearer $MYWA_KEY"{
"runs": [ { "id": "run_7c1", "status": "COMPLETED", "…": "…" } ],
"nextCursor": "run_6b0…"
}Pass cursor=<nextCursor> to fetch the next page. nextCursor is null on the last page.
Get one run
/automation-runs/:runIdRequires automations:read. Fetch a run by the runId you got when you started it — no need to know which automation it belongs to.
curl "$MYWA_API/automation-runs/run_7c1" -H "Authorization: Bearer $MYWA_KEY"{
"id": "run_7c1",
"workflowId": "wf_9f2",
"contactId": "cts_31a…",
"conversationId": "cnv_88b…",
"status": "COMPLETED",
"currentNodeId": null,
"error": null,
"exitReason": "end_node",
"goal": {
"name": "Left a review",
"reachedAt": "2026-08-27T09:31:44.000Z",
"value": null,
"currency": null
},
"startedAt": "2026-08-27T09:14:02.000Z",
"finishedAt": "2026-08-27T09:31:45.000Z"
}| Field | Type | Description |
|---|---|---|
status | string | Where the run is now: still going (PENDING, RUNNING), paused (WAITING_REPLY, SLEEPING, WAITING_EVENT), or done (COMPLETED, FAILED, CANCELLED). |
currentNodeId | string | null | The step the run is on. null once it has finished. |
error | string | null | Why the run failed. null unless status is FAILED. |
exitReason | string | null | How a finished run ended, e.g. end_node when it reached the end of the flow. |
goal | object | null | null until the run passes a "Goal reached" step; then the goal name, when it was reached, and an optional value and currency. |
startedAt | string | ISO-8601 time the run started. |
finishedAt | string | null | ISO-8601 time the run ended. null while it is still going. |
const run = await mywa.get(`/automation-runs/${runId}`);
if (run.goal) console.log('goal reached:', run.goal.name);
else if (run.status === 'FAILED') console.error('run failed:', run.error);
else console.log('status:', run.status);See it in a real flow