Workflows API
Create, manage, and execute workflow definitions
Workflows API
Manage workflow definitions including creation, updates, versioning, and execution.
List Workflows
Retrieve all workflows for your company with cursor-based pagination.
GET /api/v1/workflowsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | - | Filter by status: draft, active, paused, archived |
search | string | - | Search by workflow name |
limit | number | 50 | Number of results (1-100) |
cursor | string | - | Cursor for pagination |
Response
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Invoice Automation",
"description": "Process incoming invoices",
"status": "active",
"version": 3,
"trigger": {
"type": "webhook",
"provider": "stripe",
"events": ["invoice.paid"]
},
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-16T14:30:00.000Z"
}
],
"meta": {
"cursor": "eyJ0cyI6MTcwNTMxMjAwMDAwMCwiaWQiOiI1NTBlODQwMC4uLiJ9",
"hasMore": true
}
}Example
curl -X GET "http://localhost:3000/api/v1/workflows?status=active&limit=10" \
-H "x-api-key: YOUR_API_KEY"const response = await fetch(
'http://localhost:3000/api/v1/workflows?status=active&limit=10',
{
headers: { 'x-api-key': process.env.API_KEY }
}
);
const { data, meta } = await response.json();import requests
response = requests.get(
'http://localhost:3000/api/v1/workflows',
params={'status': 'active', 'limit': 10},
headers={'x-api-key': api_key}
)
data = response.json()Create Workflow
Create a new workflow definition. Workflows are created in draft status.
POST /api/v1/workflowsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workflow name (1-255 chars) |
description | string | No | Human-readable description |
trigger | object | Yes | Trigger configuration |
steps | array | Yes | Array of workflow steps |
inputSchema | object | No | JSON Schema for input validation |
outputSchema | object | No | JSON Schema for output |
settings | object | No | Workflow settings |
Example Request
{
"name": "New Customer Onboarding",
"description": "Send welcome email and create CRM contact",
"trigger": {
"type": "webhook",
"provider": "stripe",
"events": ["customer.created"]
},
"steps": [
{
"id": "send-welcome",
"type": "email",
"name": "Send Welcome Email",
"config": {
"action": "send",
"to": "{{input.data.object.email}}",
"subject": "Welcome to our platform!",
"body": {
"html": "<p>Hello {{input.data.object.name}},</p><p>Welcome aboard!</p>"
}
}
},
{
"id": "create-contact",
"type": "action",
"name": "Create HubSpot Contact",
"action": "hubspot.createContact",
"config": {
"email": "{{input.data.object.email}}",
"properties": {
"firstname": "{{input.data.object.name}}",
"stripe_customer_id": "{{input.data.object.id}}"
}
}
}
],
"inputSchema": {
"type": "object",
"required": ["data"],
"properties": {
"data": {
"type": "object",
"properties": {
"object": {
"type": "object",
"properties": {
"id": { "type": "string" },
"email": { "type": "string" },
"name": { "type": "string" }
}
}
}
}
}
}
}Response (201 Created)
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "New Customer Onboarding",
"description": "Send welcome email and create CRM contact",
"status": "draft",
"version": 1,
"trigger": { ... },
"steps": [ ... ],
"inputSchema": { ... },
"outputSchema": null,
"settings": null,
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}
}Get Workflow
Retrieve a specific workflow by ID.
GET /api/v1/workflows/:idPath Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Workflow UUID |
Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Invoice Automation",
"description": "Process incoming invoices",
"status": "active",
"version": 3,
"trigger": {
"type": "webhook",
"provider": "stripe",
"events": ["invoice.paid"]
},
"steps": [
{
"id": "notify-team",
"type": "action",
"name": "Notify Slack",
"action": "slack.sendMessage",
"config": {
"channel": "#finance",
"text": "Invoice {{input.data.object.number}} paid!"
}
}
],
"inputSchema": null,
"outputSchema": null,
"settings": null,
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-16T14:30:00.000Z"
}
}Update Workflow
Update a workflow. If the workflow is active, this increments the version and saves the previous version to history.
PUT /api/v1/workflows/:idRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated workflow name |
description | string | No | Updated description |
trigger | object | No | Updated trigger configuration |
steps | array | No | Updated steps array |
inputSchema | object | No | Updated input schema |
outputSchema | object | No | Updated output schema |
settings | object | No | Updated settings |
changeSummary | string | No | Description of changes (stored in version history) |
Example Request
{
"name": "Invoice Automation v2",
"steps": [
{
"id": "notify-team",
"type": "action",
"name": "Notify Slack",
"action": "slack.sendMessage",
"config": {
"channel": "#finance",
"text": "Invoice {{input.data.object.number}} paid for ${{input.data.object.amount_paid / 100}}!"
}
}
],
"changeSummary": "Added amount to Slack notification"
}Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Invoice Automation v2",
"status": "active",
"version": 4,
...
}
}Delete Workflow
Soft delete (archive) a workflow. This also deletes any associated schedules.
DELETE /api/v1/workflows/:idResponse
{
"success": true,
"data": {
"deleted": true
}
}Activate Workflow
Change workflow status to active. This enables the workflow to be triggered.
POST /api/v1/workflows/:id/activateStatus Transitions
| From | To Active |
|---|---|
draft | Allowed |
paused | Allowed |
active | Not allowed (already active) |
archived | Not allowed |
Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "active"
}
}For schedule triggers, the response includes schedule information:
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "active",
"schedule": {
"id": "sch_xxx",
"triggerScheduleId": "sched_xxx",
"nextRunAt": "2024-01-16T09:00:00.000Z"
}
}
}Pause Workflow
Pause an active workflow. Paused workflows won't be triggered.
POST /api/v1/workflows/:id/pauseResponse
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "paused"
}
}Run Workflow
Trigger a workflow execution via the API. Supports both async (default) and sync execution modes.
POST /api/v1/workflows/:id/runRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
input | object | No | Input data for the workflow |
connectionId | string | No | Specific connection to use |
idempotencyKey | string | No | Prevent duplicate runs (24h TTL) |
mode | string | No | async (default) or sync |
maxExecutionTimeMs | number | No | Max wait time for sync mode (1000-300000ms) |
onTimeout | string | No | Sync timeout behavior: return_run_id, throw_error |
onFailure | string | No | Sync failure behavior: throw_error, switch_to_async |
Async Mode (Default)
Returns immediately with a run ID. Poll the runs API for status updates.
{
"input": {
"customerId": "cus_xxx",
"amount": 9900
}
}Response (202 Accepted):
{
"success": true,
"data": {
"run_id": "run_550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"mode": "async"
}
}Sync Mode
Waits for workflow completion and returns the result directly. Ideal for short-running workflows in request/response scenarios.
{
"input": {
"customerId": "cus_xxx",
"amount": 9900
},
"mode": "sync",
"maxExecutionTimeMs": 30000,
"onTimeout": "return_run_id",
"onFailure": "throw_error"
}Sync Success Response (200):
{
"success": true,
"data": {
"run_id": "run_550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"mode": "sync",
"output": {
"invoiceId": "inv_xxx",
"status": "sent"
},
"duration_ms": 2500
}
}Sync Timeout Response (202):
When execution exceeds maxExecutionTimeMs with onTimeout: "return_run_id":
{
"success": true,
"data": {
"run_id": "run_550e8400-e29b-41d4-a716-446655440000",
"status": "running",
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"mode": "async",
"timed_out": true,
"message": "Execution in progress. Use GET /runs/:id to poll for results."
}
}Sync Mode Parameters
| Parameter | Default | Description |
|---|---|---|
maxExecutionTimeMs | 30000 | Max wait time (1 second to 5 minutes) |
onTimeout | return_run_id | return_run_id returns gracefully, throw_error returns 408 |
onFailure | throw_error | throw_error returns error, switch_to_async returns run ID |
Sync mode is best for workflows completing under 30 seconds. For longer workflows, use async mode with polling or webhooks.
Idempotency
If the same idempotencyKey is used within 24 hours, the existing run is returned:
{
"success": true,
"data": {
"run_id": "run_existing",
"status": "completed",
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Existing run returned (idempotency key matched)"
}
}List Workflow Runs
Get runs for a specific workflow.
GET /api/v1/workflows/:id/runsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | - | Filter: pending, running, completed, failed, cancelled |
limit | number | 50 | Number of results (1-100) |
cursor | string | - | Cursor for pagination |
Response
{
"success": true,
"data": [
{
"id": "run_xxx",
"workflowId": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"triggerType": "api",
"startedAt": "2024-01-15T10:30:00.000Z",
"completedAt": "2024-01-15T10:30:05.000Z",
"durationMs": 5000,
"error": null,
"createdAt": "2024-01-15T10:30:00.000Z"
}
],
"meta": {
"cursor": "eyJ0cyI6MTcwNTMxMjAwMDAwMCwiaWQiOiJydW5feHh4In0=",
"hasMore": false
}
}Clone Workflow
Create a copy of an existing workflow.
POST /api/v1/workflows/:id/cloneRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the cloned workflow |
Example Request
{
"name": "Invoice Automation (Copy)"
}Response (201 Created)
{
"success": true,
"data": {
"id": "new-workflow-id",
"name": "Invoice Automation (Copy)",
"status": "draft",
"version": 1,
"clonedFrom": "550e8400-e29b-41d4-a716-446655440000",
...
}
}Version Management
List Versions
Get all versions of a workflow.
GET /api/v1/workflows/:id/versionsResponse
{
"success": true,
"data": {
"workflowId": "550e8400-e29b-41d4-a716-446655440000",
"currentVersion": 4,
"versions": [
{
"version": 4,
"status": "current",
"isCurrent": true
},
{
"version": 3,
"name": "Invoice Automation",
"changeSummary": "Added error handling",
"status": "archived",
"createdAt": "2024-01-15T10:00:00.000Z",
"isCurrent": false
},
{
"version": 2,
"name": "Invoice Automation",
"changeSummary": "Added Slack notification",
"status": "archived",
"createdAt": "2024-01-14T10:00:00.000Z",
"isCurrent": false
}
]
}
}Get Specific Version
GET /api/v1/workflows/:id/versions/:versionResponse
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"version": 2,
"name": "Invoice Automation",
"description": "Process incoming invoices",
"trigger": { ... },
"steps": [ ... ],
"changeSummary": "Added Slack notification",
"status": "archived",
"isCurrent": false,
"createdAt": "2024-01-14T10:00:00.000Z"
}
}Compare Versions
Compare changes between two versions.
GET /api/v1/workflows/:id/versions/compare?from=2&to=4Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | number | Yes | Source version number |
to | number | Yes | Target version number |
Response
{
"success": true,
"data": {
"fromVersion": 2,
"toVersion": 4,
"changes": {
"name": {
"from": "Invoice Automation",
"to": "Invoice Automation v2",
"changed": true
},
"description": {
"from": "Process incoming invoices",
"to": "Process incoming invoices",
"changed": false
},
"trigger": {
"changed": false
},
"steps": {
"added": ["error-handler"],
"removed": [],
"modified": ["notify-team"]
}
}
}
}Rollback Version
Restore a workflow to a previous version. This creates a new version with the old content.
POST /api/v1/workflows/:id/versions/:version/rollbackRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
changeSummary | string | No | Reason for rollback |
Example Request
{
"changeSummary": "Rolling back due to bug in v4"
}Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"version": 5,
"rolledBackFrom": 4,
"rolledBackTo": 2,
"name": "Invoice Automation",
"status": "active",
...
}
}Schedule Management
Get Schedule
Get schedule information for a workflow with schedule trigger.
GET /api/v1/workflows/:id/scheduleResponse
{
"success": true,
"data": {
"id": "sch_xxx",
"workflowId": "550e8400-e29b-41d4-a716-446655440000",
"triggerScheduleId": "sched_xxx",
"scheduleType": "cron",
"cronExpression": "0 9 * * 1-5",
"interval": null,
"timezone": "America/New_York",
"enabled": true,
"nextRunAt": "2024-01-16T09:00:00.000Z",
"lastRunAt": "2024-01-15T09:00:00.000Z",
"lastRunId": "run_xxx",
"runCount": 42,
"consecutiveFailures": 0,
"lastError": null,
"createdAt": "2024-01-01T10:00:00.000Z",
"updatedAt": "2024-01-15T09:00:05.000Z"
}
}Update Schedule
Modify schedule configuration.
PUT /api/v1/workflows/:id/scheduleRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
cron | string | No | Cron expression |
interval | object | No | Interval configuration |
interval.value | number | Yes | Interval value |
interval.unit | string | Yes | minutes, hours, days, weeks |
timezone | string | No | IANA timezone |
enabled | boolean | No | Enable/disable schedule |
Example Request
{
"cron": "0 10 * * 1-5",
"timezone": "America/Los_Angeles",
"enabled": true
}Response
{
"success": true,
"data": {
"updated": true,
"scheduleId": "sch_xxx",
"nextRunAt": "2024-01-16T10:00:00.000Z"
}
}Manual Schedule Trigger
Manually trigger a scheduled workflow (for testing).
POST /api/v1/workflows/:id/schedule/triggerResponse (202 Accepted)
{
"success": true,
"data": {
"runId": "run_xxx",
"status": "pending",
"workflowId": "550e8400-e29b-41d4-a716-446655440000",
"triggeredAt": "2024-01-15T10:30:00.000Z"
}
}Workflow Statuses
| Status | Description |
|---|---|
draft | Initial state, not yet activated |
active | Running and can be triggered |
paused | Temporarily disabled |
archived | Soft deleted |
Error Responses
Workflow Not Found (404)
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Workflow not found"
}
}Invalid Status Transition (400)
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Cannot transition from 'archived' to 'active'",
"details": {
"currentStatus": "archived",
"targetStatus": "active",
"allowedTransitions": []
}
}
}Validation Error (400)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid workflow steps: Step 'send-email' references non-existent step 'process-data'"
}
}Workflow Not Active (400)
{
"success": false,
"error": {
"code": "WORKFLOW_NOT_ACTIVE",
"message": "Workflow must be active to run"
}
}