Skip to content

Start a flow with the API

Start a published flow for one contact from your own system with POST /flows/{flow_id}/runs, pass its variables, retry safely with an idempotency key, and handle the refusals.

POST /flows/{flow_id}/runs starts one of your flows for one contact, named by phone number. The flow must be published and have a Started by API trigger. To set one up in the builder, see Start a flow from your system.

The key needs the automation.trigger permission. No preset includes it, because a flow can do more than send messages (tag contacts, assign conversations, call your other systems), so a key gets it only by choice: create the key with Custom and tick it. To start a flow for a phone number you don't hold as a contact yet, the key also needs contacts.create. See Create and manage API keys.

Find the flow's ID

Open the flow in Automation and click its Started by API trigger. The panel shows the endpoint with the flow's ID in it, and an example request you can copy.

Start a run

bash
curl -X POST https://iconengage.com/api/public/v1/flows/FLOW_ID/runs \
  -H "Authorization: Bearer $ICONENGAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-confirm" \
  -d '{
    "to": "+91XXXXXXXXXX",
    "variables": { "order_number": "1042" }
  }'
  • to (required): the customer's phone number in international format, starting with + and the country code, for example "+91XXXXXXXXXX" with the customer's number in place of the X's. A number without the + is refused. If you don't hold the contact yet, it is created.
  • from (optional): the number to send from, by its id from GET /numbers or as the number is displayed. Leave it out if your organisation has one number that can send.
  • variables (optional): values for the flow's declared variables, by name, each as text of up to 1,024 characters. A number or yes/no variable takes its text form. A name the flow doesn't declare is refused.
  • Idempotency-Key (required header): one value per run you intend, 8 to 128 characters of letters, digits, ., _, : or -. A retry with the same key and body returns the first run (200) instead of starting another. The same key with a different body is 409 duplicate_request.

The answer

201 with the run:

json
{
  "id": "6f1c2e8a-…",
  "flow_id": "3b9d41c7-…",
  "version": 3,
  "contact_id": "a42e9f10-…",
  "conversation_id": null,
  "phone_number_id": "PHONE_NUMBER_ID",
  "state": "running",
  "started_at": "2026-10-21T09:30:00Z"
}

conversation_id is the customer's open conversation on the sending number, or null until the run's first message opens one. The run follows the flow's published version for its whole life. You can follow it in the flow's Runs tab.

When a run is refused

StatuscodeWhyWhat to do
404not_foundNo such flow in your organisation.Check the flow ID.
409conflict, details.reason: flow_not_publishedThe flow has no published version.Publish it.
409conflict, details.reason: flow_pausedThe flow is paused.Resume it. See Pause a flow.
409conflict, details.reason: no_api_triggerThe published version has no Started by API trigger.Add one and publish again.
409conflict, details.reason: run_activeThe customer is already in a run of this flow (details.run_id).Wait for that run to end.
409window_expiredThe customer's 24-hour window is closed, and the flow's first message isn't a template (details.node_id).Start the flow with a Send a template step, or wait for the customer to write. See window_expired.
409template_requiredThe customer has never written to this number, and the flow's first message isn't a template.Start the flow with a Send a template step. See template_required.
409contact_opted_outThe customer has opted out.Don't message them. See contact_opted_out.
409duplicate_requestThe Idempotency-Key was used with a different body.Use a new key for a new run.
400validation_failedA field is wrong, for example variables.<name> for a value that doesn't fit its variable.details.fields names each problem.
403permission_deniedThe key lacks automation.trigger (or contacts.create for a new number).Create a key with Custom and tick it.
429quota_exceededToo many runs started in a minute for your organisation.Wait, then retry with the same key.

For the error format and every other code, see Rate limits and errors.

Still need help?

Write to us at [email protected] and tell us what you were trying to do. Already a customer? Sign in to IconEngage — the same articles are under Help in the app.