Workflows
A workflow is an automation graph: a trigger event, then a set of nodes connected by edges. It is what the visual builder in the LeadX app produces, and the execution engine lives in leadx-ms-workflow.
You never call the workflow service directly — it is internal and requires its own token. Everything goes through leadx-api.
Create
curl -X POST https://api.leadx.in/api/key/protected/workflow \
-H "apikey: $KEY" -H "Content-Type: application/json" \
-d '{
"name": "Welcome new website leads",
"triggerEventType": "lead.created",
"config": {},
"nodes": [
{ "id": "n1", "type": "trigger", "data": { "eventType": "lead.created" } },
{ "id": "n2", "type": "condition", "data": { "field": "source", "op": "equals", "value": "Website" } },
{ "id": "n3", "type": "action", "data": { "action": "send", "mode": "smtp", "template": "665c..." } }
],
"edges": [
{ "source": "n1", "target": "n2" },
{ "source": "n2", "target": "n3", "sourceHandle": "true" }
]
}'
| Field | Notes |
|---|---|
name | Made unique automatically — a clashing name gets a suffix rather than an error. |
triggerEventType | The event that starts a run. |
nodes / edges | The graph. Sent whole; PUT replaces the graph rather than patching it. |
config | Workflow-level settings. |
schedule | For time-triggered workflows instead of event-triggered. |
Trigger events
| Event | Fires when |
|---|---|
lead.created | A lead is created, by any path. |
lead.updated | A lead changes. |
contact.created | A contact is created. |
contact.updated | A contact changes. |
email.sent | An email goes out. |
whatsapp.sent | A WhatsApp message goes out. |
whatsapp.received | An inbound WhatsApp message arrives. |
whatsapp.template.approved | Meta approves a template. |
call.completed | A call log is closed. |
:::note Campaigns can suppress events
Campaign creation takes triggerWorkflow (default true). Setting it false stops a bulk send from firing email.sent/whatsapp.sent for every recipient — worth doing when a large campaign would otherwise trigger thousands of workflow runs.
:::
Publish
A workflow does not run until it is published.
| Method | Endpoint |
|---|---|
POST | /workflow/:id/publish |
POST | /workflow/:id/unpublish |
Unpublishing stops new runs; it does not cancel runs already in flight.
Manage definitions
| Method | Endpoint | Purpose |
|---|---|---|
GET | /workflow | List. |
POST | /workflow | Create. |
DELETE | /workflow | Bulk delete — { "ids": [...] }. |
GET | /workflow/:id | Read, with graph hydrated. |
PUT | /workflow/:id | Update. Replaces the graph. |
DELETE | /workflow/:id | Delete one. |
Runs
Each trigger creates a run with its own state.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /workflow/runs | List runs. Filter by workflow and status. |
DELETE | /workflow/runs | Bulk delete runs. |
DELETE | /workflow/runs/:runId | Delete one run. |
POST | /workflow/runs/:runId/pause | Pause. |
POST | /workflow/runs/:runId/resume | Resume. |
POST | /workflow/runs/:runId/cancel | Cancel — terminal. |
POST | /workflow/runs/:runId/restart | Re-run from the start. |
POST | /workflow/:id/runs/pause | Pause every in-flight run of one workflow. |
POST /workflow/:id/runs/pause is the emergency brake: use it when a published workflow is misbehaving and you want to stop the bleeding before editing it.
A safe change process
POST /workflow/:id/runs/pause— freeze in-flight runs.POST /workflow/:id/unpublish— stop new ones.PUT /workflow/:id— send the full new graph.POST /workflow/:id/publish.GET /workflow/runs?filters={"workflow":"..."}— confirm new runs look right.
Action nodes and sending
Send actions inside a workflow route through leadx-ms-unified-chat, the same path as one-to-one replies and Genie outreach — not through the campaign sender. Their messages land in the unified inbox like any other.