Importing n8n
Preview, import, and migrate n8n JSON into Confluye, including lossy mappings and sub-workflows.
Confluye can ingest a single n8n workflow JSON, a multi-workflow bundle, or portable Confluye JSON. Import is lossy: n8n expressions, credentials, and unsupported nodes do not become a 1:1 runtime clone. Preview first, then connect credentials and replace blockers before deploy.
Preview before you write
POST /api/v1/workflows/import-preview requires a bearer API key. Body: importJson (one workflow) or importBundleJson (bundle). Optional name is used only as the preview base name. Missing both JSON fields returns 400. Invalid JSON returns 400 with the parser message.
Single-workflow response: { preview, workflow }. Bundle response: { bundle, workflows[] } with per-entry sourceName, sourceId, bundleSubWorkflowStatus, preview, and workflow.
preview.format is n8n or fluxus. Counts include nodeCount, edgeCount, triggerCount, outputCount, and nodeTypes[]. Typical n8n warnings:
- Expressions become Confluye templates where the importer can rewrite them (
{{input.field}}style). Remaining n8n$json/$nodesyntax may not evaluate. - If the graph has no output node, import adds a synthetic
imported_outputnode so the graph can execute. - Missing trigger or output is called out explicitly.
preview.readiness is the setup checklist: missing credentials, imported n8n parameter snapshots, referenced sub-workflows, unsupported nodes, AI provider hints, and schedule/webhook review items.
Apply an import
| Action | Route | Auth |
|---|---|---|
| Create from JSON | POST /api/v1/workflows with importJson | Bearer API key |
| Create from bundle | POST /api/v1/workflows with importBundleJson | Bearer API key |
| Replace an existing graph | PATCH /api/v1/workflows/{id} with importJson | Bearer API key; workspace must match |
| Server bundle path | POST /api/v1/workers/n8n/import-bundle | Bearer API key |
| Session bundle path | POST /api/workers/n8n/import-bundle | Session cookie; workspaceId in body or session |
| Original subflow JSON | POST /api/v1/workers/n8n/subflows/import-originals | Bearer API key |
Create returns 201. Bundle create returns { bundle, workflows[] } with importAction (create vs upsert by original n8n id), importReadiness, bundleSubWorkflowStatus, trigger sync fields, and links. PATCH import forces status: "draft" and returns importReadiness. Identity (id, workspaceId) of the target workflow is preserved; imported n8n ids stay on node config (n8nWorkflowId, n8nType).
Portable Confluye JSON (GET /api/v1/workflows/{id}?format=portable) round-trips name, description, nodes, and edges only. It does not include workspace id.
How n8n nodes map
The importer inspects n8n type + node name + parameters. Positions are rounded. n8n connections become edges; loop back-edges into splitInBatches / Loop Over Items are dropped so Confluye loops stay acyclic.
| n8n (examples) | Confluye kind | Notes |
|---|---|---|
| Manual Trigger, Execute Workflow Trigger | manualTrigger | Child graphs start as a normal manual trigger |
| Webhook | webhookTrigger | Triggers are re-synced on save |
| Schedule / Cron | scheduleTrigger | Timezone defaults from n8n settings (America/New_York if absent) |
| Wait | wait | resume=webhook\|form → mode: event; otherwise duration from amount+unit. onTimeout imports as fail. Date/until waits are not reconstructed from n8n |
| Respond to Webhook | response | Status 200–599; body templated; content type forced to JSON or plain text |
| HTTP Request | httpRequest | Live HTTP still needs WORKFLOW_LIVE_HTTP (or workspace live transports) |
| Execute Workflow / Call Workflow | workflowCall | Keeps original n8n workflow id/name; input defaults to {{lastOutput}} |
| IF / Condition | condition | |
| Switch | router | Route labels come from n8n output names |
| Split In Batches / Loop Over Items | loop | |
| Set / Edit Fields | function | Mapping object when fields parse |
| Code / Function | function | Live JS is gated (see below) |
| Filter, Stop and Error, Extract from File, Read/Write File | function | Dedicated operation values |
| OpenAI / Anthropic / LangChain / Agent | aiAgent | Provider/model hints only |
| Claude Code / Codex CLI | claudeCode / codexCli | Needs local CLI readiness |
| Sticky Note | stickyNote | Canvas annotation; not executed |
| Postgres/MySQL/SQLite/Sheets/Airtable (generic) | tableRead / tableWrite | Write vs read from operation name; often still needs a native table |
| Known Gmail/Sheets/Drive/Calendar/Docs/Jira/GitHub/Postgres query ops | function + operation | Plus optional integration manifest projection |
Known integration operations also set manifestProviderId / manifestOperationId when the catalog can resolve them. Unknown n8n types still become function nodes with n8nType and a parameter snapshot. Nodes flagged unsupportedN8nNode: true (side-effect connectors without a live mapping) block deploy until you replace them. Runtime refuses those nodes with the stored n8nRecommendedMigration text.
n8n node flags map onto settings:
| n8n | Stored settings |
|---|---|
alwaysOutputData | alwaysOutputData |
executeOnce | executeOnce |
onError continueRegularOutput / continueErrorOutput / stopWorkflow | same string |
Sub-workflows
Execute Workflow nodes become workflowCall with config.workflowId equal to the original n8n id. Until a real Confluye workflow with that marker exists, the parent stays a placeholder graph: deploy is blocked. Import the child JSON (or the full bundle) so upsert can replace the placeholder while keeping n8nWorkflowId.
POST /api/v1/workflows with subWorkflowPlaceholder creates an empty child draft for an unresolved id. Bundle import reports bundleSubWorkflowStatus per parent. Reconstructed fallback children (when original JSON was missing) still need a later original-export import via /api/v1/workers/n8n/subflows/import-originals.
Credentials and code
Import does not copy n8n credential secrets. It records names/types and optional credentialBindings. Create workspace credentials, or:
POST /api/v1/workflows/{id}/credentials/bootstrap-from-env— per workflow, from server envPOST /api/v1/workers/n8n/credentials/bootstrap-from-env— workspace-wide for imported aliases (no secret values in the response)
Then POST /api/v1/workflows/{id}/credentials/test to probe connections.
Imported Code nodes stay disabled until the operator enables FLUXUS_ENABLE_WORKFLOW_CODE=true and the deployment reports the isolated Linux executor and its policy as available. Code and general JavaScript expressions then run in a fresh one-use child with serialized inputs, a 5-second Code wall/CPU budget, and bounded code, input, and output sizes. Intl time zones, Buffer, n8n input/output helpers, per-item execution, loops, and JSON normalization remain supported; asynchronous Promise results are not supported. The old FLUXUS_ALLOW_UNSAFE_WORKFLOW_CODE variable is ignored and never enables an unsafe backend. If the flag or policy is unavailable, fix or redeploy the operator environment; the application never falls back to its process. Inline secret-looking strings in code still block deploy. Convert trivial Code nodes to native array/join operations when the importer already did so.
Live side-effect transports (WORKFLOW_LIVE_* / workspace liveTransports) still apply after import. Dry-run and the n8n smoke test do not execute those external writes.
Operator checks
- Preview JSON; read
setupChecklistandunsupportedNodeRequirements. - Import bundle or originals; confirm placeholders are gone (
GET .../validate). - Bootstrap credentials; test them.
POST /api/v1/workers/n8n/smoke-testwith optionalbundlePath,useQueue,waitForWorkerMs. HTTP200= passed,202= attention (readiness leftovers or queued run still waiting),500= failed. The audit does not run the imported graph’s live side effects.
/api/v1/workers/luminai/* mirrors the n8n worker routes for the same bundle tooling.
Limitations
- Not every n8n node type has a native executor. Unknown types are
functionshells or unsupported flags. - Expression conversion is best-effort. Nested n8n expressions can remain invalid.
- Wait
untildates and rich webhook Wait options are not fully reconstructed. - Response headers from n8n are not imported (
headers: {}). - Bundle upsert keys off original n8n workflow ids. Portable JSON without those markers will not merge into the same rows.
- In-memory platform store (
DATABASE_URLunset) loses imported workflows on process restart.
