Flows
Start your flow-builder automations for a customer.
Flows are the conversations you build in the flow builder: questions, buttons, waits, conditions, hand-overs to your team. The API starts them from your systems and tells you how they end, so an event in your store or CRM can open a real conversation.
How it works: Flows & automationsMake a flow startable · Start a flow for a customer · Follow a run · WhatsApp Flows (forms)
Make a flow startable#
In the flow builder, give the flow the API / webhook trigger and publish it. GET /flows?startable_via_api=true then lists it with startable_via_api: true. A draft, or a flow with another trigger (a keyword, a new conversation…), answers flow_not_triggerable.
Start a flow for a customer#
{
"to": "+966501234567",
"variables": { "order_id": "10482", "delivery_date": "الخميس" },
"reference": "order-10482"
}variablesbecome the run's starting variables: the flow reads them as{{order_id}}, next to what it already knows about the contact (name, custom fields).referenceis your own id. It comes back on the run and in everyflow.run.*event.- The flow's first message follows WhatsApp's rules: outside the 24-hour window it must be an approved template, so start flows meant for cold contacts with a template step.
The run starts at once; the answer shows where it stands (often waiting_input, waiting for the customer's reply).
Follow a run#
GET /flow_runs/{id} shows the run's state and the variables it has collected so far: answers, button choices, values from your systems. GET /flows/{id}/runs lists a flow's runs, by state or customer.
| Event | When |
|---|---|
flow.run.started | A run began (from the API, a trigger or the inbox) |
flow.run.handed_off | The flow passed the customer to your team |
flow.run.completed | The run reached its end; variables holds everything it collected |
flow.run.expired | The flow stopped waiting for a customer who did not answer in time |
A typical integration: start a delivery-feedback flow from your order system, and on flow.run.completed save the rating from variables against the order found by reference.
WhatsApp Flows (forms)#
WhatsApp Flows are forms that open inside the chat: a booking, a sign-up, a survey. Each submission arrives as a flow.response event with the customer's answers, and GET /flow_responses lists them, by form (whatsapp_flow_id) or date.
Endpoints
List WhatsApp Flow form responses
https://api.saei.automize.sa/v1/flow_responses- Scope:
flows:read - Live keys only
Answers customers submitted in WhatsApp Flows (the forms that open inside the chat), newest first. Each new one also arrives as a flow.response event.
Query parameters
limitintegeroptionalHow many objects to return, 1 to 100.
cursorstringoptionalThe
next_cursorfrom the previous page.whatsapp_flow_idstringoptionalOnly responses to this WhatsApp Flow (Meta's flow id).
sincestringoptional
Response fields200· A page of responses.
object"list"requireddataarray<FlowResponse>requiredChild fields (10)
idstringrequiredobject"flow_response"requiredwhatsapp_flow_idstring | nulloptionalflow_namestring | nulloptionalcustomerobjectoptionalChild fields (2)
contact_idstring | nulloptionaladdressstring | nulloptional
campaign_idstring | nulloptionaltemplate_idstring | nulloptionalanswersobjectrequiredThe form's fields and what the customer entered, by the field names set in the WhatsApp Flow.
file_countintegeroptionalsubmitted_atstring | nulloptional
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return3
- 403test_mode_unsupportedNot in test mode
- 422parameter_invalidInvalid parameter
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/flow_responses \
-H "Authorization: Bearer $API_KEY"A page of responses.
{
"object": "list",
"data": [
{
"id": "fres_77",
"object": "flow_response",
"whatsapp_flow_id": "string",
"flow_name": "string",
"customer": {
"contact_id": "string",
"address": "string"
},
"campaign_id": "string",
"template_id": "string",
"answers": {},
"file_count": 0,
"submitted_at": "2026-10-01T09:30:00Z"
}
],
"has_more": false,
"next_cursor": "string"
}Get a flow run
https://api.saei.automize.sa/v1/flow_runs/{id}- Scope:
flows:read - Live keys only
Where one customer is in a flow, and the variables the flow has collected so far (answers, choices, values from your systems).
Path parameters
idstringrequiredThe object's id.
Response fields200· The run.
idstringrequiredobject"flow_run"requiredflow_idstringrequiredcustomerobjectoptionalChild fields (2)
contact_idstring | nulloptionaladdressstring | nulloptional
channelstringoptionalstatestringrequiredwaiting_inputwaits for the customer;pausedwaits for a delay step;handed_offpassed to your team;expiredgave up waiting.One of
activewaiting_inputpausedhanded_offcompletedexpiredcurrent_stepstring | nulloptionalreferencestring | nulloptionalvariablesobjectoptionalstarted_atstring | nulloptionalcompleted_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return3
- 403test_mode_unsupportedNot in test mode
- 404resource_missingNot found
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/flow_runs/id_123 \
-H "Authorization: Bearer $API_KEY"The run.
{
"id": "run_9021",
"object": "flow_run",
"flow_id": "string",
"customer": {
"contact_id": "string",
"address": "string"
},
"channel": "string",
"state": "active",
"current_step": "string",
"reference": "string",
"variables": {},
"started_at": "2026-10-01T09:30:00Z",
"completed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}List flows
https://api.saei.automize.sa/v1/flows- Scope:
flows:read - Works in test mode
The automation flows built in the flow builder. startable_via_api marks the published flows with an "API / webhook" trigger, which POST /v1/flows/{id}/runs can start for a customer.
Query parameters
limitintegeroptionalHow many objects to return, 1 to 100.
cursorstringoptionalThe
next_cursorfrom the previous page.statusstringoptionalOne of
draftpublishedarchivedstartable_via_apibooleanoptionaltruefor only the flows you can start through the API.
Response fields200· A page of flows.
object"list"requireddataarray<Flow>requiredChild fields (11)
idstringrequiredobject"flow"requirednamestringrequireddescriptionstring | nulloptionalstatusstringrequiredOne of
draftpublishedarchivedtriggerstring | nulloptionalWhat starts the flow, e.g.
webhook,keyword,inbound-message,contact-added.startable_via_apibooleanrequirednumber_idstring | nulloptionalpublished_atstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return2
- 422parameter_invalidInvalid parameter
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/flows \
-H "Authorization: Bearer $API_KEY"A page of flows.
{
"object": "list",
"data": [
{
"id": "flow_18",
"object": "flow",
"name": "string",
"description": "string",
"status": "draft",
"trigger": "string",
"startable_via_api": false,
"number_id": "string",
"published_at": "2026-10-01T09:30:00Z",
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}
],
"has_more": false,
"next_cursor": "string"
}Get a flow
https://api.saei.automize.sa/v1/flows/{id}- Scope:
flows:read - Works in test mode
Path parameters
idstringrequiredThe object's id.
Response fields200· The flow.
idstringrequiredobject"flow"requirednamestringrequireddescriptionstring | nulloptionalstatusstringrequiredOne of
draftpublishedarchivedtriggerstring | nulloptionalWhat starts the flow, e.g.
webhook,keyword,inbound-message,contact-added.startable_via_apibooleanrequirednumber_idstring | nulloptionalpublished_atstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return2
- 404resource_missingNot found
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/flows/flow_18 \
-H "Authorization: Bearer $API_KEY"The flow.
{
"id": "flow_18",
"object": "flow",
"name": "متابعة بعد الشراء",
"description": "يسأل العميل عن تجربته بعد 3 أيام من التسليم",
"status": "published",
"trigger": "webhook",
"startable_via_api": true,
"number_id": "num_3",
"published_at": "2026-09-01T08:00:00Z",
"created_at": "2026-08-28T12:00:00Z",
"updated_at": "2026-09-01T08:00:00Z"
}List a flow's runs
https://api.saei.automize.sa/v1/flows/{id}/runs- Scope:
flows:read - Live keys only
Path parameters
idstringrequiredThe object's id.
Query parameters
limitintegeroptionalHow many objects to return, 1 to 100.
cursorstringoptionalThe
next_cursorfrom the previous page.statestringoptionalOne of
activewaiting_inputpausedhanded_offcompletedexpiredtostringoptionalOnly this customer's runs (phone, any format).
Response fields200· A page of runs.
object"list"requireddataarray<FlowRun>requiredChild fields (12)
idstringrequiredobject"flow_run"requiredflow_idstringrequiredcustomerobjectoptionalChild fields (2)
contact_idstring | nulloptionaladdressstring | nulloptional
channelstringoptionalstatestringrequiredwaiting_inputwaits for the customer;pausedwaits for a delay step;handed_offpassed to your team;expiredgave up waiting.One of
activewaiting_inputpausedhanded_offcompletedexpiredcurrent_stepstring | nulloptionalreferencestring | nulloptionalvariablesobjectoptionalstarted_atstring | nulloptionalcompleted_atstring | nulloptionalupdated_atstring | nulloptional
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return4
- 403test_mode_unsupportedNot in test mode
- 422parameter_invalidInvalid parameter
- 404resource_missingNot found
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/flows/flow_18/runs \
-H "Authorization: Bearer $API_KEY"A page of runs.
{
"object": "list",
"data": [
{
"id": "run_9021",
"object": "flow_run",
"flow_id": "string",
"customer": {
"contact_id": "string",
"address": "string"
},
"channel": "string",
"state": "active",
"current_step": "string",
"reference": "string",
"variables": {},
"started_at": "2026-10-01T09:30:00Z",
"completed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}
],
"has_more": false,
"next_cursor": "string"
}Start a flow for a customer
https://api.saei.automize.sa/v1/flows/{id}/runs- Scope:
flows:trigger - Live keys only
- Accepts Idempotency-Key
Runs the flow for one customer now, exactly as its "API / webhook" trigger would: the same steps, messages, waits and hand-offs. variables become the run's starting variables (the flow reads them as {{name}}), next to what it already knows about the contact. The customer comes from to only: contact_id, contact_phone, phone, phone_number, customer and keys starting with _ are reserved and refused. reference is your own id, returned on the run and in every flow.run.* event.
The flow must be published with the "API / webhook" trigger (startable_via_api: true). Its first message follows WhatsApp's rules: outside the 24-hour window that means an approved template.
Path parameters
idstringrequiredThe object's id.
Headers
Idempotency-KeystringoptionalAny unique string (a UUID is ideal). Retrying with the same key and body returns the first response instead of acting twice. Remembered for 24 hours.
Request body
tostringrequiredThe customer's phone, in any format.
variablesobjectoptionalreferencestringoptional
Response fields201· The run, already under way.
idstringrequiredobject"flow_run"requiredflow_idstringrequiredcustomerobjectoptionalChild fields (2)
contact_idstring | nulloptionaladdressstring | nulloptional
channelstringoptionalstatestringrequiredwaiting_inputwaits for the customer;pausedwaits for a delay step;handed_offpassed to your team;expiredgave up waiting.One of
activewaiting_inputpausedhanded_offcompletedexpiredcurrent_stepstring | nulloptionalreferencestring | nulloptionalvariablesobjectoptionalstarted_atstring | nulloptionalcompleted_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return6
- 403test_mode_unsupportedNot in test mode
- 422parameter_missingMissing parameter
- 422parameter_invalidInvalid parameter
- 404resource_missingNot found
- 422flow_not_triggerableFlow cannot be started
- 429rate_limitedToo many requests
Try it
curl -X POST https://api.saei.automize.sa/v1/flows/flow_18/runs \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"to": "+966501234567",
"variables": {
"order_id": "10482",
"delivery_date": "الخميس"
},
"reference": "order-10482"
}'The run, already under way.
{
"id": "run_9021",
"object": "flow_run",
"flow_id": "flow_18",
"customer": {
"contact_id": "ct_1052",
"address": "+966501234567"
},
"channel": "whatsapp",
"state": "waiting_input",
"current_step": "node_ask_rating",
"reference": "order-10482",
"variables": {
"order_id": "10482",
"delivery_date": "الخميس",
"first_name": "سارة",
"reference": "order-10482"
},
"started_at": "2026-10-01T10:00:00Z",
"completed_at": null,
"updated_at": "2026-10-01T10:00:01Z"
}