Create Workflow
POST/workflows/
Create a workflow from a complete definition. The definition is validated in full before anything is persisted, so a rejected request creates nothing. Workflows are always created in draft; use Update Workflow Status to publish.
Request
API Version
v3Sub-account (location) ID the workflow belongs to
- application/json
- Body
- linear
- branching
- wait
- webhook
Bodyrequired
Workflow name
Where this definition came from
Triggers that enrol contacts. May be empty — a workflow with no trigger can still be entered by another workflow or by the API — but the key must be present.
How multiple triggers combine. Echoed by Get Workflow Definition; ignored on write — the system always stores or.
andorSteps. May be an empty array, but the key must be present.
Connections between steps. May be empty, but the key must be present.
Workflow-level settings
Single-segment folder to place the workflow in. Mutually exclusive with folderPath.
Folder path, outermost first, max 10 levels. Mutually exclusive with folderName.
Create the folder if it does not exist. Requires folderName or folderPath.
The workflow's version counter, owned by the system — not a format version. Get Workflow Definition fills it in; leave it untouched and send it back on update, and a concurrent edit in the builder can never be silently overwritten. A stale value is rejected with 422.
Treat it as opaque: echo it, never compute from it. It does not always advance by one (delete and restore each add 0.1, and a later save rounds up), so it is not always an integer.
Omit it on create — the system assigns the starting value.
- Linear — two steps in sequence
{
"version": 1,
"name": "Welcome new contacts",
"source": {
"system": "api"
},
"triggers": [
{
"type": "contact_created",
"name": "New contact"
}
],
"actions": [
{
"id": "send-welcome-sms",
"type": "sms",
"name": "Send welcome SMS",
"attributes": {
"body": "Hi {{contact.first_name}}, thanks for getting in touch!"
}
},
{
"id": "tag-as-welcomed",
"type": "add_contact_tag",
"name": "Tag as welcomed",
"attributes": {
"tags": [
"your-existing-tag"
]
}
}
],
"edges": [
{
"from": "send-welcome-sms",
"to": "tag-as-welcomed"
}
]
}
- If/else — two lanes from one condition
{
"version": 1,
"name": "Route by tag",
"source": {
"system": "api"
},
"triggers": [
{
"type": "contact_created"
}
],
"actions": [
{
"id": "is-vip",
"type": "if_else",
"name": "Is this a VIP?",
"attributes": {
"conditionName": "Is this a VIP?",
"operator": "and",
"if": true
}
},
{
"id": "vip-greeting",
"type": "sms",
"name": "VIP greeting",
"attributes": {
"body": "Welcome back!"
}
},
{
"id": "standard-greeting",
"type": "sms",
"name": "Standard greeting",
"attributes": {
"body": "Welcome!"
}
}
],
"edges": [
{
"from": "is-vip",
"to": "vip-greeting",
"branch": "yes"
},
{
"from": "is-vip",
"to": "standard-greeting",
"branch": "default"
}
]
}
- Wait — pause before the next step
{
"version": 1,
"name": "Follow up after two days",
"source": {
"system": "api"
},
"triggers": [
{
"type": "contact_created"
}
],
"actions": [
{
"id": "wait-one-day",
"type": "wait",
"name": "Wait 2 days",
"attributes": {
"type": "time",
"startAfter": {
"when": "after",
"type": "days",
"value": 2
}
}
},
{
"id": "send-welcome-sms",
"type": "sms",
"name": "Follow-up SMS",
"attributes": {
"body": "Still interested?"
}
}
],
"edges": [
{
"from": "wait-one-day",
"to": "send-welcome-sms"
}
],
"settings": {
"timezone": "account",
"window": {
"condition": "when",
"start": "09:00",
"end": "17:00",
"days": [
1,
2,
3,
4,
5
]
}
}
}
- Webhook — call an external system
{
"version": 1,
"name": "Notify external CRM",
"source": {
"system": "api"
},
"triggers": [
{
"type": "contact_created"
}
],
"actions": [
{
"id": "send-welcome-sms",
"type": "webhook",
"name": "POST to CRM",
"attributes": {
"method": "POST",
"url": "https://example.com/hooks/new-contact",
"headers": [
{
"key": "X-Api-Key",
"value": "your-api-key"
}
],
"customData": [
{
"key": "email",
"value": "{{contact.email}}"
},
{
"key": "source",
"value": "highlevel"
}
]
}
}
],
"edges": []
}
Workflow created
- application/json
- Schema
- Example (auto)
Schema
ID of the created workflow
Status of the new workflow. Always draft — creating something already live is not possible. Absent only in the rare case where the workflow was created but could not be read back.
draftpublishedThe created workflow, in the same shape Get Workflow Definition returns and Update Workflow Definition accepts — so an update needs no separate read. Note version is not 1: the create path saves several times. Absent only if the workflow was created but could not be read back.
Non-blocking findings
{
"workflowId": "b1b0de82-3efb-4d63-83f6-13c50aef208c",
"status": "draft",
"definition": {
"version": 3,
"name": "Welcome new contacts",
"source": {
"system": "api"
},
"triggers": [],
"actions": [],
"edges": []
},
"warnings": [
{
"path": "actions[4]",
"message": "Step has no incoming edges and may be unreachable."
}
]
}