each::labs API Documentation
This interactive API reference is deprecated. Use
docs.eachlabs.ai
for canonical Eachlabs API documentation. Machine-readable specs remain
available below.
Machine-readable API specifications:
Models API (OpenAPI 3.0.3)
openapi: 3.0.3
info:
title: each::labs Official API v1
description: |
Official each::labs API V1.
This API provides access to our comprehensive AI model catalog and other resources.
## Public contract notes
- Public API routes handled by request logging include `X-Request-Id` for
support and log correlation. Clients may send `X-Request-Id`; otherwise
api-service generates one. Root, health, and metrics endpoints are excluded.
- REST error bodies keep the backward-compatible JSON shape used by existing
clients. Most errors include at least `error`; some shared error paths also
include `status` and `details`. Use the HTTP status code as the primary
programmatic signal unless an endpoint documents a richer envelope.
- Rate-limit and retry headers are endpoint-dependent. If a response includes
`Retry-After`, honor it before retrying; otherwise use bounded exponential
backoff for retryable 429/5xx responses.
- api-service exposes single workflow trigger through
`/v1/workflows/trigger/{workflowID}/{versionID}`. Bulk workflow trigger is
not routed through api-service; use the workflows-engine public API directly
where bulk trigger is required.
version: 1.0.0
contact:
name: API Support
email: support@eachlabs.ai
x-logo:
url: './logo-white.svg'
altText: 'each::labs'
servers:
- url: https://api.eachlabs.ai
description: Production server
tags:
- name: AI Models
description: Endpoints for listing and retrieving AI models and other resources.
- name: AI Models Prediction
description: Endpoints for managing model predictions
- name: Uploads
description: Endpoints for uploading files that can be used as model inputs.
- name: Executions
description: Endpoints for listing execution history.
- name: Workflows
description: Endpoints for triggering workflow executions through api-service.
- name: OpenAI Compatibility
description: OpenAI-compatible endpoints for LLM Router requests.
- name: Webhooks
description: |
Endpoints for retrieving webhook information and delivery history.
**Note:** Currently, webhooks are only supported for Workflows V2. We are actively expanding webhook support to other services and will update this documentation as new integrations become available.
paths:
/v1/models:
get:
tags:
- AI Models
summary: List AI models
description: Retrieve a paginated list of AI models with optional filters
operationId: listModels
parameters:
- name: name
in: query
schema:
type: string
description: Filter by model name (case-insensitive search)
example: "nano-banana-pro-edit"
- name: limit
in: query
schema:
type: integer
default: 50
minimum: 1
maximum: 500
description: Maximum number of results to return
example: 20
- name: offset
in: query
schema:
type: integer
default: 0
minimum: 0
description: Number of results to skip for pagination
example: 0
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Model'
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/models/{slug}:
get:
tags:
- AI Models
summary: Get model details
description: Retrieve detailed information about a specific model by slug
operationId: getModelByPath
parameters:
- name: slug
in: path
required: true
schema:
type: string
description: Model slug identifier
example: "nano-banana-pro-edit"
responses:
'200':
description: Model details retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ModelDetail'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/models/{slug}/schemas/openapi:
get:
tags:
- AI Models
summary: Get model OpenAPI schema
description: |
Returns an OpenAPI 3.0 document describing the model's input
contract (derived from its request_schema) and the prediction
lifecycle endpoints. Intended for the model API tab and for
clients that consume a per-model machine-readable spec.
operationId: getModelOpenAPI
parameters:
- name: slug
in: path
required: true
schema:
type: string
description: Model slug identifier
example: "nano-banana-pro-edit"
responses:
'200':
description: OpenAPI 3.0 document for the model
content:
application/json:
schema:
type: object
description: An OpenAPI 3.0 document.
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/model:
get:
tags:
- AI Models
summary: Get model details (deprecated)
description: |
Deprecated: use `GET /v1/models/{slug}` instead. Retained for
backwards compatibility; returns the same payload.
deprecated: true
operationId: getModel
parameters:
- name: slug
in: query
required: true
schema:
type: string
description: Model slug identifier
example: "nano-banana-pro-edit"
responses:
'200':
description: Model details retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ModelDetail'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/llm-router/model-catalog:
get:
tags:
- AI Models
summary: Get eachlabs-llm-router model catalog
description: Retrieve the curated visible model list and generated model enum schema for eachlabs-llm-router.
operationId: getLLMRouterModelCatalog
responses:
'200':
description: LLM router model catalog retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/LLMRouterModelCatalog'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/prediction:
post:
tags:
- AI Models Prediction
summary: Create Model Prediction
description: |
Create a new prediction for a specific model.
operationId: createPrediction
security:
- ApiKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePredictionRequest'
example:
model: "flux-1-1-pro"
input:
prompt: "A beautiful sunset over the ocean with vibrant colors"
aspect_ratio: "16:9"
webhook_url: "https://your-app.com/webhook"
webhook_secret: "your-secret-key"
responses:
'200':
description: Prediction created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePredictionResponse'
example:
status: "success"
message: "Prediction created successfully"
predictionID: "abc123-def456-ghi789"
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/prediction/run:
post:
tags:
- AI Models Prediction
summary: Run Model Prediction Synchronously
description: |
Create a prediction and wait for the result. This compatibility endpoint is only supported
for models with synchronous execution enabled; unsupported models return a bad request error.
operationId: runPrediction
security:
- ApiKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePredictionRequest'
example:
model: "eachlabs-llm-router"
input:
model: "openai/gpt-4o-mini"
messages:
- role: "user"
content: "Write a one sentence caption."
responses:
'200':
description: Prediction completed or failed synchronously
content:
application/json:
schema:
$ref: '#/components/schemas/RunPredictionResponse'
example:
status: "success"
message: "Prediction completed successfully"
predictionID: "abc123-def456-ghi789"
output:
text: "A cinematic sunset over the ocean."
error: ""
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/prediction/{id}:
get:
tags:
- AI Models Prediction
summary: Get Model Prediction
description: |
Retrieve the status and results of a model prediction by its ID.
Prediction statuses are `starting` or `processing` while work is in flight.
Terminal statuses are `success`, `failed`, and `cancelled`.
operationId: getPrediction
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Prediction ID
example: "abc123-def456-ghi789"
security:
- ApiKeyAuth: []
responses:
'200':
description: Prediction retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Prediction'
example:
id: "abc123-def456-ghi789"
input:
prompt: "A beautiful sunset over the ocean with vibrant colors"
aspect_ratio: "16:9"
status: "success"
output: "https://storage.example.com/predictions/abc123/image.jpg"
logs: null
metrics:
predict_time: 12.5
cost: 0.05
urls:
cancel: "https://api.eachlabs.ai/v1/prediction/abc123-def456-ghi789/cancel"
get: "https://api.eachlabs.ai/v1/prediction/abc123-def456-ghi789"
'404':
description: Prediction not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "Prediction not found"
'500':
$ref: '#/components/responses/InternalServerError'
/v1/prediction/{id}/cancel:
post:
tags:
- AI Models Prediction
summary: Cancel Model Prediction
description: |
Cancel a running prediction by ID. Cancellation is best-effort for upstream providers;
not every provider can interrupt work that is already running. When provider
cancellation is supported and succeeds, the Eachlabs execution record is updated
to `cancelled`; otherwise the original prediction may still complete or fail.
operationId: cancelPrediction
security:
- ApiKeyAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Prediction ID
example: "abc123-def456-ghi789"
responses:
'200':
description: Prediction cancellation accepted
content:
application/json:
schema:
$ref: '#/components/schemas/CancelPredictionResponse'
example:
status: "cancelled"
message: "Prediction canceled successfully"
predictionID: "abc123-def456-ghi789"
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/upload/presign:
post:
tags:
- Uploads
summary: Create Presigned Upload URL
description: |
Create a short-lived presigned URL for uploading media files. Upload the raw file bytes
to `presigned_url` using every header returned in `required_headers`, then pass
`public_url` as a model input.
operationId: presignUpload
security:
- ApiKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PresignUploadRequest'
example:
content_type: "image/png"
file_type: "image"
responses:
'200':
description: Presigned upload URL created
content:
application/json:
schema:
$ref: '#/components/schemas/PresignUploadResponse'
example:
id: "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
presigned_url: "https://eachlabs-storage.s3.amazonaws.com/uploads/...?X-Amz-Signature=..."
public_url: "https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png"
expires_at: "2026-04-27T18:15:00Z"
required_headers:
x-amz-meta-file-id: "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/executions:
get:
tags:
- Executions
summary: List executions
description: |
Retrieve execution history for the authenticated API key with optional filters.
Model prediction terminal statuses include `success`, `failed`, and `cancelled`;
workflow executions can surface `running`, `completed`, `failed`, or `cancelled`
depending on the originating backend.
operationId: listExecutions
security:
- ApiKeyAuth: []
parameters:
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Maximum number of executions to return
example: 20
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
description: Number of executions to skip for pagination
example: 0
- name: model
in: query
schema:
type: string
description: Filter executions by model slug
example: "flux-1-1-pro"
- name: status
in: query
schema:
type: string
description: Comma-separated status filter
example: "success,failed"
- name: workflow_id
in: query
schema:
type: string
description: Filter by workflow ID
example: "wf_abc123"
- name: workflow_execution_id
in: query
schema:
type: string
description: Filter by workflow execution ID
example: "wf_exec_abc123"
- name: from
in: query
schema:
type: string
format: date-time
description: Start of creation time window, as RFC 3339
example: "2026-01-01T00:00:00Z"
- name: to
in: query
schema:
type: string
format: date-time
description: End of creation time window, as RFC 3339
example: "2026-01-31T23:59:59Z"
responses:
'200':
description: List of executions
content:
application/json:
schema:
$ref: '#/components/schemas/ListExecutionsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chat/completions:
post:
tags:
- OpenAI Compatibility
summary: Create Chat Completion
description: |
OpenAI-compatible chat completions endpoint backed by Eachlabs LLM Router. Use
`Authorization: Bearer <API_KEY>` and point an OpenAI-compatible client at
`https://api.eachlabs.ai/v1`.
This endpoint uses the OpenAI-compatible error envelope rather than the REST
error body described in the global contract notes.
operationId: createChatCompletion
security:
- BearerAuth: []
parameters:
- name: X-Eachlabs-Webhook-Url
in: header
required: false
schema:
type: string
format: uri
description: Optional webhook URL for asynchronous result delivery.
example: "https://your-app.com/webhook"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChatCompletionRequest'
example:
model: "openai/gpt-4o-mini"
messages:
- role: "user"
content: "Write a one sentence caption."
responses:
'200':
description: OpenAI-compatible chat completion. Requests with `stream: true` return Server-Sent Events.
content:
application/json:
schema:
$ref: '#/components/schemas/ChatCompletionResponse'
text/event-stream:
schema:
type: string
description: |
Server-Sent Events stream for requests with `stream: true`.
Events use OpenAI-compatible `chat.completion.chunk` payloads
and the stream terminates with `data: [DONE]`.
example: |
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"A cinematic"},"finish_reason":null}]}
data: [DONE]
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/OpenAIErrorResponse'
'401':
description: Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/OpenAIErrorResponse'
'402':
description: Insufficient balance
content:
application/json:
schema:
$ref: '#/components/schemas/OpenAIErrorResponse'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/OpenAIErrorResponse'
/v1/workflows:
post:
tags:
- Workflows
summary: Create workflow
description: |
Create a new workflow together with its initial version. This route forwards to
workflows-engine, which generates the slug, persists the workflow + version, and
provisions the execution state machine.
Only `name` is required. `definition` is the workflow DSL as an arbitrary JSON
object (steps, input_schema, metadata). Categories, tags, and visibility are not
accepted on this route — workflows-engine applies its defaults (categories
`["general"]`, visibility `private`).
operationId: createWorkflow
security:
- ApiKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowCreateRequest'
example:
name: "My Workflow"
definition:
version: "1.0"
steps: []
responses:
'201':
description: Workflow created
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowDetailResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'408':
$ref: '#/components/responses/RequestTimeout'
'409':
$ref: '#/components/responses/Conflict'
'502':
$ref: '#/components/responses/BadGateway'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/workflows/trigger/{workflowID}/{versionID}:
post:
tags:
- Workflows
summary: Trigger workflow execution
description: |
Start an asynchronous workflow execution through api-service. This route forwards to
workflows-engine and requires callers to pin the workflow version in the path.
The immediate response only confirms the workflow was queued. Downstream workflow
lifecycle statuses are `running`, `completed`, `failed`, and `cancelled`.
api-service does not expose workflows-engine's bulk trigger route.
operationId: triggerWorkflowExecution
security:
- ApiKeyAuth: []
parameters:
- name: workflowID
in: path
required: true
schema:
type: string
description: Workflow ID or slug to execute.
example: "wf_abc123"
- name: versionID
in: path
required: true
schema:
type: string
description: Workflow version ID to execute.
example: "v1"
- name: webhook_url
in: query
required: false
schema:
type: string
format: uri
description: Optional compatibility query parameter for execution completion webhooks. The request body field takes precedence when both are present.
example: "https://your-app.com/webhook"
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowTriggerRequest'
example:
inputs:
prompt: "A cinematic establishing shot of a mountain lake"
webhook_url: "https://your-app.com/webhook"
webhook_secret: "your-secret-key"
responses:
'202':
description: Workflow execution queued
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowTriggerResponse'
example:
execution_id: "exec_xyz789"
status: "queued"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'408':
$ref: '#/components/responses/RequestTimeout'
'409':
$ref: '#/components/responses/Conflict'
'502':
$ref: '#/components/responses/BadGateway'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/files/{id}:
delete:
tags:
- Uploads
summary: Delete uploaded file
description: |
Delete a previously uploaded file by its ID. Returns 204 on success.
Proxies the delete request to storage-service and passes through its
status codes: 404 when the file does not exist, 409 when deletion is
not permitted for the file's current state.
operationId: deleteFile
security:
- ApiKeyAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: File ID returned by the presign upload endpoint
example: "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
responses:
'204':
description: File deleted successfully
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/webhooks:
get:
tags:
- Webhooks
summary: List webhooks
description: Retrieve a paginated list of webhooks for the authenticated organization
operationId: listWebhooks
security:
- ApiKeyAuth: []
parameters:
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 50
description: Maximum number of webhooks to return
example: 50
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
description: Number of webhooks to skip for pagination
example: 0
responses:
'200':
description: List of webhooks
content:
application/json:
schema:
$ref: '#/components/schemas/ListWebhooksResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/webhooks/{execution_id}:
get:
tags:
- Webhooks
summary: Get webhook by execution ID
description: Retrieve details of a specific webhook including delivery attempts by execution ID
operationId: getWebhook
security:
- ApiKeyAuth: []
parameters:
- name: execution_id
in: path
required: true
schema:
type: string
description: Execution ID for tracking the webhook
example: "abc123-def456-ghi789"
responses:
'200':
description: Webhook details
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookWithAttempts'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
headers:
RequestId:
description: Request correlation ID. Echoes the incoming `X-Request-Id` header or a generated ID.
schema:
type: string
example: "123e4567-e89b-12d3-a456-426614174000"
RetryAfter:
description: Optional retry delay returned by rate-limit or upstream retry responses when available.
schema:
oneOf:
- type: integer
minimum: 0
- type: string
example: 30
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: API key for authentication
BearerAuth:
type: http
scheme: bearer
description: API key passed as an Authorization Bearer token for OpenAI-compatible endpoints
schemas:
Model:
type: object
properties:
title:
type: string
example: "Nano Banana Pro Edit"
slug:
type: string
example: "nano-banana-pro-edit"
version:
type: string
deprecated: true
description: "Deprecated. Always returns \"0.0.1\". Will be removed in a future version."
example: "0.0.1"
output_type:
type: string
example: "array"
request_schema:
type: object
description: |
JSON Schema for API requests to this model.
Defines the structure, types, and validation rules for making requests.
example:
type: object
required: ["prompt"]
properties:
prompt:
type: string
minLength: 10
maxLength: 500
num_images:
type: integer
minimum: 1
maximum: 4
default: 1
ModelDetail:
type: object
properties:
title:
type: string
example: "Nano Banana Pro Edit"
slug:
type: string
example: "nano-banana-pro-edit"
version:
type: string
deprecated: true
description: "Deprecated. Always returns \"0.0.1\". Will be removed in a future version."
example: "0.0.1"
output_type:
type: string
example: "array"
request_schema:
type: object
description: |
JSON Schema for API requests to this model.
Defines the structure, types, and validation rules for making requests.
example:
type: object
required: ["prompt"]
properties:
prompt:
type: string
minLength: 10
maxLength: 500
LLMRouterModelCatalog:
type: object
properties:
slug:
type: string
example: "eachlabs-llm-router"
source:
type: string
enum: ["catalog", "odoo_fallback"]
version:
type: integer
example: 1
updated_at:
type: string
example: "2026-05-24"
model_enum:
type: array
items:
type: string
example: ["openai/gpt-5.2", "anthropic/claude-sonnet-4-6"]
request_schema:
type: object
description: JSON Schema fragment containing the generated model enum.
models:
type: array
items:
$ref: '#/components/schemas/LLMRouterCatalogModel'
LLMRouterCatalogModel:
type: object
properties:
id:
type: string
example: "openai/gpt-5.2"
status:
type: string
example: "visible"
family:
type: string
example: "openai"
canonical_provider:
type: string
example: "openrouter"
canonical_target_model:
type: string
example: "openai/gpt-5.2"
routing_policy:
type: string
example: "explicit_route"
legacy_requesty:
type: boolean
title:
type: string
example: "GPT-5.2"
description:
type: string
faqs:
type: array
items:
$ref: '#/components/schemas/LLMRouterCatalogFAQ'
readme_md:
type: string
LLMRouterCatalogFAQ:
type: object
properties:
question:
type: string
answer:
type: string
WorkflowTriggerRequest:
type: object
properties:
inputs:
type: object
additionalProperties: true
description: Input values defined by the workflow version. May be omitted for workflows with no inputs.
example:
prompt: "A cinematic establishing shot of a mountain lake"
webhook_url:
type: string
format: uri
description: Optional webhook URL for workflow execution completion.
example: "https://your-app.com/webhook"
webhook_secret:
type: string
description: Optional secret used to sign workflow webhook requests.
example: "your-secret-key"
WorkflowTriggerResponse:
type: object
properties:
execution_id:
type: string
description: Queued workflow execution identifier.
example: "exec_xyz789"
status:
type: string
enum:
- queued
description: Execution queue status returned immediately after triggering.
example: "queued"
WorkflowCreateRequest:
type: object
required:
- name
properties:
name:
type: string
description: Human-readable workflow name. Required.
example: "My Workflow"
definition:
type: object
additionalProperties: true
description: Workflow DSL (steps, input_schema, metadata) as a JSON object.
example:
version: "1.0"
steps: []
WorkflowDetailResponse:
type: object
description: The created workflow (summary fields + its versions).
properties:
workflow_id:
type: string
example: "wf_abc123"
slug:
type: string
example: "my-workflow"
name:
type: string
example: "My Workflow"
categories:
type: array
items:
type: string
example: ["video"]
tags:
type: array
items:
type: string
example: ["beta"]
status:
type: string
example: "active"
trigger_count:
type: integer
example: 0
clone_count:
type: integer
example: 0
is_public:
type: boolean
example: false
production:
type: boolean
example: false
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
versions:
type: array
items:
$ref: '#/components/schemas/WorkflowVersionDetail'
WorkflowVersionDetail:
type: object
properties:
version_id:
type: string
example: "1.0"
slug:
type: string
example: "my-workflow"
published:
type: boolean
example: true
locked:
type: boolean
example: false
production:
type: boolean
example: false
allowed_to_share:
type: boolean
example: false
trigger_count:
type: integer
example: 0
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
definition:
type: object
additionalProperties: true
description: The version's workflow DSL.
status:
type: string
example: "active"
public_description:
type: string
nullable: true
public_thumbnail:
type: string
nullable: true
public_example_output:
type: string
nullable: true
Error:
type: object
description: |
Backward-compatible REST error body. Endpoint-specific handlers may return only
`error`; shared error paths may also include `status` and `details`.
properties:
status:
type: integer
description: HTTP status code, when returned by the shared error handler.
example: 400
error:
type: string
description: Safe user-facing error message.
example: "error message"
details:
nullable: true
description: Optional validation or request details for client errors.
required:
- error
CreatePredictionRequest:
type: object
required:
- model
- input
properties:
model:
type: string
description: Model slug or identifier
example: "flux-1-1-pro"
version:
type: string
deprecated: true
description: "Deprecated. This field is ignored. Kept for backwards compatibility."
example: "0.0.1"
input:
type: object
description: Input parameters for the prediction
additionalProperties: true
example:
prompt: "A beautiful sunset over the ocean with vibrant colors"
aspect_ratio: "16:9"
webhook_url:
type: string
format: uri
description: Optional webhook URL to receive prediction result asynchronously
example: "https://your-app.com/webhook"
webhook_secret:
type: string
description: Optional secret used to sign webhook requests
example: "your-secret-key"
CreatePredictionResponse:
type: object
properties:
status:
type: string
description: Status of the prediction creation request
example: "success"
message:
type: string
description: Human-readable message about the prediction creation
example: "Prediction created successfully"
predictionID:
type: string
description: Unique prediction identifier
example: "abc123-def456-ghi789"
RunPredictionResponse:
type: object
properties:
status:
type: string
enum:
- success
- failed
- cancelled
description: Final terminal status of the synchronous prediction
example: "success"
message:
type: string
description: Human-readable message
example: "Prediction completed successfully"
predictionID:
type: string
description: Unique prediction identifier
example: "abc123-def456-ghi789"
output:
description: Prediction output, when available
nullable: true
oneOf:
- type: string
- type: array
- type: object
error:
type: string
description: User-facing error message when the prediction failed
example: ""
CancelPredictionResponse:
type: object
properties:
status:
type: string
enum:
- cancelled
description: Cancellation status returned when the cancellation request succeeds
example: "cancelled"
message:
type: string
description: Human-readable cancellation message
example: "Prediction canceled successfully"
predictionID:
type: string
description: Unique prediction identifier
example: "abc123-def456-ghi789"
Prediction:
type: object
properties:
id:
type: string
description: Unique prediction identifier
example: "abc123-def456-ghi789"
input:
type: object
description: Input parameters used for the prediction
additionalProperties: true
example:
prompt: "A beautiful sunset over the ocean with vibrant colors"
aspect_ratio: "16:9"
status:
type: string
description: |
Current status of the prediction. `starting` and `processing` are
non-terminal. `success`, `failed`, and `cancelled` are terminal.
enum:
- starting
- processing
- success
- failed
- cancelled
example: "success"
output:
description: Prediction output (type varies based on model)
oneOf:
- type: string
- type: array
- type: object
example: "https://storage.example.com/predictions/abc123/image.jpg"
logs:
type: string
nullable: true
description: Execution logs from the prediction
example: null
metrics:
type: object
description: Performance and cost metrics
properties:
predict_time:
type: number
description: Time taken for prediction in seconds
example: 12.5
cost:
type: number
description: Cost of the prediction in USD
example: 0.05
urls:
type: object
description: Related API endpoints
properties:
cancel:
type: string
format: uri
description: URL to cancel the prediction
example: "https://api.eachlabs.ai/v1/prediction/abc123-def456-ghi789/cancel"
get:
type: string
format: uri
description: URL to get the prediction
example: "https://api.eachlabs.ai/v1/prediction/abc123-def456-ghi789"
PresignUploadRequest:
type: object
required:
- content_type
properties:
content_type:
type: string
description: MIME type of the file to upload
example: "image/png"
file_type:
type: string
description: High-level file category
enum:
- image
- video
- audio
- other
example: "image"
ttl_days:
type: integer
nullable: true
description: Optional file TTL tier in days, when enabled for the caller
example: 30
PresignUploadResponse:
type: object
properties:
id:
type: string
description: Upload identifier
example: "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
presigned_url:
type: string
format: uri
description: Short-lived URL for uploading raw file bytes
example: "https://eachlabs-storage.s3.amazonaws.com/uploads/...?X-Amz-Signature=..."
public_url:
type: string
format: uri
description: Public URL to pass as a model input after upload succeeds
example: "https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png"
expires_at:
type: string
format: date-time
description: Presigned URL expiration time
example: "2026-04-27T18:15:00Z"
required_headers:
type: object
description: Headers that must be sent verbatim with the upload PUT request
additionalProperties:
type: string
example:
x-amz-meta-file-id: "0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0"
ExecutionSummary:
type: object
properties:
id:
type: string
description: Execution identifier
example: "exec_abc123"
model:
type: string
description: Model slug
example: "flux-1-1-pro"
status:
type: string
description: |
Execution status. Model prediction terminal statuses include `success`,
`failed`, and `cancelled`; workflow executions can surface `running`,
`completed`, `failed`, or `cancelled` depending on the originating backend.
example: "success"
workflow_id:
type: string
nullable: true
description: Workflow ID, when execution was triggered by a workflow
example: "wf_abc123"
workflow_execution_id:
type: string
nullable: true
description: Workflow execution ID, when execution was triggered by a workflow
example: "wf_exec_abc123"
execution_cost:
type: number
description: Execution cost in USD
example: 0.05
run_time:
type: number
description: Runtime in seconds
example: 12.5
created_at:
type: string
format: date-time
description: Creation timestamp
example: "2026-01-01T00:00:00Z"
started_at:
type: string
format: date-time
nullable: true
description: Start timestamp
example: "2026-01-01T00:00:02Z"
completed_at:
type: string
format: date-time
nullable: true
description: Completion timestamp
example: "2026-01-01T00:00:15Z"
output:
type: string
nullable: true
description: Primary execution output, when available
example: "https://storage.example.com/predictions/abc123/image.jpg"
ListExecutionsResponse:
type: object
properties:
executions:
type: array
items:
$ref: '#/components/schemas/ExecutionSummary'
total_count:
type: integer
description: Total number of matching executions
example: 123
offset:
type: integer
description: Applied offset
example: 0
limit:
type: integer
description: Applied limit
example: 20
required:
- executions
- total_count
- offset
- limit
ChatCompletionRequest:
type: object
description: OpenAI-compatible chat completions request body
required:
- model
- messages
additionalProperties: true
properties:
model:
type: string
description: LLM model identifier
example: "openai/gpt-4o-mini"
messages:
type: array
items:
type: object
additionalProperties: true
description: OpenAI-compatible chat messages
example:
- role: "user"
content: "Write a one sentence caption."
stream:
type: boolean
description: Set to `true` to receive OpenAI-compatible SSE chunks (`text/event-stream`) instead of a buffered JSON response.
example: false
stream_options:
type: object
nullable: true
additionalProperties: true
description: Optional OpenAI-compatible streaming options. When `include_usage` is true, the stream may include a final usage chunk before `[DONE]`.
properties:
include_usage:
type: boolean
description: Include token usage in the streamed response when provider usage data is available.
example: true
ChatCompletionResponse:
type: object
description: OpenAI-compatible chat completions response
properties:
id:
type: string
example: "chatcmpl-abc123"
object:
type: string
example: "chat.completion"
created:
type: integer
format: int64
example: 1773651600
model:
type: string
example: "eachlabs-llm-router"
choices:
type: array
items:
type: object
properties:
index:
type: integer
example: 0
message:
type: object
properties:
role:
type: string
example: "assistant"
content:
type: string
example: "A cinematic sunset over the ocean."
finish_reason:
type: string
example: "stop"
usage:
type: object
nullable: true
properties:
prompt_tokens:
type: integer
example: 12
completion_tokens:
type: integer
example: 8
total_tokens:
type: integer
example: 20
OpenAIErrorResponse:
type: object
description: OpenAI-compatible error envelope used only by `/v1/chat/completions`.
properties:
error:
type: object
properties:
message:
type: string
example: "Invalid API key"
type:
type: string
example: "authentication_error"
param:
type: string
example: "model"
code:
type: string
example: "invalid_api_key"
Webhook:
type: object
description: Webhook information without attempts
properties:
execution_id:
type: string
nullable: true
description: Execution identifier for tracking
example: "abc123-def456-ghi789"
url:
type: string
format: uri
description: Target URL for webhook delivery
example: "https://api.example.com/webhook"
request:
type: string
description: Original request payload
example: "{\"event\":\"prediction.completed\"}"
headers:
type: object
description: Headers included in the webhook request
additionalProperties:
type: string
example:
"Content-Type": "application/json"
source:
type: string
description: Service that triggered the webhook
example: "api-gateway"
created_at:
type: string
format: date-time
description: When the webhook was created
example: "2025-12-14T10:30:00Z"
required:
- url
- request
- source
- created_at
WebhookWithAttempts:
allOf:
- $ref: '#/components/schemas/Webhook'
- type: object
properties:
attempts:
type: array
description: Delivery attempts for this webhook
items:
$ref: '#/components/schemas/WebhookAttempt'
WebhookAttempt:
type: object
description: Individual webhook delivery attempt
properties:
status:
type: string
enum:
- PENDING
- SUCCESS
- FAILED
description: Status of the delivery attempt
example: "SUCCESS"
status_code:
type: integer
nullable: true
description: HTTP status code from target URL
example: 200
response:
type: string
nullable: true
description: Response body from target URL
example: "{\"received\":true}"
error_message:
type: string
nullable: true
description: Error message if delivery failed
example: "connection timeout"
created_at:
type: string
format: date-time
description: When the attempt was made
example: "2025-12-14T10:30:05Z"
required:
- status
- created_at
ListWebhooksResponse:
type: object
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/Webhook'
limit:
type: integer
description: Applied limit
example: 50
offset:
type: integer
description: Applied offset
example: 0
total_count:
type: integer
description: Total number of matching webhooks
example: 123
required:
- webhooks
- limit
- offset
- total_count
responses:
BadRequest:
description: Bad request
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "slug parameter is required"
NotFound:
description: Resource not found
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "Failed to fetch model: model not found"
Unauthorized:
description: Authentication required or invalid credentials
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "Invalid or missing API key"
PaymentRequired:
description: Insufficient balance
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "insufficient balance"
Forbidden:
description: Forbidden
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "forbidden"
Conflict:
description: Conflict with current resource state
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "conflict"
RequestTimeout:
description: Upstream request timed out
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "Request timeout"
UnprocessableEntity:
description: Request body could not be processed
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "invalid request body"
BadGateway:
description: Upstream service unavailable
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "workflows-engine unavailable"
InternalServerError:
description: Internal server error
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: "Failed to fetch models: internal error"
Workflows API (OpenAPI 3.0.3)
openapi: 3.0.3
info:
title: Workflows Engine API
description: |
# Workflows Engine API
Execute and monitor AI workflows with a simple, consistent API.
## Quick Start
1. **Trigger a workflow** - POST to `https://api.eachlabs.ai/v1/workflows/trigger/{workflowID}/{versionID}` with your inputs
2. **Monitor execution** - GET `/executions/{executionID}` to check status
3. **Optional**: Provide a `webhook_url` to receive automatic notifications when complete
---
## Webhook Notifications
When you provide a `webhook_url` when triggering a workflow, the Workflows Engine will automatically
**POST** to your endpoint with the execution results when the workflow completes (successfully or with an error).
### Key Features
- ✅ **Consistent Payload**: The webhook payload has the same structure as the response from `GET /executions/{executionID}`
- ✅ **Automatic Retries**: Failed webhook deliveries are automatically retried with exponential backoff
- ✅ **Simple Integration**: No authentication required - your endpoint just needs to accept POST requests
### Webhook Request
The engine will POST to your `webhook_url` with:
- **Method**: `POST`
- **Content-Type**: `application/json`
- **Body**: Execution details (see payload structure below)
### Example Webhook Payload
```json
{
"execution_id": "69ae8c7b-7500-4a45-b7c0-348b8cc2665b",
"workflow_id": "50741f40-8621-4d46-8a91-dff4d873be98",
"status": "completed",
"started_at": "2025-12-04T11:48:10Z",
"inputs": {
"story": "tell an epic story of a rat graduating from law"
},
"step_outputs": {
"step1": {
"step_id": "step1",
"status": "completed",
"output": "Once upon a time in Ratropolis...",
"primary": "Once upon a time in Ratropolis...",
"metadata": {
"model": "openai-chatgpt-5",
"version": "0.0.1",
"params": {
"system_prompt": "You are a helpful assistant",
"max_output_tokens": 512
}
}
},
"step2": {
"step_id": "step2",
"status": "completed",
"output": [
"https://storage.googleapis.com/uploads/image1.png",
"https://storage.googleapis.com/uploads/image2.png"
],
"primary": "https://storage.googleapis.com/uploads/image1.png",
"metadata": {
"model": "nano-banana-pro",
"params": {
"num_images": 2,
"aspect_ratio": "16:9"
}
}
}
},
"output": [
"https://storage.googleapis.com/uploads/image1.png",
"https://storage.googleapis.com/uploads/image2.png"
]
}
```
### Example Webhook Handler
```python
@app.post("/webhooks/workflow-completed")
async def handle_workflow_webhook(request: Request):
execution = await request.json()
if execution["status"] == "completed":
# Process successful execution
final_output = execution["output"]
step_details = execution["step_outputs"]
print(f"Workflow completed: {final_output}")
elif execution["status"] == "failed":
# Handle failure
error = execution.get("error_cause", "Unknown error")
print(f"Workflow failed: {error}")
return {"received": True}
```
Your webhook endpoint should return a `200 OK` status to acknowledge receipt.
---
## Fallback Configuration
Model steps support an optional **fallback configuration** that automatically retries with an alternative
model if the primary model invocation fails. This provides resilience against temporary model outages
or rate limits.
### How Fallback Works
When a model step has fallback configured, the workflow engine will:
1. **Execute the primary model** with its configured parameters
2. **If the primary attempt fails**, automatically execute the fallback model configuration
3. **Mark the step as failed only if both primary and fallback attempts fail**
### Fallback Configuration
Add a `fallback` object to any model step in your workflow definition:
```json
{
"step_id": "generate_image",
"type": "model",
"model": "flux-dev",
"params": {
"prompt": "{{inputs.prompt}}",
"num_images": 1
},
"fallback": {
"enabled": true,
"model": "flux-1-1-pro",
"params": {
"prompt": "{{inputs.prompt}}",
"guidance_scale": 7.5
}
}
}
```
### Fallback Properties
| Property | Type | Description |
|----------|------|-------------|
| `enabled` | boolean | Enable or disable fallback for this step (default: `true`) |
| `model` | string | Alternative AI model identifier to use on failure |
| `version` | string | Fallback model version (defaults to primary version when omitted) |
| `params` | object | Model-specific parameters for the fallback (supports template variables) |
### Detecting Fallback Usage
When a fallback is used, the step's metadata in execution results will include:
- `fallback_used: true` - Indicates the step completed using the fallback configuration
- `primary_error` - Human-readable description of why the primary attempt failed
### Example Execution Response with Fallback
```json
{
"step_id": "generate_image",
"status": "completed",
"output": "https://storage.googleapis.com/uploads/image.png",
"metadata": {
"model": "flux-1-1-pro",
"fallback_used": true,
"primary_error": "Primary model flux-dev failed: rate limit exceeded"
}
}
```
---
## Unlisted Workflows
Versions can be "unlisted" - accessible via direct link but hidden from public listings.
**Visibility states:**
- **Private** (default): Organization only
- **Unlisted**: Accessible via link, hidden from public listings
- **Public**: Visible in listings and accessible to everyone
**Setting unlisted:** Use `allowed_to_share: true` when creating or updating a version.
```bash
# Create unlisted version
PUT /workflows/{workflowID}/versions/v1 { "allowed_to_share": true, ... }
```
**Behavior:**
- `allowed_to_share: true` → Creates/updates as unlisted
- `allowed_to_share: false` → Creates/updates as private
- No effect on public versions (never downgraded)
version: 1.0.0
x-logo:
url: './logo-white.svg'
altText: 'Eachlabs Logo'
servers:
- url: https://workflows.eachlabs.run/api/v1
description: Production server
security:
- ApiKeyAuth: []
tags:
- name: Categories
description: Workflow categories for organization
- name: Workflows
description: Workflow and version management
- name: Executions
description: Workflow execution and monitoring
- name: Public Workflows
description: Access public and unlisted workflows by organization nickname
paths:
/categories:
get:
tags:
- Categories
summary: List categories
description: |
Retrieve all available workflow categories.
Categories help organize workflows into logical collections.
Use the category slugs when creating or updating workflows.
operationId: listCategories
responses:
'200':
description: Categories retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/CategoriesResponse'
/workflows:
post:
tags:
- Workflows
summary: Create workflow
description: |
Create a new workflow with an initial version and generate its state machine.
This endpoint creates both the workflow metadata and its first version in a single operation.
The workflow definition must include at least one step.
operationId: createWorkflow
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkflowRequest'
responses:
'201':
description: Workflow created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowDetail'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/workflows/{workflowID}:
parameters:
- $ref: '#/components/parameters/WorkflowID'
get:
tags:
- Workflows
summary: Get workflow details
description: |
Retrieve detailed information about a workflow including all its versions.
You can specify either the workflow UUID or slug as the workflowID parameter.
operationId: getWorkflow
responses:
'200':
description: Workflow details retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowDetail'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
put:
tags:
- Workflows
summary: Update workflow
description: |
Update workflow metadata such as name, description, categories, and visibility.
Note: To update the workflow definition (steps), use the version endpoints instead.
Locked workflows cannot be modified unless you're unlocking them.
operationId: updateWorkflow
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateWorkflowRequest'
responses:
'200':
description: Workflow updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowDetail'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/workflows/{workflowID}/versions/{versionID}:
parameters:
- $ref: '#/components/parameters/WorkflowID'
- name: versionID
in: path
required: true
description: Version identifier (e.g., "v1", "v2")
schema:
type: string
example: v1
put:
tags:
- Workflows
summary: Create or update workflow version
description: |
Create a new workflow version or update an existing one.
This operation will:
- Create/update the version in the database
- Generate or update the AWS Step Functions state machine
- Set this version as the latest version for the workflow
**Important**: Once a version is locked, it cannot be modified.
operationId: upsertWorkflowVersion
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertVersionRequest'
responses:
'200':
description: Workflow version created or updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowVersionSummary'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/{workflowID}/trigger:
parameters:
- name: workflowID
in: path
required: true
description: Unique workflow identifier
schema:
type: string
example: wf_abc123
post:
tags:
- Executions
summary: Trigger workflow (deprecated)
deprecated: true
description: |
> **⚠️ Deprecated.** This version-less endpoint is deprecated and will be
> removed on **1 August 2026**. Single workflow trigger has moved to
> api-service; use `POST https://api.eachlabs.ai/v1/workflows/trigger/{workflowID}/{versionID}`
> instead so the triggered version is explicit. Deprecated responses carry
> `Deprecation`, `Sunset`, `Link` (`rel="successor-version"`), and `Warning` headers.
Start an execution of the workflow.
By default, this triggers the latest version of the workflow.
You can optionally specify a version_id in the request body to trigger a specific version.
The workflow is executed asynchronously - you'll receive an execution ID immediately,
then poll `/executions/{executionID}` to check status and retrieve results.
operationId: triggerWorkflow
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TriggerWorkflowRequest'
responses:
'202':
description: Workflow execution started
content:
application/json:
schema:
$ref: '#/components/schemas/ExecutionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/{workflowID}/bulk-trigger:
parameters:
- name: workflowID
in: path
required: true
description: Unique workflow identifier
schema:
type: string
example: wf_abc123
post:
tags:
- Executions
summary: Bulk trigger workflow (deprecated)
deprecated: true
description: |
> **⚠️ Deprecated.** This version-less endpoint is deprecated and will be
> removed on **1 August 2026**. Use the versioned successor
> `POST /workflows/{workflowID}/versions/{versionID}/bulk-trigger` instead so
> the triggered version is explicit. Deprecated responses carry `Deprecation`,
> `Sunset`, `Link` (`rel="successor-version"`), and `Warning` headers.
Start multiple executions of the same workflow with different inputs in parallel.
This endpoint is useful for batch processing scenarios where you need to run the same
workflow multiple times with different input parameters.
**Key Features:**
- Maximum 10 executions per request
- All executions share the same `bulk_id` for tracking
- Executions run in parallel
- Partial failures are allowed - some executions may succeed while others fail
- Optional webhook notification when all executions complete
**Bulk ID:**
All executions from a bulk trigger share a unique `bulk_id` that can be used to:
- Query all executions from a single bulk operation
- Track batch progress
- Correlate webhook notifications
**Webhook Behavior:**
When a `webhook_url` is provided, the notification payload includes the `bulk_id`
field to help you identify and correlate executions from the same bulk operation.
operationId: bulkTriggerWorkflow
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkTriggerWorkflowRequest'
responses:
'202':
description: Bulk workflow executions started
content:
application/json:
schema:
$ref: '#/components/schemas/BulkTriggerWorkflowResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/workflows/{workflowID}/versions/{versionID}/bulk-trigger:
parameters:
- $ref: '#/components/parameters/WorkflowID'
- name: versionID
in: path
required: true
description: Version identifier (e.g., "v1", "v2")
schema:
type: string
example: v1
post:
tags:
- Executions
summary: Bulk trigger workflow version
description: |
Start multiple executions of a specific workflow version with different inputs
in parallel. This is the versioned successor to the deprecated
`POST /{workflowID}/bulk-trigger` endpoint — the version to run is taken from
the URL path rather than the request body.
**Key Features:**
- Maximum 10 executions per request
- All executions share the same `bulk_id` for tracking
- Executions run in parallel
- Partial failures are allowed - some executions may succeed while others fail
- Optional webhook notification when all executions complete
operationId: bulkTriggerWorkflowVersion
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkTriggerWorkflowRequest'
responses:
'202':
description: Bulk workflow executions started
content:
application/json:
schema:
$ref: '#/components/schemas/BulkTriggerWorkflowResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/workflows/{workflowID}/executions:
parameters:
- $ref: '#/components/parameters/WorkflowID'
get:
tags:
- Executions
summary: List workflow executions
description: |
Retrieve a paginated list of executions for a specific workflow.
**Filtering by Bulk ID:**
When a `bulk_id` query parameter is provided, the endpoint returns only executions
from that specific bulk operation. This allows you to:
- Track progress of a batch of executions
- Retrieve all executions triggered via the bulk-trigger endpoint
- Correlate webhook notifications from the same bulk operation
**Usage Example:**
```bash
# 1. Trigger a bulk operation
POST /workflows/wf-123/bulk-trigger
{
"inputs": [
{"prompt": "sunset"},
{"prompt": "mountains"},
{"prompt": "ocean"}
]
}
# Returns: { "bulk_id": "550e8400-e29b-41d4-a716-446655440000", ... }
# 2. List all executions from that bulk operation
GET /workflows/wf-123/executions?bulk_id=550e8400-e29b-41d4-a716-446655440000
```
**Note:** When filtering by `bulk_id`, pagination still applies using the same
`offset` and `limit` parameters.
operationId: listWorkflowExecutions
parameters:
- name: bulk_id
in: query
description: |
**Optional**: Filter executions by bulk operation ID.
When provided, only returns executions from the specified bulk trigger operation.
The `bulk_id` is returned when you trigger a workflow via the bulk-trigger endpoint.
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
- name: offset
in: query
description: |
Pagination offset - number of items to skip.
The response includes a `offset` field pointing to the next page if more results exist.
schema:
type: integer
format: int32
default: 0
minimum: 0
example: 0
- name: limit
in: query
description: |
Maximum number of executions to return per page.
Default: 50
Maximum: 100
schema:
type: integer
format: int32
default: 50
minimum: 1
maximum: 100
example: 50
responses:
'200':
description: List of workflow executions
content:
application/json:
schema:
$ref: '#/components/schemas/ListExecutionsResponse'
examples:
normal:
summary: Normal workflow execution list
value:
executions:
- execution_id: "exec-1"
flow_id: "wf-123"
flow_name: "Text to Image Generator"
version_id: "v1"
status: "completed"
started_at: "2025-12-20T10:00:00Z"
ended_at: "2025-12-20T10:05:00Z"
created_at: "2025-12-20T10:00:00Z"
updated_at: "2025-12-20T10:05:00Z"
- execution_id: "exec-2"
flow_id: "wf-123"
flow_name: "Text to Image Generator"
version_id: "v1"
status: "running"
started_at: "2025-12-20T10:10:00Z"
created_at: "2025-12-20T10:10:00Z"
updated_at: "2025-12-20T10:10:00Z"
offset: 2
total_count: 142
bulk_filtered:
summary: Executions filtered by bulk_id
value:
executions:
- execution_id: "exec-1"
flow_id: "wf-123"
flow_name: "Batch Image Generator"
version_id: "v1"
status: "completed"
started_at: "2025-12-20T10:00:00Z"
ended_at: "2025-12-20T10:05:00Z"
created_at: "2025-12-20T10:00:00Z"
updated_at: "2025-12-20T10:05:00Z"
- execution_id: "exec-2"
flow_id: "wf-123"
flow_name: "Batch Image Generator"
version_id: "v1"
status: "completed"
started_at: "2025-12-20T10:00:01Z"
ended_at: "2025-12-20T10:05:15Z"
created_at: "2025-12-20T10:00:01Z"
updated_at: "2025-12-20T10:05:15Z"
- execution_id: "exec-3"
flow_id: "wf-123"
flow_name: "Batch Image Generator"
version_id: "v1"
status: "completed"
started_at: "2025-12-20T10:00:02Z"
ended_at: "2025-12-20T10:04:58Z"
created_at: "2025-12-20T10:00:02Z"
updated_at: "2025-12-20T10:04:58Z"
total_count: 3
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/executions/{executionID}:
parameters:
- $ref: '#/components/parameters/ExecutionID'
get:
tags:
- Executions
summary: Get execution details
description: Get the current status and output of a workflow execution
operationId: getExecution
responses:
'200':
description: Execution details
content:
application/json:
schema:
$ref: '#/components/schemas/ExecutionDetails'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/public/@{nickname}/workflows/{slug}/versions/{versionID}:
parameters:
- $ref: '#/components/parameters/Nickname'
- $ref: '#/components/parameters/Slug'
- $ref: '#/components/parameters/VersionID'
get:
tags:
- Public Workflows
summary: Get public workflow version
description: |
Retrieve a specific version of a public or unlisted workflow by organization nickname.
**No authentication required** for unlisted workflows.
Example:
```
GET /api/v1/public/@acme-corp/workflows/my-generator/versions/v1
```
operationId: getPublicWorkflowVersionByNickname
responses:
'200':
description: Workflow version details
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowVersionSummary'
'404':
$ref: '#/components/responses/NotFound'
/public/@{nickname}/workflows/{slug}/versions/{versionID}/trigger:
parameters:
- $ref: '#/components/parameters/Nickname'
- $ref: '#/components/parameters/Slug'
- $ref: '#/components/parameters/VersionID'
post:
tags:
- Public Workflows
summary: Trigger public workflow version
description: |
Trigger a public or unlisted workflow using the organization nickname, workflow slug, and version.
**Authentication required** - provide API key via `X-API-Key` header or `api_key` in request body.
Example:
```
POST /api/v1/public/@acme-corp/workflows/my-generator/versions/v1/trigger
Headers: X-API-Key: your-api-key
Body: { "inputs": { "prompt": "..." } }
```
Or with API key in body:
```
POST /api/v1/public/@acme-corp/workflows/my-generator/versions/v1/trigger
Body: { "api_key": "your-api-key", "inputs": { "prompt": "..." } }
```
operationId: triggerPublicWorkflowVersionByNickname
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TriggerWorkflowRequest'
responses:
'202':
description: Workflow execution started
content:
application/json:
schema:
$ref: '#/components/schemas/ExecutionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: API key for authentication
parameters:
WorkflowID:
name: workflowID
in: path
required: true
description: Unique workflow identifier
schema:
type: string
example: wf_abc123
ExecutionID:
name: executionID
in: path
required: true
description: Execution identifier
schema:
type: string
example: exec_xyz789
Nickname:
name: nickname
in: path
required: true
description: Organization nickname (without @ prefix)
schema:
type: string
example: acme-corp
Slug:
name: slug
in: path
required: true
description: Workflow slug
schema:
type: string
example: my-image-generator
VersionID:
name: versionID
in: path
required: true
description: Version identifier
schema:
type: string
example: v1
schemas:
CategoriesResponse:
type: object
required:
- categories
properties:
categories:
type: array
items:
$ref: '#/components/schemas/Category'
description: List of available workflow categories
example:
categories:
- slug: "image-generation"
label: "Image Generation"
description: "Workflows for generating images"
is_default: true
created_at: "2025-12-01T10:00:00Z"
updated_at: "2025-12-01T10:00:00Z"
- slug: "text-processing"
label: "Text Processing"
description: "Workflows for processing text"
is_default: true
created_at: "2025-12-01T10:00:00Z"
updated_at: "2025-12-01T10:00:00Z"
Category:
type: object
required:
- slug
- label
properties:
slug:
type: string
description: Unique category identifier (used in API requests)
example: "image-generation"
label:
type: string
description: Human-readable category name
example: "Image Generation"
description:
type: string
description: Category description
example: "Workflows for generating images"
is_default:
type: boolean
description: Whether this is a default system category
example: true
created_at:
type: string
format: date-time
description: RFC3339 timestamp when category was created
example: "2025-12-01T10:00:00Z"
updated_at:
type: string
format: date-time
description: RFC3339 timestamp when category was last updated
example: "2025-12-01T10:00:00Z"
CreateWorkflowRequest:
type: object
required:
- name
- description
- definition
properties:
name:
type: string
description: Human-readable workflow name
example: "Text to Image Generator"
description:
type: string
description: Detailed description of what the workflow does
example: "Generates images from text prompts using AI models"
categories:
type: array
items:
type: string
description: List of category slugs to organize the workflow
example: ["image-generation", "ai"]
locked:
type: boolean
description: Whether the workflow is locked from modifications
default: false
production:
type: boolean
description: Whether this is a production workflow
default: false
definition:
type: object
description: |
The workflow definition containing steps, input schema, and metadata.
This follows the workflow DSL format.
properties:
version:
type: string
description: Version identifier for this workflow
example: "v1"
steps:
type: array
description: Array of step definitions
items:
type: object
example:
- step_id: "step1"
type: "model"
model: "openai-chatgpt-5"
params:
system_prompt: "You are a helpful assistant"
user_prompt: "{{inputs.prompt}}"
fallback:
enabled: true
model: "anthropic-claude-4"
params:
system_prompt: "You are a helpful assistant"
user_prompt: "{{inputs.prompt}}"
input_schema:
type: object
description: JSON Schema for validating workflow inputs
example:
type: "object"
properties:
prompt:
type: "string"
description: "Text prompt for generation"
required: ["prompt"]
metadata:
type: object
description: Additional workflow metadata
example:
output_mapping:
result: "{{step1.output}}"
UpdateWorkflowRequest:
type: object
description: |
Update workflow metadata. All fields are optional - only provided fields will be updated.
Note: To update the workflow definition (steps), use the version endpoints instead.
properties:
name:
type: string
description: Human-readable workflow name
example: "Text to Image Generator v2"
description:
type: string
description: Detailed description of what the workflow does
example: "Enhanced image generation with multiple models"
categories:
type: array
items:
type: string
description: List of category slugs
example: ["image-generation", "ai", "production"]
locked:
type: boolean
description: Lock/unlock the workflow from modifications
production:
type: boolean
description: Mark as production workflow
UpsertVersionRequest:
type: object
required:
- version_id
- definition
properties:
version_id:
type: string
description: Version identifier (e.g., "v1", "v2", "v1.1")
example: "v2"
definition:
type: object
description: |
The complete workflow definition for this version.
This follows the workflow DSL format and must include all steps.
properties:
version:
type: string
description: Version identifier (should match version_id)
example: "v2"
steps:
type: array
description: Array of step definitions
items:
type: object
example:
- step_id: "generate_text"
type: "model"
model: "openai-chatgpt-5"
params:
system_prompt: "You are a helpful assistant"
user_prompt: "{{inputs.prompt}}"
- step_id: "generate_image"
type: "model"
model: "flux-dev"
params:
prompt: "{{generate_text.output}}"
num_images: 2
fallback:
enabled: true
model: "flux-1-1-pro"
params:
prompt: "{{generate_text.output}}"
guidance_scale: 7.5
input_schema:
type: object
description: JSON Schema for validating workflow inputs
metadata:
type: object
description: Additional workflow metadata including output mappings
locked:
type: boolean
description: Whether to lock this version from further modifications
default: false
production:
type: boolean
description: Whether this is a production version
default: false
allowed_to_share:
type: boolean
description: |
Toggle unlisted sharing for this version.
- `true` → Makes version "unlisted" (accessible via link, hidden from public listings)
- `false` → Makes version "private" (organization only)
- No effect on public versions
- New versions default to private when omitted
default: false
WorkflowDetail:
type: object
description: Complete workflow information including all versions
required:
- workflow_id
- name
- description
properties:
workflow_id:
type: string
format: uuid
description: Unique workflow identifier
example: "50741f40-8621-4d46-8a91-dff4d873be98"
slug:
type: string
description: URL-friendly workflow identifier
example: "text-to-image-generator"
name:
type: string
description: Human-readable workflow name
example: "Text to Image Generator"
description:
type: string
description: Workflow description
example: "Generates images from text prompts"
categories:
type: array
items:
type: string
description: Category slugs
example: ["image-generation", "ai"]
locked:
type: boolean
description: Whether workflow is locked
example: false
production:
type: boolean
description: Whether this is a production workflow
example: false
latest_version_id:
type: string
description: Most recently updated version ID
example: "v2"
status:
type: string
enum: [active, archived, deleted]
description: Workflow lifecycle status
example: active
trigger_count:
type: integer
description: Total number of times this workflow has been triggered
example: 42
created_at:
type: string
format: date-time
description: RFC3339 timestamp when workflow was created
example: "2025-12-01T10:00:00Z"
updated_at:
type: string
format: date-time
description: RFC3339 timestamp when workflow was last updated
example: "2025-12-07T15:30:00Z"
versions:
type: array
description: List of all versions for this workflow
items:
$ref: '#/components/schemas/WorkflowVersionSummary'
WorkflowVersionSummary:
type: object
description: Summary information about a workflow version
required:
- version_id
- slug
properties:
version_id:
type: string
description: Version identifier
example: "v1"
slug:
type: string
description: Workflow slug (inherited from parent workflow)
example: "text-to-image-generator"
locked:
type: boolean
description: Whether this version is locked from modifications
example: false
production:
type: boolean
description: Whether this is a production version
example: true
allowed_to_share:
type: boolean
description: True if version is unlisted (accessible via direct link but hidden from public listings).
example: false
trigger_count:
type: integer
description: Number of times this specific version has been triggered
example: 15
created_at:
type: string
format: date-time
description: RFC3339 timestamp when version was created
example: "2025-12-01T10:00:00Z"
updated_at:
type: string
format: date-time
description: RFC3339 timestamp when version was last updated
example: "2025-12-05T14:20:00Z"
status:
type: string
enum: [active, archived, deleted]
description: Version lifecycle status
example: active
definition:
type: object
description: |
The complete workflow definition (only included in detail responses).
Contains steps, input schema, and metadata.
TriggerWorkflowRequest:
type: object
properties:
version_id:
type: string
description: |
**Optional**: Specific version to trigger.
If not provided, triggers the latest version of the workflow.
This allows you to execute specific versions for testing or comparison.
example: "v1"
inputs:
type: object
description: Input parameters defined in the workflow definition for the workflow
example:
text: "tell me a story"
webhook_url:
type: string
format: uri
description: |
**Optional webhook URL for execution completion notifications.**
When provided, the engine will POST an `ExecutionDetails` payload to this URL
when the workflow finishes (either successfully or with an error).
See the **Webhooks** section for detailed information about webhook behavior and payload structure.
example: https://your-api.com/webhooks/workflow-completed
BulkTriggerWorkflowRequest:
type: object
required:
- inputs
properties:
version_id:
type: string
description: |
**Optional**: Specific version to trigger for all executions.
If not provided, triggers the latest version of the workflow.
example: "v1"
inputs:
type: array
minItems: 1
maxItems: 10
description: |
Array of input parameter objects. Each item in the array will result in a separate workflow execution.
**Constraints:**
- Minimum 1 input required
- Maximum 10 inputs per request
All inputs must conform to the workflow's input schema.
items:
type: object
additionalProperties: true
example:
- prompt: "Generate image of a sunset"
style: "photorealistic"
- prompt: "Generate image of mountains"
style: "artistic"
- prompt: "Generate image of ocean"
style: "minimalist"
webhook_url:
type: string
format: uri
description: |
**Optional webhook URL for execution completion notifications.**
When provided, webhook notifications for all executions in this bulk operation
will include a `bulk_id` field to help you correlate them.
Each execution sends its own webhook notification when it completes.
example: https://your-api.com/webhooks/workflow-completed
BulkTriggerWorkflowResponse:
type: object
required:
- bulk_id
- executions
properties:
bulk_id:
type: string
format: uuid
description: |
Unique identifier for this bulk operation. All executions from this bulk trigger
share this ID, which can be used to query and track them together.
example: "550e8400-e29b-41d4-a716-446655440000"
executions:
type: array
description: |
Array of execution responses, one per input in the request.
The order matches the order of inputs in the request.
**Partial Failures:**
If some inputs fail validation, those entries will have `status: "failed"`
with an error message, while successful triggers will have `status: "queued"`.
items:
$ref: '#/components/schemas/ExecutionResponse'
example:
- execution_id: "exec-1"
status: "queued"
started_at: "2025-12-20T10:00:00Z"
- execution_id: "exec-2"
status: "queued"
started_at: "2025-12-20T10:00:01Z"
- status: "failed"
message: "invalid input: missing required field 'prompt'"
ExecutionResponse:
type: object
description: Response from triggering a workflow execution
properties:
execution_id:
type: string
description: Unique execution identifier (only present for successful triggers)
example: exec_xyz789
status:
type: string
enum: [queued, failed]
description: |
Execution status immediately after triggering.
- `queued`: Workflow execution has been queued and will start shortly
- `failed`: Trigger failed due to validation or system error
example: queued
started_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution was queued (only present for successful triggers)
message:
type: string
description: Error message (only present when status is "failed")
example: "invalid input: missing required field"
example:
execution_id: "e2dba2bb-bc1d-4651-b6bf-fbbbebdee104"
status: "queued"
started_at: "2025-12-03T10:21:09Z"
ListExecutionsResponse:
type: object
description: Paginated list of workflow executions
required:
- executions
- total_count
properties:
executions:
type: array
description: Array of execution summaries
items:
$ref: '#/components/schemas/ExecutionSummary'
offset:
type: integer
format: int32
description: |
Offset for the next page of results.
If null, there are no more results to fetch.
example: 50
total_count:
type: integer
format: int32
description: Total number of executions matching the query
example: 142
example:
executions:
- execution_id: "exec-1"
flow_id: "wf-123"
flow_name: "Text to Image Generator"
version_id: "v1"
status: "completed"
started_at: "2025-12-20T10:00:00Z"
ended_at: "2025-12-20T10:05:00Z"
created_at: "2025-12-20T10:00:00Z"
updated_at: "2025-12-20T10:05:00Z"
- execution_id: "exec-2"
flow_id: "wf-123"
flow_name: "Text to Image Generator"
version_id: "v1"
status: "running"
started_at: "2025-12-20T10:10:00Z"
created_at: "2025-12-20T10:10:00Z"
updated_at: "2025-12-20T10:10:00Z"
offset: 2
total_count: 142
ExecutionSummary:
type: object
description: |
Summary information about a workflow execution, used in list responses.
Contains less detail than `ExecutionDetails` to optimize list queries.
required:
- execution_id
- flow_id
- flow_name
- version_id
- status
- created_at
properties:
execution_id:
type: string
description: Unique execution identifier
example: "exec-1"
flow_id:
type: string
description: Workflow identifier (UUID)
example: "wf-123"
flow_name:
type: string
description: Human-readable workflow name
example: "Text to Image Generator"
version_id:
type: string
description: Version identifier for this execution
example: "v1"
api_key:
type: string
description: User/API key identifier that triggered this execution
example: "user-456"
status:
type: string
enum: [running, completed, failed, cancelled]
description: Current execution status
example: "completed"
started_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution started (omitted if not started yet)
example: "2025-12-20T10:00:00Z"
ended_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution completed (omitted for running executions)
example: "2025-12-20T10:05:00Z"
created_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution was created
example: "2025-12-20T10:00:00Z"
updated_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution was last updated
example: "2025-12-20T10:05:00Z"
deleted_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution was soft-deleted (if applicable)
example: null
inputs:
type: object
description: Input parameters provided when triggering the workflow
additionalProperties: true
example:
prompt: "Generate an image of a sunset"
step_results:
description: |
Brief summary of step execution results.
Structure varies - may be an object with step IDs as keys, or an array.
oneOf:
- type: object
- type: array
items: {}
output:
type: string
description: |
Simple string output from the workflow (if available).
For complex outputs, use `output_json` instead.
example: "https://storage.googleapis.com/uploads/image.png"
output_json:
type: object
description: |
Structured JSON output from the workflow (if available).
Contains the full workflow output when output mapping is configured.
additionalProperties: true
example:
image_url: "https://storage.googleapis.com/uploads/image.png"
generation_time: 2.45
cost:
description: |
Cost information for this execution (if available).
Structure varies by provider and workflow configuration.
oneOf:
- type: object
- type: number
ExecutionDetails:
type: object
description: |
Execution details returned by both `GET /executions/{id}` and webhook notifications.
### Webhook Notifications
When you provide a `webhook_url` when triggering a workflow, this same structure
will be POSTed to your webhook URL when the execution completes.
required:
- execution_id
- workflow_id
- status
properties:
execution_id:
type: string
description: Unique execution identifier (UUID format)
example: "69ae8c7b-7500-4a45-b7c0-348b8cc2665b"
workflow_id:
type: string
description: Workflow identifier (UUID format)
example: "50741f40-8621-4d46-8a91-dff4d873be98"
bulk_id:
type: string
format: uuid
description: |
Bulk operation identifier (only present for executions triggered via bulk-trigger endpoint).
All executions from the same bulk operation share this ID, allowing you to:
- Query all executions from a bulk operation together
- Track batch progress
- Correlate webhook notifications from related executions
example: "550e8400-e29b-41d4-a716-446655440000"
status:
type: string
enum: [running, completed, failed, cancelled]
description: |
Current execution status:
- `running` - Workflow is currently executing
- `completed` - Workflow finished successfully
- `failed` - Workflow encountered an error
- `cancelled` - Workflow was cancelled by user
example: completed
started_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution started
example: "2025-12-04T11:48:10Z"
completed_at:
type: string
format: date-time
description: RFC3339 timestamp when the execution completed (omitted for running executions)
example: "2025-12-04T11:50:53Z"
inputs:
type: object
description: Input parameters provided when triggering the workflow
additionalProperties: true
example:
story: "tell an epic story of a rat graduating from law"
step_outputs:
type: object
description: |
Complete outputs from all workflow steps. Each key is a step ID (e.g., "step1", "step2"),
and the value is a `StepOutput` object containing detailed information about that step's execution.
additionalProperties:
$ref: '#/components/schemas/StepOutput'
example:
step1:
step_id: "step1"
status: "completed"
started_at: "2025-12-04T11:48:10Z"
completed_at: "2025-12-04T11:48:39Z"
output: "Once upon a time..."
primary: "Once upon a time..."
metadata:
model: "openai-chatgpt-5"
version: "0.0.1"
params:
system_prompt: "You are a helpful assistant"
user_prompt: "tell an epic story of a rat graduating from law"
max_output_tokens: 512
step2:
step_id: "step2"
status: "completed"
started_at: "2025-12-04T11:48:39Z"
completed_at: "2025-12-04T11:50:53Z"
output:
- "https://storage.googleapis.com/uploads/image1.png"
- "https://storage.googleapis.com/uploads/image2.png"
primary: "https://storage.googleapis.com/uploads/image1.png"
metadata:
model: "nano-banana-pro"
version: "0.0.1"
params:
prompt: "Generate images based on the story"
num_images: 2
aspect_ratio: "16:9"
resolution: "1K"
output_format: "png"
output:
description: |
Output from the last completed step in the workflow.
This provides quick access to the final result without navigating step_outputs.
**Important**: This field is only populated when the workflow status is `completed`.
- For `running` workflows: null (even if some steps have completed)
- For `failed` workflows: null
- For `cancelled` workflows: null
- For `completed` workflows: contains output from the chronologically last step
The last step is determined by the latest `completed_at` timestamp.
The value is extracted from the step's `output` field, or `primary` field as fallback.
The type varies based on the workflow's final step:
- Text generation steps return a string
- Image generation steps return an array of URLs
- Structured data steps return an object
oneOf:
- type: string
- type: array
items: {}
- type: object
- type: 'null'
example:
- "https://storage.googleapis.com/uploads/image1.png"
- "https://storage.googleapis.com/uploads/image2.png"
error:
type: string
description: High-level error message (only present if status is "failed")
example: "ExecutionFailed"
error_cause:
type: string
description: Detailed error cause with context (only present if status is "failed")
example: "Step 'generate_image' failed: Model timeout after 30s"
StepOutput:
type: object
description: |
Detailed information about a single step's execution within a workflow.
Each step in the workflow produces one of these objects.
required:
- step_id
- status
properties:
step_id:
type: string
description: Unique identifier for this step within the workflow
example: "step1"
status:
type: string
enum: [queued, running, completed, failed, cancelled]
description: |
Current status of this step:
- `queued` - Step is waiting to execute
- `running` - Step is currently executing
- `completed` - Step finished successfully
- `failed` - Step encountered an error
- `cancelled` - Step was skipped due to an earlier failure in the workflow
example: "completed"
started_at:
type: string
format: date-time
description: RFC3339 timestamp when the step started executing (omitted for queued steps)
example: "2025-12-04T11:48:10Z"
completed_at:
type: string
format: date-time
description: RFC3339 timestamp when the step finished (only present if completed or failed)
example: "2025-12-04T11:48:39Z"
output:
description: |
The step's output data. The structure depends on the step type:
- Text generation: string
- Image generation: array of URLs
- Structured data: object
- Multi-output steps: array or object with multiple values
oneOf:
- type: string
- type: array
items: {}
- type: object
- type: number
- type: boolean
example: "Once upon a time in the city of Ratropolis..."
primary:
description: |
The primary output value from this step. For steps that return multiple values
(e.g., generating multiple images), this field contains the first/main result
for quick access.
oneOf:
- type: string
- type: number
- type: boolean
- type: object
example: "https://storage.googleapis.com/uploads/image1.png"
input:
type: object
description: |
The complete resolved input payload sent to this step handler.
This includes the full step configuration with all template values resolved:
- `step_id` - The step identifier
- `type` or `model` - The step type or model name
- `version` - API version (if applicable)
- `params` or `inputs` - All parameters with values from previous steps resolved
Values like `{{step1.output}}` are replaced with actual data from prior steps.
additionalProperties: true
example:
step_id: "generate_image"
model: "flux-dev"
version: "1.0.0"
params:
prompt: "Generate an image of a rat graduating from law school"
num_images: 2
metadata:
type: object
description: |
Step configuration and runtime information. Fields vary by step type:
**Model steps** include:
- `model` - The AI model identifier (e.g., "openai-chatgpt-5")
- `version` - API version for the step handler (e.g., "0.0.1")
- `params` - All parameters sent to the model
- `prediction_id` - External prediction ID (when completed)
- `processed_at` - Processing timestamp (when completed)
- `fallback_used` - Present and `true` when the primary attempt failed and the fallback configuration was used
- `primary_error` - Human-readable error message from the primary attempt when fallback was used
**HTTP steps** include:
- `type` - Always "http"
- `method` - HTTP method (e.g., "GET", "POST")
- `url` - Request URL
- `params` - Request parameters
- `elapsed_seconds` - Request duration (when completed)
**Python steps** include:
- `type` - Always "python"
- `params` - Input parameters
- `execution_time` - Execution duration in seconds (when completed)
- `processed_at` - Processing timestamp (when completed)
properties:
model:
type: string
description: The AI model used (model steps only)
example: "openai-chatgpt-5"
version:
type: string
description: API version (model steps only)
example: "0.0.1"
type:
type: string
description: Step type (http or python steps)
enum: [http, python]
example: "http"
method:
type: string
description: HTTP method (http steps only)
example: "POST"
url:
type: string
description: Request URL (http steps only)
example: "https://api.example.com/endpoint"
params:
type: object
description: Complete parameters sent to the step, including resolved values
additionalProperties: true
example:
system_prompt: "You are a helpful assistant"
user_prompt: "tell an epic story of a rat graduating from law"
max_output_tokens: 512
prediction_id:
type: string
description: External prediction ID (model steps, when completed)
example: "6yxkzw4th9rme0ct1re8q42xer"
processed_at:
type: string
format: date-time
description: Processing timestamp (when available)
example: "2025-12-04T11:48:39Z"
fallback_used:
type: boolean
description: |
Indicates that the step completed successfully using a configured fallback after the primary attempt failed (model steps only).
example: true
primary_error:
type: string
description: |
Original error message from the primary attempt when a fallback configuration was used (model steps only).
example: "primary model failed due to timeout"
elapsed_seconds:
type: number
description: Execution duration in seconds (when completed)
example: 2.45
execution_time:
type: number
description: Python execution time in seconds (python steps, when completed)
example: 0.123
error:
type: string
description: Error message if the step failed
example: "ModelTimeout"
error_cause:
type: string
description: Detailed error information if the step failed
example: "Model request timed out after 30 seconds"
FallbackConfig:
type: object
description: |
Fallback configuration for model steps. When configured, the workflow engine will
automatically retry with the fallback model if the primary model invocation fails.
properties:
enabled:
type: boolean
default: true
description: Enable or disable fallback for this step
example: true
model:
type: string
description: |
Fallback AI model identifier to use if the primary model fails.
Should be compatible with the expected output format.
example: "flux-1-1-pro"
version:
type: string
description: |
Fallback model version. When omitted, defaults to the primary model's version.
example: "1.0.0"
params:
type: object
description: |
Fallback-specific model parameters. Supports template variables like `{{inputs.prompt}}`
and `{{step_id.output}}` for referencing workflow inputs and previous step outputs.
additionalProperties: true
example:
prompt: "{{inputs.prompt}}"
guidance_scale: 7.5
example:
enabled: true
model: "flux-1-1-pro"
params:
prompt: "{{inputs.prompt}}"
guidance_scale: 7.5
Error:
type: object
required:
- error
properties:
error:
type: string
description: Error message
responses:
BadRequest:
description: Bad request - Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized - Invalid or missing API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: Forbidden - Operation not allowed (e.g., workflow is locked)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Not found - Resource does not exist
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Models API YAML |
Workflows API YAML |
llms.txt