Workflows API
CRUD endpoints for workflow templates, plus listing and triggering workflow runs. Workflows are multi-step sequences for lead qualification, property blasts, follow-up campaigns, and more.
List Templates
GET /api/v1/workflowsReturns all workflow templates available to your account (your own templates plus system defaults), with full template detail including steps and configuration.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Items per page (default: 20) |
Response:
{
"data": [
{
"id": "wf_abc123",
"name": "Lead Pre-Screening",
"description": "Qualify prospects with key questions before scheduling a showing.",
"isPublic": true,
"isActive": true,
"triggerType": "manual",
"slug": "prescreening",
"steps": [
{ "type": "send_message", "config": { "template": "intro" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 24 } }
],
"exitConditions": { "maxMessages": 20, "timeoutDays": 7 },
"questionConfig": {},
"completionConfig": {},
"introMessage": "Hi! I'd like to ask a few quick questions.",
"voiceConfig": { "enabled": true },
"version": 3,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-20T08:30:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 4 }
}Get Template
GET /api/v1/workflows/:idReturns the full workflow template including steps, exit conditions, question config, completion config, intro message, voice config, and version info.
Response:
{
"data": {
"id": "wf_abc123",
"name": "Lead Pre-Screening",
"description": "Qualify prospects with key questions before scheduling a showing.",
"isPublic": true,
"isActive": true,
"triggerType": "manual",
"slug": "prescreening",
"steps": [
{ "type": "send_message", "config": { "template": "intro" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 24 } }
],
"exitConditions": { "maxMessages": 20, "timeoutDays": 7 },
"questionConfig": {},
"completionConfig": {},
"introMessage": "Hi! I'd like to ask a few quick questions.",
"voiceConfig": { "enabled": true },
"version": 3,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-20T08:30:00Z"
}
}Create Template
POST /api/v1/workflowsCreate a new workflow template. The slug is auto-generated from the name and must be unique per tenant.
Request Body:
{
"name": "Lead Pre-Screening",
"triggerType": "manual",
"steps": [
{ "type": "send_message", "config": { "template": "intro" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 24 } },
{ "type": "agent", "config": { "mode": "interactive" } }
],
"description": "Qualify prospects with key questions before scheduling a showing.",
"exitConditions": { "maxMessages": 20, "timeoutDays": 7 },
"introMessage": "Hi! I'd like to ask a few quick questions.",
"isPublic": true
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name (1-100 chars) |
steps | array | Yes | Workflow step definitions (max 20) |
triggerType | string | Yes | manual, deep_link, automatic, or scheduled |
description | string | No | Human-readable description (max 500 chars) |
triggerConfig | object | No | Trigger-specific configuration |
exitConditions | object | No | maxMessages (1-50) and/or timeoutDays (1-90) |
questionConfig | object | No | Question-level configuration |
completionConfig | object | No | Completion behavior configuration |
isPublic | boolean | No | Whether the workflow is publicly accessible (default: false) |
introMessage | string | No | Opening message sent to the contact (max 2000 chars) |
voiceConfig | object | No | Voice agent configuration |
isActive | boolean | No | Whether the template is active (default: true) |
Response 201 Created:
{
"data": {
"id": "wf_new456",
"name": "Lead Pre-Screening",
"description": "Qualify prospects with key questions before scheduling a showing.",
"isPublic": true,
"isActive": true,
"triggerType": "manual",
"slug": "lead-pre-screening",
"steps": [
{ "type": "send_message", "config": { "template": "intro" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 24 } },
{ "type": "agent", "config": { "mode": "interactive" } }
],
"exitConditions": { "maxMessages": 20, "timeoutDays": 7 },
"questionConfig": null,
"completionConfig": null,
"introMessage": "Hi! I'd like to ask a few quick questions.",
"voiceConfig": null,
"version": 1,
"createdAt": "2026-02-26T12:00:00Z",
"updatedAt": "2026-02-26T12:00:00Z"
}
}Emits a workflow.created webhook event.
Supports Idempotency-Key header.
Update Template
PATCH /api/v1/workflows/:idUpdate an existing workflow template. Send only the fields you want to change.
Changes to execution fields (steps, exitConditions, questionConfig, completionConfig, introMessage) automatically create a version snapshot, incrementing the template’s version number.
Request Body:
{
"description": "Updated description for the screening workflow.",
"steps": [
{ "type": "send_message", "config": { "template": "intro_v2" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 48 } },
{ "type": "agent", "config": { "mode": "interactive" } },
{ "type": "end" }
],
"exitConditions": { "maxMessages": 30, "timeoutDays": 14 }
}| Field | Type | Description |
|---|---|---|
name | string | Template name (1-100 chars) |
steps | array | Workflow step definitions (max 20) |
triggerType | string | manual, deep_link, automatic, or scheduled |
description | string | Human-readable description (max 500 chars) |
triggerConfig | object | Trigger-specific configuration |
exitConditions | object | maxMessages (1-50) and/or timeoutDays (1-90) |
questionConfig | object | Question-level configuration |
completionConfig | object | Completion behavior configuration |
isPublic | boolean | Whether the workflow is publicly accessible |
introMessage | string | Opening message (max 2000 chars) |
voiceConfig | object | Voice agent configuration |
isActive | boolean | Whether the template is active |
Response 200 OK:
{
"data": {
"id": "wf_abc123",
"name": "Lead Pre-Screening",
"description": "Updated description for the screening workflow.",
"isPublic": true,
"isActive": true,
"triggerType": "manual",
"slug": "prescreening",
"steps": [
{ "type": "send_message", "config": { "template": "intro_v2" } },
{ "type": "wait_for_reply", "config": { "timeoutHours": 48 } },
{ "type": "agent", "config": { "mode": "interactive" } },
{ "type": "end" }
],
"exitConditions": { "maxMessages": 30, "timeoutDays": 14 },
"questionConfig": {},
"completionConfig": {},
"introMessage": "Hi! I'd like to ask a few quick questions.",
"voiceConfig": { "enabled": true },
"version": 4,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-26T12:30:00Z"
}
}Emits a workflow.updated webhook event.
Delete Template
DELETE /api/v1/workflows/:idPermanently delete a workflow template and its version history. Completed runs are cascade-deleted.
Returns 409 Conflict if the template has active runs (status pending, running, or paused). Cancel or wait for those runs to finish before deleting.
Response: 204 No Content on success.
Error Response 409 Conflict:
{
"error": {
"code": "conflict",
"message": "Cannot delete workflow template with active runs. Cancel pending runs first."
}
}Emits a workflow.deleted webhook event.
List Runs
GET /api/v1/workflows/runsQuery Parameters:
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Items per page (default: 20) |
status | string | Filter: active, paused, completed, cancelled, failed |
templateId | string | Filter by workflow template ID |
contactId | string | Filter by contact ID |
Response:
{
"data": [
{
"id": "run_abc123",
"workflowTemplateId": "wf_abc123",
"templateName": "Lead Pre-Screening",
"contactId": "550e8400-...",
"status": "active",
"currentStep": 3,
"totalSteps": 8,
"startedAt": "2026-02-11T14:00:00Z",
"completedAt": null
}
],
"pagination": { "page": 1, "limit": 20, "total": 12 }
}Trigger Run
POST /api/v1/workflows/runsStart a new workflow run for a contact.
Request Body:
{
"workflowId": "wf_abc123",
"contactId": "550e8400-e29b-41d4-a716-446655440000",
"propertyId": "prop_def456"
}| Field | Type | Required | Description |
|---|---|---|---|
workflowId | string (UUID) | Yes | The workflow template to run |
contactId | string (UUID) | Yes | The contact to run the workflow for |
propertyId | string (UUID) | No | Property context for property-scoped workflows |
Response 201 Created:
{
"data": {
"id": "run_new123",
"workflowTemplateId": "wf_abc123",
"contactId": "550e8400-...",
"status": "active",
"currentStep": 0,
"totalSteps": 8,
"startedAt": "2026-02-11T15:00:00Z"
}
}Get Run
GET /api/v1/workflows/runs/:idIdempotency
POST /api/v1/workflows and POST /api/v1/workflows/runs support the Idempotency-Key header.