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 } (templates may also return chat thread fields). Bundle: { bundle, workflows[] } with importAction, importReadiness, bundleSubWorkflowStatus, links. links point at version, validate, execute, status, and portable export URLs.
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 }.
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).
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 }) and message? run the workflow for an end user of your product. They are accepted
only from a product gateway key, which must send both endUser and a non-blank message; any other key that sends
either field gets 400. The idempotency fingerprint covers endUser and message, so the same key with another
message answers 409 instead of replaying. 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.
Repeating a completed request with the same key, principal and input returns the original execution receipt, even if the destination has since stopped or its candidate changed. 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.
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).
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.
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.
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.
