Workflows
Create, import, deploy, validate, review, and execute workflows via the API.
Endpoints under /api/v1/workflows. Send Authorization: Bearer. Missing/invalid token → 401. Workflow in another workspace → 403 { error: "API key cannot access this workflow" }. Missing workflow → 404.
Execute additionally requires a workspace-scoped key (403 "A workspace API key is required."), or a
product gateway key for a workflow on its allowlist when the deployment enables end users (see
End users).
There is no v1 collaboration API (canvas CRDT is tRPC only). Execute-step and pin-data are session /api/workflows/{id}/... only.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/workflows | List non-trashed workflows in the key's workspace |
| POST | /api/v1/workflows | Create, import, duplicate, or placeholder |
| GET | /api/v1/workflows/{id} | Get workflow; ?format=portable for export JSON |
| PATCH | /api/v1/workflows/{id} | Update, import-replace, trash, or deploy-via-status |
| DELETE | /api/v1/workflows/{id} | Delete |
| POST | /api/v1/workflows/{id}/deploy | Deploy + provision webhook |
| POST | /api/v1/workflows/{id}/execute | Execute (workspace key) |
| GET | /api/v1/workflows/{id}/status | Run status (optional runId) |
| GET/POST | /api/v1/workflows/{id}/validate | Validation + deployment readiness |
| GET/POST | /api/v1/workflows/{id}/review | Git review status / create proposal |
| GET | /api/v1/workflows/{id}/versions | List versions |
| POST | /api/v1/workflows/{id}/versions/{version}/restore | Restore version ≥ 1 |
| GET/POST | /api/v1/workflows/{id}/sync-from-repo | Preview / import merged artifacts |
| POST | /api/v1/workflows/{id}/credentials/test | Test mapped credentials |
| POST | /api/v1/workflows/{id}/credentials/bootstrap-from-env | Create credentials from server env |
| POST | /api/v1/workflows/import-preview | Preview import (no write) |
| POST | /api/v1/workflows/validate-artifact | Validate git artifact files |
| GET/POST | /api/v1/workflows/mcp/{workspaceId}/{serverSlug} | Workflow MCP server |
Create, import, or duplicate
POST /api/v1/workflows branches on the JSON body (all fields optional):
| Field | Type | Effect |
|---|---|---|
name | string | Name for the new workflow |
templateKey | string | Create from a built-in template |
sourceWorkflowId | string | Duplicate (same workspace rules as get) |
importJson | string | Import one Confluye or n8n JSON |
importBundleJson | string | Import a multi-workflow bundle (upsert by n8n id) |
subWorkflowPlaceholder | object | { name, workflowId?, sourceNodeId?, sourceNodeLabel? } |
Empty body → blank workflow. 201. Single create: { workflow, links, ...syncedTriggers }. Bundle: { bundle, workflows[] } with importAction, importReadiness, bundleSubWorkflowStatus, links. links point at version, validate, execute, status, and portable export URLs.
The signed-in app can also create a linked setup chat when starting a built-in template. Its initial message and fixed explanation copy use the app's interface-language cookie. The bearer API above creates the workflow without that linked chat; it does not seed a setup message.
POST /api/v1/workflows/import-preview — importJson or importBundleJson required (400 otherwise). Does not persist. See Importing n8n.
Update, get, and delete
GET → { workflow, links } or portable { name, description, nodes, edges }.
In full-projection responses, workflow.collaborationSessionId identifies the source session when the graph includes an uncheckpointed collaboration draft. Use the versions endpoint to read saved versions. Collaboration mutations still require authenticated editor access through tRPC.
PATCH accepts name, description, status (draft | deployed | disabled), nodes[], edges[], importJson, trashed. Invalid status → 400. status: "deployed" runs deploy and returns the deploy failure payload on 400. Import-replace forces draft and returns importReadiness. trashed: true/false uses the trash path (in-memory trash on Prisma — see Recently deleted). DELETE → { deleted: true }.
PATCH does not accept versionMode / collaborationSessionId (those are tRPC workflows.update only).
Each edge may include an ordered zipTies array of { id, x, y } visual guides. Use the same guide ID
and coordinates on multiple edges to bundle their cables, and update every edge carrying that ID when
moving it. Conflicting coordinates for a shared guide ID are rejected before saving or importing.
Remove the matching entry from each edge to release the bundle. Coordinates must be finite
numbers; IDs must be nonempty and unique within each edge. Preserve the rest of the graph when replacing
edges[]. These guides affect canvas routing only, and are retained in native JSON exports and Git artifacts.
Execute and status
POST /api/v1/workflows/{id}/execute — input?, startNodeId?, dryRun?, target? (active | candidate), executionTargetId?, expectedVersionId?, confirm?. Public API calls target active by default. Idempotency-Key supported. 202 { run, execution, queued: true, statusUrl, cancelUrl } when BullMQ accepted the job; 201 when inline (no Redis, E2E mode, or dry run). execution and run.executionEvidence identify requestedTarget, versionId, resourceMode (simulated | workspace-live), and reviewIdentity.
endUser? ({ externalId }), message? and mode? run the workflow for an end user of your product. They are
accepted only from a product gateway key; any other key that sends any of them gets 400. A product gateway key
must send endUser.externalId. mode is "conversation" (the default when omitted) or "event" (any other value
answers 400). A conversational run also needs a non-blank message of at most 32,000 characters, and its message
and the reply form the turn recorded in the end user's memory. mode: "event" runs the workflow with that end user's
memory for something that happened in your product, records no conversation turn and sends no end_user.reply
callback, so message is optional: an event run can omit it, and a message it does send (at most 32,000
characters) is used to rank which remembered facts are most relevant. The idempotency fingerprint covers endUser,
message and mode, so the same key with another message or mode answers 409 instead of replaying (the whole
fingerprint is listed below). End user runs execute the active version, are always queued (202 with statusUrl/cancelUrl under
/api/v1/end-users/runs/{id}, or 503 without a queue), and return the safe run summary and outcome fields without inputs, steps or logs. See
End users for the full contract.
productContext? (an object, at most 2048 bytes of JSON) is your product's context for the run, sent beside
input and never inside it. It is accepted only from an end_user_gateway key with the run permission; a
workspace key or another caller that sends it gets 400 with
code: "product_context_requires_product_credential". This is a behavior change: workspace keys can no longer
assert product context. Confluye validates its
reserved fields delegationRef, usageTag, subjectExternalIds and selectedCustomerExternalId (a malformed value
answers 400 with a product_context_* code; the selected customer must be one of subjectExternalIds) and keeps the
rest opaque. The run stores it apart from input: it never reaches a
model, the run object, logs or exports, and it is only signed into requests to the workspace's
product connections. A run with productContext cannot be a dry run
(400) and requires the durable workflow runtime. The idempotency fingerprint
covers it, so the same key with another productContext answers 409. Find the runs a delegation started with
GET /api/v1/runs?delegationRef=. A workspace API key sees every run
of the workspace with that reference; a product gateway key needs the run permission and sees only end-user runs of
the workflows it may run that the same API key started. Another gateway key cannot read those runs, even when its
allowlist overlaps.
callbackUrl? asks Confluye to call your product back, with a signed POST, when the run ends (run.completed)
and, for a conversational end user run, with its reply (end_user.reply). It is accepted from workspace and product
gateway keys, and its value must be exactly a callbackUrl registered on one of the workspace's
product connections; any other value answers 400 with
code: "callback_url_not_registered" and creates no run. The registration is checked only when the request starts a
new execution, after the idempotency check: repeating a completed request with the same Idempotency-Key returns the
original receipt even if the callback URL has been removed since, so a lost response can always be recovered. A new key
is checked against the current registrations. A callback URL is unique in the workspace (registering one
that another connection already holds answers 409), so the value names exactly one connection, and that connection's
signing secret signs the callback. The run keeps that URL and is called back only while the
connection still registers it. The callback is at least once and idempotent by event ID, and carries the run's
delegationRef. A run with callbackUrl cannot be a dry run (400) and requires the durable workflow runtime. The
idempotency fingerprint covers it, so the same key with another callbackUrl answers 409. The callback never
replaces polling: if it does not arrive, read the run, with GET /api/v1/runs/{id} for a workspace key or
GET /api/v1/end-users/runs/{id} (with X-End-User-Id) for a product gateway key.
Idempotency-Key is supported. Its fingerprint covers the whole execution request: input, startNodeId, target, dryRun, expectedVersionId, executionTargetId, confirm, endUser, message, mode, productContext, callbackUrl and the API key that sent it. Repeating a key with a change to any of them answers 409 (code: "idempotency_replay_mismatch") instead of replaying the earlier run.
Repeating a completed request with the same key, principal and complete execution request (every field of the fingerprint above) returns the original execution receipt, even if the destination has since stopped, its candidate changed or its callbackUrl was unregistered. It does not execute again. Use a new key for a new execution; current version, destination and approval checks then apply. Agent execute, test and step tools follow the same replay rule.
executionTargetId selects a named preview or production destination. Its active version must have a
current approval and enabled deployment for live execution. Simulations use that destination's candidate
and retain its identity in execution.destination; live runs include run.executionTarget. Reusing a key
for a different destination, expected version or API principal returns a conflict. A foreign or unavailable
destination does not select production instead. The typed workflows.execute tool accepts the same ID.
expectedVersionId pins the version a call may run. When the target now resolves to another version, nothing
starts (no run, no end user, no audit entry) and the call answers 400 with { "error": "Workflow active version changed: expected …, resolved ….", "code": "workflow_version_changed" } (it names candidate for a candidate call). The code is
stable: read the current version and send a new request with it; do not parse the message. A rejected
productContext answers 400 with { "error": "…", "code": "product_context_…" } (for example
product_context_invalid, product_context_too_large, product_context_requires_product_credential or
product_context_selected_customer_invalid); branch on the code, not the message. A 400 for any other validation
failure that has no code keeps its { "error" } body only.
Candidate calls default to dry run. Live candidate execution requires dryRun: false, confirm: true,
and the matching expectedVersionId. It uses real workspace resources; it is not an isolated runtime.
Testing candidate v2 never changes active v1. Only deploy promotes a version.
GET /api/v1/workflows/{id}/status?runId= → { workflow, projection, run, status, queued, active, output, error, steps[], logs (last 20), links, pollAfterMs }. projection is the discriminator { kind: "workflow-status", version: 1, redacted }; keys without workspace.secret.read receive redacted: true and the safe run/workflow DTOs only (never inputs, outputs, errors, logs, node configuration, or credentials). active is true for queued | running | waiting. Unknown run → 404. Omit runId → { workflow, runs, statuses } (limit 20).
File inputs
input.fileInputs is interpreted as a selection map only when the chosen Start node defines File inputs. Otherwise it remains ordinary application input.
For a Start node with File input report, send input: { "fileInputs": { "report": ["file-id"] } }.
Every ID must belong to the execution workspace and have status: "ready"; required fields, multiple
selection, accepted extensions and file limits are validated before execution. The server builds one
item with json and binary. The 10-file/100 MiB total limit covers the complete input, including
reused descriptors, retained upstream outputs and new selections together, before live or simulated admission.
Admission uses stored file sizes and checks descriptor size/checksum against the stored file. Conflicting
metadata for aliases of the same file is rejected. Existing normalized items keep their JSON and binary properties.
New Start selections are merged into the first item; a selected property that collides with an existing
binary property is rejected instead of silently replacing it.
Selections are execution input and are not persisted in node configuration.
The same input.fileInputs contract applies to workflows.execute over workspace and organization MCP.
File test listeners
POST /api/v1/workflows/{id}/file-tests accepts nodeId, executionMode: "step" | "workflow" and
optional executionTargetId. An authorized execution principal receives a temporary URL, listener ID
and expiry. GET .../file-tests?listenerId={id} reads its state; DELETE cancels it. Only its owner
with current execution permission can manage it. It captures one candidate submission in 120 seconds,
then scans and simulates the selected step or workflow. It does not deploy a version.
The matching tRPC procedures are fileTestStart, fileTestStatus and fileTestCancel. MCP exposes
workflows.file-test-start, workflows.file-test-status and workflows.file-test-cancel. MCP returns
metadata and execution IDs without upload tokens or private entry links; obtain upload URLs through
the editor or authenticated HTTP API. Organization calls must explicitly select an authorized workspace.
Deploy
Production and named previews
GET /api/v1/workflows/{id}/targets lists destination identities, candidate/active pointers, revisions and enabled state. Each destination also has sources: its RSS feeds, mail routes and Jenkins sources, and any overlaps with another destination. A Jenkins source reports its jobs, result filter, interval, lastPolledAt, paused, error and a jobStatuses entry per job with baselineBuildNumber, lastSeenBuildNumber, omittedBuildCount, paused and error. It does not return connection secrets, the Jenkins server address or draft graphs. Add ?includeHistory=true to include the latest 30 production activations in history, with activationId, targetId, versionId, numbered version, displayLabel, createdAt and canPrepareRollback. This flag identifies snapshots that can enter rollback preparation; current AIMS, connection and Git checks still decide whether publication is allowed.
POST /api/v1/workflows/{id}/targets accepts { "confirm": true, "change": { "action": "…" } } and requires an Idempotency-Key header (or idempotencyKey body field). The authenticated key needs write and execute authority. The key is bound to the authenticated principal, workflow and exact change. Replaying it returns the same receipt; a different change or principal returns 409.
| Action | Change fields |
|---|---|
prepare-production | No additional fields |
create-preview | versionId, name |
rename-preview | targetId, expectedRevision, name |
rename-version | versionId, displayLabel (empty removes the label) |
save-candidate | targetId, expectedRevision, name, nodes, edges, optional description |
save-connections | targetId, expectedRevision, bindings alias-to-credential-ID map; optional exact child dependencies and allowProductionReactivation |
restore-candidate | targetId, expectedRevision, versionId |
request-git-review | targetId, expectedRevision |
prepare-promotion | sourceTargetId, sourceActivationId, productionTargetId, production expectedRevision, optional stopAfter (default true) |
prepare-rollback | Production targetId, expectedRevision, historical activationId |
publish | targetId, expectedRevision, versionId, UUID requestId; optional prepared source, restoreActivationId or resumeActivationId |
stop | targetId, expectedRevision |
configure-source | The source destination's expectedRevision; source: an RSS source (kind: "rss", targetId, feedUrl, optional intervalSeconds) or a Jenkins source (see below) |
A Jenkins source has kind: "jenkins", targetId, the Jenkins trigger's nodeId in the destination's saved version, a credentialId, 1 to 50 jobs, optional results (omitted means every result) and optional intervalSeconds (60 to 86400, default 60). It is configured and polled as the key's user, so the credential must be one that user may use. It is refused when the workflow would start a job that the source watches on the same Jenkins server. An RSS source (and a mail route) needs a Start or plain Webhook trigger in the destination's saved version and is otherwise refused with event_source_trigger_not_found, because Jenkins, Sentry, app and schedule triggers start only from their own source. Mail and Sentry sources return a one-time secret, so you configure them in Versions & previews. A destination whose version has a Jenkins trigger cannot publish until the trigger has a source. When the destination's saved version changed after the revision you sent, the source is not stored and the request fails with 409 and workflow_target_revision_conflict; read the destination again and retry with its current revision.
Preparation keeps the current deployment running. A rollback preparation also preserves the editor candidate and returns preparedPublicationVersionId; use that historical version when requesting its approval and publication. Publication verifies the destination's current AIMS authority, Git evidence, connections and dependencies. API calls cannot grant approval. A production rollback can reuse only an approval explicitly permitting reactivation of that snapshot; otherwise prepare it and complete a new decision in Approvals.
For prepare-production and create-preview, the result also includes preparation:
approvalGranted: false, publicationPerformed: false, a connections list with each required
key, name, type and configured flag, nextAction, and an explanatory message.
If connections are missing, call save-connections before requesting approval. These preparation
receipts contain no credential IDs or secret values and do not imply that the candidate is published.
The receipt describes the revision prepared by that request. Retrying with the same idempotency key
returns that original receipt even if the destination has changed; read the destination again for its
current state. A lost response does not create another preview when retried with the same key.
Missing connections are reported with workflow_target_connections_required; invalid or inaccessible
connections and missing or unavailable child activations have separate workflow_target_* codes and
corrective messages. MCP errors include retryable and the next action. An occupied AI credential
lease returns local_ai_cli_credentials_busy with retryable: true instead of waiting behind the
running operation during publication readiness. Retry after that operation finishes.
Blocked publication checks also include code, retryable, and nextAction when the cause is a
known setup or busy-account error. Successful checks keep their usual fields.
POST /api/v1/workflows/{id}/targets/preview-publication accepts the publish fields without action and requires execute authority. It returns { ready, checks, warnings, connections, dependencies }: checks report blockers, warnings identify overlapping event sources, connections contain credential references (never secret values), and dependencies identify pinned child deployments. It is a read-only readiness check, not permission to skip revalidation on publish.
The equivalent tools are workflows.targets, workflows.preview-target-publication and workflows.update-target (with the same change object). MCP publication additionally requires its existing AIMS service-token and deployment-role checks. workflows.test and workflows.execute-step accept executionTargetId; step execution rejects a source run from another destination. Live steps run the destination's approved active version.
Using a deployed destination
In the destination panel, Use deployment opens the Use as API and Use as MCP options. Opening these options does not publish a workflow or run an execution; AIMS approval and deployment remain separate actions.
For an on destination with a target-authorized active version, the API option shows a copyable
server-side request. It fixes executionTargetId, expectedVersionId, target: "active", and
dryRun: false. Supply a workspace API key, a unique request ID for Idempotency-Key, and the
workflow's required input. If the active version changes, obtain a new example rather than
removing the version pin. Off, blocked, stopping, or legacy destinations must complete their
approved deployment flow before an exact live request is offered.
The MCP option opens the existing workflow publication settings. MCP publication uses the workflow's deployed production version; named previews use the API and are not separate published MCP tools. Check publication readiness in MCP Servers; navigating there does not publish anything.
Legacy production transport
POST /api/v1/workflows/{id}/deploy validates readiness, pins the synchronized candidate, provisions a webhook, and syncs triggers. Success includes { workflow, synchronizedVersionId, webhookUrl, links: { webhook, invoke }, ...syncedTriggers }. Repository review blocks use workflow_review_not_synced, workflow_candidate_changed, or workflow_reviewed_version_unavailable. Other deploy failures → 400 with the public readiness payload.
Validate and review
GET|POST /api/v1/workflows/{id}/validate → { report, deploymentReadiness } (public: no internal env dump). POST validates a draft body without saving.
GET|POST .../review and GET|POST .../sync-from-repo: Versions & Git Review. Review POST: Member+. Sync POST: Admin/Owner.
POST /api/v1/workflows/validate-artifact { files } object or array (400 if missing).
Credentials
POST .../credentials/test → connection probe results for imported aliases. POST .../credentials/bootstrap-from-env → public bootstrap (no secret values). Workspace-wide n8n bootstrap: /api/v1/workers/n8n/credentials/bootstrap-from-env.
MCP
GET|POST /api/v1/workflows/mcp/{workspaceId}/{serverSlug} serves the workflow MCP server for that
workspace slug. It always requires a bearer workspace-scoped API key bound to the stored workflow
server workspace. Initialize, discovery, and listing require current read authority; tool calls require
current execute authority. Personal and copilot keys are rejected, and revoked or downgraded keys lose
authority at use time.
