Workflows
Create, manage, deploy, and execute automation workflows. Workflows are composed of interconnected nodes that define data processing pipelines.
All endpoints require authentication via X-API-Key header and the appropriate scope.
Workflow Object
{
"id": "wf_abc123",
"name": "Daily ETL Pipeline",
"description": "Extracts data from MySQL, transforms, and loads to S3",
"status": "active",
"version": 3,
"nodes": [
{
"id": "node_1",
"nodeId": "mysql-source",
"label": "Extract Orders",
"position": { "x": 100, "y": 200 },
"config": {}
}
],
"connections": [
{
"sourceNodeId": "node_1",
"sourcePort": "output",
"targetNodeId": "node_2",
"targetPort": "input"
}
],
"config": {},
"settings": {
"timeout": 3600,
"retryOnFailure": true,
"maxRetries": 3
},
"tags": ["etl", "production"],
"organizationId": "org_xyz",
"ownerId": "user_456",
"sharedWith": ["user_789"],
"isPublic": false,
"isTemplate": false,
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-02-01T14:22:00Z"
}
GET /api/v1/workflows
List all workflows accessible to the authenticated user.
Scope: workflows:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status: draft, active, paused, archived |
tag | string | No | Filter by tag |
search | string | No | Search by name or description |
limit | integer | No | Number of results to return (default: 20) |
offset | integer | No | Number of results to skip (default: 0) |
sort | string | No | Sort field and direction, e.g. createdAt:desc |
Response 200 OK
{
"count": 42,
"limit": 20,
"offset": 0,
"workflows": [
{
"id": "wf_abc123",
"name": "Daily ETL Pipeline",
"description": "Extracts data from MySQL, transforms, and loads to S3",
"status": "active",
"version": 3,
"tags": ["etl", "production"],
"organizationId": "org_xyz",
"ownerId": "user_456",
"isPublic": false,
"isTemplate": false,
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-02-01T14:22:00Z"
}
]
}
POST /api/v1/workflows
Create a new workflow.
Scope: workflows:write
Request Body
{
"name": "Daily ETL Pipeline",
"description": "Extracts data from MySQL, transforms, and loads to S3",
"status": "draft",
"nodes": [],
"connections": [],
"tags": ["etl"],
"settings": {
"timeout": 3600,
"retryOnFailure": true,
"maxRetries": 3
}
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workflow name |
description | string | No | Workflow description |
status | string | No | Initial status (default: draft) |
nodes | array | No | Array of node objects |
connections | array | No | Array of connection objects |
tags | array | No | Array of tag strings |
settings | object | No | Workflow settings (timeout, retry, etc.) |
Response 201 Created
{
"workflowId": "wf_abc123"
}
GET /api/v1/workflows/:id
Get a single workflow by ID.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
Returns the full Workflow object.
PUT /api/v1/workflows/:id
Update an existing workflow.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"name": "Updated ETL Pipeline",
"description": "Updated description",
"nodes": [],
"connections": [],
"tags": ["etl", "v2"],
"settings": {
"timeout": 7200
}
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Workflow name |
description | string | No | Workflow description |
nodes | array | No | Array of node objects |
connections | array | No | Array of connection objects |
tags | array | No | Array of tag strings |
settings | object | No | Workflow settings |
Response 200 OK
Returns the updated Workflow object.
DELETE /api/v1/workflows/:id
Delete a workflow. This action is irreversible.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 204 No Content
POST /api/v1/workflows/:id/duplicate
Duplicate an existing workflow. Creates a copy with a new ID and draft status.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID to duplicate |
Response 201 Created
{
"workflowId": "wf_def456"
}
POST /api/v1/workflows/:id/execute
Execute a workflow. Submits the workflow for execution and returns an execution ID.
Scope: workflows:execute
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"definition": {
"nodes": [],
"connections": []
},
"triggerInputs": {
"key": "value"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
definition | object | No | Override workflow definition for this execution |
triggerInputs | object | No | Input data to pass to the trigger node |
Response 201 Created
{
"executionId": "exec_xyz789"
}
POST /api/v1/workflows/:id/trigger
Trigger a deployed (production) workflow. Proxies the request to the deployed pod's /trigger endpoint inside Kubernetes. Use this for production workflows; use /execute for draft/test runs. Auto-starts the workflow if it is stopped and the lifecycle policy allows it.
Scope: workflows:execute
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"trigger_type": "api",
"inputs": {
"key": "value"
},
"sync": false
}
| Field | Type | Required | Description |
|---|---|---|---|
trigger_type | string | No | Trigger source label (default: api) |
inputs | object | No | Input data for the trigger |
sync | boolean | No | Wait for completion before responding. Sync timeout is 5 minutes; async timeout is 30 seconds (default: false) |
Response 200 OK
{
"status": "started",
"execution_id": "exec_xyz789",
"workflow_id": "wf_abc123",
"output": {}
}
POST /api/v1/workflows/:id/enqueue
Enqueue a workflow execution via its queue trigger node. The workflow must be active and contain a queue trigger node.
Scope: workflows:execute
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"message": {
"orderId": "ord_123"
},
"priority": 0,
"source": "rest_api"
}
| Field | Type | Required | Description |
|---|---|---|---|
message | object | No | Queue message payload (alias: data). The entire body is used if neither is provided. |
priority | number | No | Message priority (default: 0) |
source | string | No | Source label (default: rest_api) |
Response 201 Created
{
"executionId": "exec_xyz789",
"trigger_type": "queue"
}
POST /api/v1/workflows/:id/email-trigger
Trigger a workflow via inbound email. Designed to be POSTed to by external email services (SendGrid, SES, Mailgun) that have parsed an inbound message. The workflow must be active and contain an email trigger node.
Scope: workflows:execute
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"from": "sender@example.com",
"to": "inbox@workflow.strongly.ai",
"subject": "Invoice attached",
"body_text": "Plain text email body",
"body_html": "<p>HTML email body</p>",
"attachments": [],
"email_headers": {}
}
| Field | Type | Required | Description |
|---|---|---|---|
from | string | No | Sender email address |
to | string | No | Recipient email address |
subject | string | No | Email subject |
body_text | string | No | Plain text body (alias: text) |
body_html | string | No | HTML body (alias: html) |
attachments | array | No | Array of parsed attachments |
email_headers | object | No | Raw email headers |
Response 201 Created
{
"executionId": "exec_xyz789",
"trigger_type": "email"
}
POST /api/v1/workflows/events
Emit a platform event. Finds all active workflows in the caller's organization whose event trigger node matches the given event_type and executes each of them.
Scope: workflows:execute
Request Body
{
"event_type": "user.created",
"event_data": {
"userId": "user_456"
},
"source": "platform"
}
| Field | Type | Required | Description |
|---|---|---|---|
event_type | string | Yes | Event type name |
event_data | object | No | Event payload |
source | string | No | Source label (default: platform) |
Response 200 OK
{
"event_type": "user.created",
"workflows_triggered": 2,
"workflows_failed": 0,
"results": [
{
"workflowId": "wf_abc123",
"workflowName": "Send welcome email",
"executionId": "exec_xyz789"
}
]
}
POST /api/v1/workflows/:id/deploy
Deploy a workflow. Provisions the required infrastructure and makes the workflow ready for execution.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"message": "Workflow deployed successfully",
"workflowId": "wf_abc123",
"status": "active"
}
POST /api/v1/workflows/:id/undeploy
Undeploy a workflow. Tears down the provisioned infrastructure.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"message": "Workflow undeployed successfully",
"workflowId": "wf_abc123",
"status": "draft"
}
POST /api/v1/workflows/:id/stop
Stop a deployed workflow by scaling it to zero pods ($0 compute cost). Preserves the deployment for a fast restart via /start.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"deploymentStatus": "stopped"
}
POST /api/v1/workflows/:id/start
Start a stopped workflow by scaling its deployment back up (~10s restart). Much faster than a full deploy because all Kubernetes resources are preserved.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"replicas": 1
}
| Field | Type | Required | Description |
|---|---|---|---|
replicas | number | No | Number of replicas to start (default: 1) |
Response 200 OK
{
"workflowId": "wf_abc123",
"deploymentStatus": "running",
"replicas": 1
}
GET /api/v1/workflows/:id/lifecycle
Get the lifecycle policy and current deployment status for a workflow.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"lifecyclePolicy": {
"type": "idle-shutdown",
"idleTimeoutMinutes": 30
},
"deploymentStatus": "running",
"stoppedReason": null
}
PUT /api/v1/workflows/:id/lifecycle
Update the lifecycle policy for a workflow. Controls when the deployed pod is kept warm versus scaled down.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"type": "scheduled-window",
"schedule": {
"timezone": "America/Los_Angeles",
"windows": [
{
"days": [1, 2, 3, 4, 5],
"startTime": "09:00",
"endTime": "17:00"
}
]
}
}
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | One of always-on, idle-shutdown, on-demand, scheduled-window |
idleTimeoutMinutes | number | No | Minutes of idleness before shutdown (5–1440, default: 30). Required for idle-shutdown. |
schedule | object | No | Required for scheduled-window. Contains timezone and windows[] of { days: number[], startTime: "HH:MM", endTime: "HH:MM" }. days are 0 (Sunday) through 6 (Saturday). |
Response 200 OK
{
"workflowId": "wf_abc123",
"lifecyclePolicy": {
"type": "scheduled-window",
"schedule": {
"timezone": "America/Los_Angeles",
"windows": [
{
"days": [1, 2, 3, 4, 5],
"startTime": "09:00",
"endTime": "17:00"
}
]
}
}
}
PUT /api/v1/workflows/:id/status
Update the status of a workflow.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"status": "active"
}
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | New status. Must be one of: draft, active, paused, archived |
Response 200 OK
Returns the updated Workflow object.
POST /api/v1/workflows/:id/validate
Validate workflow structure. Checks for empty workflows, broken connections, disconnected nodes, nodes that need configuration, and absence of a trigger node.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"valid": true,
"errors": [],
"warnings": [
{
"type": "missing-config",
"message": "Node \"Extract Orders\" (mysql-source) needs configuration",
"nodeId": "node_1"
}
],
"nodeCount": 4,
"connectionCount": 3
}
POST /api/v1/workflows/:id/layout
Automatically arrange all nodes in the workflow in a clean left-to-right layout.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"changed": true,
"nodesRepositioned": 4
}
POST /api/v1/workflows/:id/compute-scopes
Compute and update the required OAuth/integration scopes for a workflow based on its nodes. Run after editing nodes to keep the workflow's scopes array in sync.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"scopes": ["datasources:read:ds_001", "models:invoke:model_001"]
}
GET /api/v1/workflows/:id/versions
List all versions of a workflow.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"currentVersion": 3,
"versions": [
{
"version": 1,
"versionTag": "v1.0.0",
"description": "Initial version",
"createdBy": "user_456",
"createdAt": "2025-01-15T10:30:00Z"
},
{
"version": 2,
"versionTag": "v1.1.0",
"description": "Added error handling",
"createdBy": "user_456",
"createdAt": "2025-01-20T08:15:00Z"
},
{
"version": 3,
"versionTag": "v2.0.0",
"description": "Refactored pipeline",
"createdBy": "user_456",
"createdAt": "2025-02-01T14:22:00Z"
}
]
}
POST /api/v1/workflows/:id/versions
Create a new version snapshot of the workflow.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"versionTag": "v2.1.0",
"description": "Added retry logic to S3 upload node"
}
| Field | Type | Required | Description |
|---|---|---|---|
versionTag | string | Yes | Version tag label |
description | string | No | Description of changes in this version |
Response 201 Created
{
"workflowId": "wf_abc123",
"version": 4,
"versionTag": "v2.1.0"
}
GET /api/v1/workflows/:id/share
List users the workflow is shared with.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"sharedWith": [
{
"userId": "user_789",
"sharedAt": "2025-01-18T12:00:00Z"
}
]
}
POST /api/v1/workflows/:id/share
Share a workflow with another user in the organization.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"userId": "user_789"
}
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | ID of the user to share with |
Response 200 OK
{
"message": "Workflow shared successfully",
"workflowId": "wf_abc123",
"userId": "user_789"
}
DELETE /api/v1/workflows/:id/share/:subId
Remove sharing access for a user.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
subId | string | Yes | User ID to remove |
Response 204 No Content
GET /api/v1/workflows/:id/nodes
List nodes in a workflow with a summary of their inbound and outbound connection counts.
Scope: workflows:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Response 200 OK
{
"workflowId": "wf_abc123",
"count": 2,
"nodes": [
{
"id": "node_1",
"type": "mysql-source",
"label": "Extract Orders",
"category": "sources",
"position": { "x": 100, "y": 200 },
"hasConfig": true,
"inboundConnections": 0,
"outboundConnections": 1
}
]
}
POST /api/v1/workflows/:id/nodes
Add a node to a workflow. The node metadata (type, category, S3 location, resources) is resolved from the workflow node catalog by nodeId. The position is auto-computed if not provided.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"nodeId": "mysql-source",
"label": "Extract Orders",
"version": "1.2.0",
"position": { "x": 100, "y": 200 },
"config": {
"dataSource": "ds_001",
"query": "SELECT * FROM orders"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
nodeId | string | Yes | Catalog node identifier (alias: nodeType for legacy callers) |
label | string | No | Custom label. Defaults to the catalog name. |
version | string | No | Pinned node version. Defaults to the catalog version or latest. |
position | object | No | Position { x, y }. Auto-computed if omitted. |
config | object | No | Initial node configuration |
Response 201 Created
{
"nodeId": "node-xyz123",
"workflowId": "wf_abc123",
"node": {
"id": "node-xyz123",
"type": "mysql-source",
"category": "sources",
"label": "Extract Orders",
"nodeVersion": "1.2.0",
"position": { "x": 100, "y": 200 },
"data": {},
"config": {}
}
}
PUT /api/v1/workflows/:id/nodes/:sub
Configure an existing node in a workflow. Merges the provided config into the node's existing config.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
sub | string | Yes | Node ID within the workflow |
Request Body
{
"config": {
"query": "SELECT * FROM orders WHERE created_at > NOW() - INTERVAL 1 DAY"
},
"label": "Extract Recent Orders"
}
| Field | Type | Required | Description |
|---|---|---|---|
config | object | No | Configuration key-value pairs to merge into the node |
label | string | No | Updated label for the node |
If the body is not wrapped in a config field, the body itself is treated as the config payload.
Response 200 OK
{
"nodeId": "node-xyz123",
"workflowId": "wf_abc123",
"node": {
"id": "node-xyz123",
"type": "mysql-source",
"label": "Extract Recent Orders",
"config": {}
}
}
DELETE /api/v1/workflows/:id/nodes/:sub
Remove a node and all of its incoming and outgoing connections from a workflow.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
sub | string | Yes | Node ID to remove |
Response 200 OK
{
"removed": true,
"nodeId": "node-xyz123",
"removedConnections": 2,
"workflowId": "wf_abc123"
}
PUT /api/v1/workflows/:id/nodes/:sub/input-mappings
Set input mappings for a node. Maps incoming data fields to the node's declared inputs.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
sub | string | Yes | Node ID |
Request Body
{
"mappings": {
"userId": "data.user.id",
"email": "data.user.email"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
mappings | object | Yes | Object mapping target field names to source expressions |
Response 200 OK
{
"nodeId": "node-xyz123",
"workflowId": "wf_abc123",
"inputMappings": {
"userId": "data.user.id",
"email": "data.user.email"
}
}
PUT /api/v1/workflows/:id/nodes/:sub/passthrough-values
Set the passThroughValues for a node. These map input keys to output keys so they pass through the node unchanged.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
sub | string | Yes | Node ID |
Request Body
{
"values": {
"correlationId": "correlationId",
"tenantId": "tenantId"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
values | object | Yes | Object mapping output keys to input keys |
Response 200 OK
{
"nodeId": "node-xyz123",
"workflowId": "wf_abc123",
"passThroughValues": {
"correlationId": "correlationId",
"tenantId": "tenantId"
}
}
POST /api/v1/workflows/:id/connections
Connect two nodes in a workflow. For agent nodes, set targetPort to ai or tools.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
Request Body
{
"sourceNodeId": "node_1",
"targetNodeId": "node_2",
"sourcePort": "output",
"targetPort": "input"
}
| Field | Type | Required | Description |
|---|---|---|---|
sourceNodeId | string | Yes | Source node ID |
targetNodeId | string | Yes | Target node ID |
sourcePort | string | No | Source port (default: output) |
targetPort | string | No | Target port (default: input). Use ai or tools for agent nodes. |
Response 201 Created
{
"connectionId": "conn-abc123",
"workflowId": "wf_abc123",
"connection": {
"id": "conn-abc123",
"source": "node_1",
"target": "node_2",
"sourcePort": "output",
"targetPort": "input"
}
}
DELETE /api/v1/workflows/:id/connections/:sub
Remove a connection between two nodes in a workflow.
Scope: workflows:write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Workflow ID |
sub | string | Yes | Connection ID to remove |
Response 200 OK
{
"removed": true,
"connectionId": "conn-abc123",
"workflowId": "wf_abc123"
}
GET /api/v1/workflows/discover
Discover production workflows belonging to a marketplace app. Returns the in-cluster trigger endpoint for each matching active workflow, used by marketplace apps to call workflows they own.
Scope: workflows:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
appId | string | Yes | Marketplace app ID |
Response 200 OK
[
{
"id": "wf_abc123",
"name": "Daily ETL Pipeline",
"description": "Extracts data from MySQL, transforms, and loads to S3",
"trigger_type": "webhook",
"mode": "production",
"endpoints": {
"proxy_url": "http://workflow-wf_abc123.user-workflows.svc.cluster.local/trigger",
"method": "POST"
},
"deployment": {
"pod_name": "workflow-wf_abc123",
"namespace": "user-workflows"
}
}
]
GET /api/v1/workflows/templates
List available workflow templates.
Scope: workflows:read
Response 200 OK
{
"count": 5,
"templates": [
{
"id": "wf_tmpl_001",
"name": "Basic ETL Pipeline",
"description": "A starter template for extract-transform-load workflows",
"tags": ["etl", "starter"],
"nodes": [],
"connections": [],
"createdAt": "2025-01-01T00:00:00Z"
}
]
}
GET /api/v1/workflows/stats
Get aggregate statistics for workflows in the organization.
Scope: workflows:read
Response 200 OK
{
"total": 42,
"active": 18,
"paused": 5,
"draft": 15,
"archived": 4
}