Workflow API
Execute workflows programmatically and manage workflow definitions.
The Workflow API allows you to execute workflows, manage definitions, and monitor execution progress. Workflows run on a durable execution backend that supports long-running processes with pause/resume capabilities.
Authentication
All workflow endpoints support both API Key and Signed JWT authentication.
API Key (server-to-server):
curl -X POST https://service.ensembleapp.ai/api/workflow/start/${WORKFLOW_ID} \
-H "x-api-key: sk_your_api_key" \
-H "x-tenant-id: your_tenant_id" \
-H "Content-Type: application/json" \
-d '{"data": {"customerName": "John Doe"}}'Signed JWT (frontend integrations):
curl -X POST https://service.ensembleapp.ai/api/workflow/start/${WORKFLOW_ID} \
-H "Authorization: Bearer your_jwt_token" \
-H "Content-Type: application/json" \
-d '{"data": {"customerName": "John Doe"}}'See Authentication for details on creating API keys and signing JWTs.
Endpoints
Execute Workflow (Sync)
Execute a workflow and wait for completion.
POST /api/workflow/start/:workflowIdRequest Body:
{
"data": {
"customerName": "John Doe",
"email": "john@example.com"
}
}| Field | Type | Description |
|---|---|---|
data | object | Input payload matching workflow's expected inputs |
Response:
{
"runId": "dynamic-workflow-1705779900000",
"status": "completed",
"data": {
"customerName": "John Doe",
"email": "john@example.com",
"confirmationSent": true
},
"result": {
"success": true
}
}When to use: Simple, fast workflows that complete quickly. The request blocks until the workflow finishes.
Execute Workflow (Async)
Execute a workflow and return immediately with a run ID.
POST /api/workflow/start-async/:workflowIdRequest Body: Same as synchronous execution.
Response:
{
"runId": "dynamic-workflow-1705779900000"
}When to use: Long-running workflows, workflows with human approval steps, or when you need non-blocking execution. Poll the status endpoint to track progress.
Get Execution Status
Check the status and progress of a workflow run.
GET /api/workflow/status/:runIdResponse:
{
"runId": "dynamic-workflow-1705779900000",
"workflowId": "customer-onboarding",
"status": "running",
"currentStepId": "send-email-1",
"pauseSignal": null,
"data": {
"customerName": "John Doe",
"email": "john@example.com"
},
"stepExecutionHistory": [
{
"stepId": "collect-inputs-1",
"stepType": "collect-inputs",
"stepName": "Collect Customer Info",
"status": "completed",
"startTime": "2024-01-20T15:45:00Z",
"endTime": "2024-01-20T15:45:05Z",
"duration": 5000,
"outputData": {
"customerName": "John Doe",
"email": "john@example.com"
}
}
],
"result": null,
"startTime": "2024-01-20T15:45:00Z"
}| Field | Description |
|---|---|
status | Current status: running, completed, failed, paused |
currentStepId | ID of the currently executing step |
pauseSignal | Present when workflow is paused for input |
stepExecutionHistory | Array of completed and in-progress steps |
result | Final output when workflow completes |
Resume Workflow
Resume a paused workflow by providing requested input or action.
POST /api/workflow/resume/:runIdRequest Body (for collect-inputs pause):
{
"type": "collect_inputs",
"data": {
"approvalReason": "Budget approved for Q1"
}
}Request Body (for user-action pause):
{
"type": "request_user_action",
"actionId": "approval-action-1",
"actionValue": "approved"
}| Field | Description |
|---|---|
type | Pause type: collect_inputs or request_user_action |
data | Input data for collect_inputs type |
actionId | Action identifier for request_user_action type |
actionValue | Selected action value (e.g., approved, rejected) |
Get Workflow Input Schema
Retrieve the expected input payload for a workflow.
GET /api/workflow/metadata/input/:workflowIdResponse:
{
"success": true,
"data": {
"workflowId": "customer-onboarding",
"payload": {
"customerName": {"type": "string", "description": "Customer name"},
"email": {"type": "string", "description": "Contact email"}
}
}
}Workflow Management
List Workflows
GET /api/workflowsQuery Parameters:
| Parameter | Default | Description |
|---|---|---|
search | - | Search by name or description |
status | - | Filter by status: draft, testing, published, archived |
includeArchived | false | Include archived workflows |
limit | - | Pagination limit |
offset | - | Pagination offset |
Response:
[
{
"id": "customer-onboarding",
"name": "Customer Onboarding",
"description": "Onboarding workflow for new customers",
"status": "published",
"version": "1.2.0",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-20T15:45:00Z"
}
]Get Workflow
GET /api/workflows/:idQuery Parameters:
| Parameter | Default | Description |
|---|---|---|
version | latest | Version selector: latest, published, or version number |
Get Workflow Versions
GET /api/workflows/:id/versionsReturns all versions of a workflow with their status and metadata.
Create Workflow
POST /api/workflowsRequest Body:
{
"name": "Customer Onboarding",
"description": "Onboarding workflow for new customers",
"initialStep": "collect-inputs-1",
"steps": [
{
"type": "collect-inputs",
"id": "collect-inputs-1",
"output": {
"customerName": {"type": "string"},
"email": {"type": "string"}
}
},
{
"type": "end-flow",
"id": "end-1"
}
],
"edges": [
{"from": "collect-inputs-1", "to": "end-1"}
],
"payload": {}
}Update Workflow
PUT /api/workflows/:idUpdates create a new version automatically. Previous versions are preserved.
Archive Workflow
DELETE /api/workflows/:idSoft-deletes the workflow by setting status to archived. Can be restored with unarchive.
Unarchive Workflow
POST /api/workflows/:id/unarchiveRestores an archived workflow to draft status.
Permanent Delete
DELETE /api/workflows/:id/permanentPermanently deletes an archived workflow. Requires Owner role. This action is irreversible.
Publish Workflow
POST /api/workflows/:id/publishRequest Body:
{
"version": "1.0.0"
}Publishes a specific version, making it available for production use.
Clone Workflow
POST /api/workflows/:id/cloneCreates a copy of the workflow with "(Copy)" suffix. The cloned workflow starts in draft status.
Execution Control
Cancel Workflow
Request graceful cancellation of a running workflow.
POST /api/workflow/management/cancel{
"workflowId": "customer-onboarding",
"runId": "dynamic-workflow-1705779900000",
"reason": "User requested cancellation"
}Terminate Workflow
Force-terminate a running workflow immediately.
POST /api/workflow/management/terminate{
"workflowId": "customer-onboarding",
"runId": "dynamic-workflow-1705779900000",
"reason": "Workflow unresponsive"
}File Uploads
Workflows support file uploads via multipart/form-data. This allows you to pass documents, images, or other files as input to workflows that process attachments.
Execute with Attachment
Use -F flags instead of JSON body to send files along with other parameters:
With Signed JWT:
curl -X POST "https://service.ensembleapp.ai/api/workflow/start/${WORKFLOW_ID}" \
-H "Authorization: Bearer ${YOUR_JWT}" \
-F "attachment=@/path/to/document.pdf" \
-F "customerName=John Doe" \
-F "documentType=invoice"With API Key:
curl -X POST "https://service.ensembleapp.ai/api/workflow/start/${WORKFLOW_ID}" \
-H "x-api-key: sk_your_api_key" \
-H "x-tenant-id: your_tenant_id" \
-F "attachment=@/path/to/document.pdf" \
-F "param1=value1" \
-F "param2=value2"Request Format
When uploading files, use multipart/form-data encoding (automatically set when using -F flags):
| Field | Description |
|---|---|
attachment | The file to upload (use @ prefix for file path) |
| Other fields | Workflow input parameters as key-value pairs |
Constraints
| Constraint | Value |
|---|---|
| Max file size | 3.75 MB |
| Field name | attachment |
| Supported formats | PDF, images, and other common document types |
How Files Are Processed
- The file is uploaded to cloud storage
- A unique UUID is generated for the file reference
- The workflow receives the file reference in its data context
- Workflow steps can access the file for processing (e.g., document extraction, image analysis)
Example: Document Processing Workflow
# Upload a PDF for processing
curl -X POST "https://service.ensembleapp.ai/api/workflow/start/${WORKFLOW_ID}" \
-H "Authorization: Bearer ${YOUR_JWT}" \
-F "attachment=@./contracts/agreement.pdf" \
-F "extractionType=full" \
-F "outputFormat=json"Response:
{
"runId": "dynamic-workflow-1705779900000",
"status": "completed",
"data": {
"fileId": "550e8400-e29b-41d4-a716-446655440000",
"extractedData": {
"title": "Service Agreement",
"parties": ["Company A", "Company B"],
"effectiveDate": "2024-01-15"
}
}
}Error Responses
| Status | Error | Description |
|---|---|---|
| 400 | Invalid input | Missing or invalid request parameters |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions for operation |
| 404 | Workflow not found | Workflow or version doesn't exist |
| 500 | Internal server error | Server-side error |