Workflows
How Kustomer workflows run. A trigger event starts a run, steps call actions with params built from earlier outputs, and transitions with conditions choose the path. Covers the anatomy, run lifecycle, limits and API.
A workflow is a small program that runs inside Kustomer whenever an event happens. Admins build workflows in Settings › Platform › Workflows without code. Underneath, each workflow is a JSON document you can read, write and version through the Workflows API.
Use workflows for logic that should run next to your Kustomer data: tagging and routing conversations, keeping records in sync, calling your own services when something changes, and handling data from inbound webhooks.
New to workflows? Read these in order. Each one has an interactive scene you can step through.
/#steps… and {{…}} language you use to refer to it.The rest of this section is reference material.
{ "steps": {} }
Anatomy
Every workflow has the same five building blocks.
Here's the workflow from the diagram above as JSON:
{
"name": "sync-closed-conversations",
"description": "Post closed conversations to our analytics service",
"enabled": true,
"trigger": {
"id": "1",
"eventName": "kustomer.conversation.update",
"transitions": [
{
"target": "lookup",
"condition": { "op": "eq", "values": ["/#steps.1.changes.attributes.status.after", "done"] }
}
]
},
"steps": [
{
"id": "lookup",
"action": "kustomer.customer.find",
"params": { "identifier": "/#steps.1.customer" },
"transitions": [{ "target": "post", "condition": { "op": "true", "values": [true] } }]
},
{
"id": "post",
"action": "kustomer.rest-api.json",
"params": {
"method": "post",
"uri": "https://api.example.com/kustomer/closed",
"headers": { "Content-Type": "application/json", "Authorization": "Bearer {{{variables.6513b2f4a4b1e1001a6b3f20}}}" },
"json": true,
"data": {
"conversationId": "/#steps.1.id",
"email": "/#steps.lookup.emails.0.email",
"closedAt": "/#steps.1.lastDone.createdAt"
}
},
"transitions": [
{ "target": "tag", "condition": { "op": "lt", "values": ["/#steps.post.response.statusCode", 300] } },
{ "target": "note", "condition": { "op": "gte", "values": ["/#steps.post.response.statusCode", 300] } }
]
},
{
"id": "tag",
"action": "kustomer.conversation.append-tags",
"params": { "id": "/#steps.1.id", "tags": ["64f1c0ffee5ca1ab1e000001"] },
"transitions": []
},
{
"id": "note",
"action": "kustomer.note.create",
"params": { "conversation": "/#steps.1.id", "body": "Sync failed: HTTP {{steps.post.response.statusCode}}" },
"transitions": []
}
]
}The Authorization header reads a workflow variable. 6513b2f4a4b1e1001a6b3f20 is the variable's ID, not its name: workflows always refer to variables by ID.
Three rules explain most of what you see:
- Outputs are keyed by step ID. When a step finishes, its output is stored at
steps.<id>in the run's context. The trigger is always step1. Steps you create in the builder get short random IDs such asSJsVbyiGf. - References keep their type; templates make strings. A param that is exactly
"/#steps.1.id"resolves to the value itself, whether that's a string, number, array or object. Any other string is rendered as a Handlebars template, such as"Sync failed: HTTP {{steps.post.response.statusCode}}", and the result is always a string. See Conditions and variables. - The first matching transition wins. After a step runs, its transitions are checked in order. The first one whose condition passes picks the next step. If none match, the run ends. That's normal, and it's how most runs end: the trigger fires on every update, and the first condition filters out the ones you don't care about.
Runs only move forward. A transition can't point back to a step that's already on the path to it, and Kustomer rejects such a workflow when you save it. To repeat work later, schedule a callable workflow. For the full engine model, see How workflows run.
The life of a run
Diagram source
sequenceDiagram
autonumber
participant K as Kustomer
participant W as Workflow engine
participant A as Actions
K->>W: Event (kustomer.conversation.update)
W->>W: Find enabled workflows with this trigger
Note over W: Each matching workflow runs in turn
W->>W: Normalize event into step 1 output
loop Until no transition matches
W->>W: Check transitions in order
W->>A: Run next step with resolved params
A-->>W: Output stored at steps.<id>
end
W-->>K: Run complete (or error recorded)Matching delay~60 seconds- A workflow you create, enable or update can take about a minute to start matching events. Wait before you test.
Run timeout5 minutes- A run that hasn't finished after five minutes is stopped. The limit is checked between steps, so a single slow step can run past it, and the run ends when that step finishes. Hand long-running work to your own service with a REST step.
Branches10 per step- A step or trigger can have up to 10 transitions and 10 error cases. Two identical transitions on the same step are rejected.
REST timeout60 seconds- A REST step waits up to 60 seconds for a response.
Rate limitsskipped- Limits apply per org and event name. Events over the limit are skipped rather than queued. Calls to callable workflows aren't rate limited.
Orderingnot guaranteed- Runs for different events can execute in parallel and finish in any order. Don't assume the run for an earlier update finishes first. When several workflows match the same event, they run one after another, in no documented order.
System retriesfrom step 1- If a Kustomer action gets a
5xxfrom the API, or the platform has a temporary problem, the step's error cases are skipped and the whole run starts again from step1. Steps that already succeeded run again, so make them safe to repeat. Versions30 kept- Each save creates a new version of the workflow. Kustomer keeps the 30 most recent.
Where workflow events come from
Manage workflows with the API
Workflows are ordinary resources. Read them to back them up, diff them in code review, or copy them between orgs.
curl "https://acme.api.kustomerapp.com/v1/workflows?eventName=kustomer.conversation.update&enabled=true" \
-H "Authorization: Bearer $KUSTOMER_API_KEY"