> For the complete documentation index, see [llms.txt](https://docs.n8n.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.n8n.io/connect/n8n-api/n8n-package.md).

# N8n Package

Beta — breaking changes may still occur without major version bump.

## Beta: Export workflows, folders, or projects as an n8n package

> \*\*Beta\*\* — breaking changes may still occur without major version bump.\
> \
> Export workflows and/or folders, or projects, as a gzipped tar archive\
> (.n8np). Provide \`workflowIds\`/\`folderIds\`, or \`projectIds\`, but not both\
> groups. Each exported folder includes its nested folders. Empty projects\
> export project metadata only. Statically referenced sub-workflows must also\
> be included in the resulting package, otherwise the export is rejected. The\
> response is streamed as \`application/gzip\` with a \`Content-Disposition\`\
> attachment header. Requires the n8n Packages feature to be licensed.\
> \
> API key scopes: \`workflow:export\` is required when exporting workflows or folders, and \`project:export\` is required when exporting projects. When \`includeVariableValues\` is true (the default) and the exported workflows reference variables, \`variable:list\` is also required; exports that reference no variables never need it.<br>

```json
{"openapi":"3.0.0","info":{"title":"n8n Public API","version":"1.1.1"},"tags":[{"name":"N8nPackage","description":"Beta — breaking changes may still occur without major version bump."}],"servers":[{"url":"/api/v1","description":"Current n8n instance (self-hosted built-in playground)"},{"url":"{url}/api/v1","description":"Self-hosted n8n instance","variables":{"url":{"default":"https://example.com"}}}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]},{"CookieAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-N8N-API-KEY"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"CookieAuth":{"type":"apiKey","in":"cookie","name":"n8n-auth"}},"schemas":{"exportPackageRequest":{"type":"object","additionalProperties":false,"description":"Selects what to export. Provide `workflowIds` and/or `folderIds` to export loose workflows and folders, or `projectIds` to export whole projects, but not both groups in the same request. At least one id must be supplied.","properties":{"workflowIds":{"type":"array","maxItems":300,"description":"IDs of the workflows to include in the exported package.","items":{"type":"string","minLength":1}},"folderIds":{"type":"array","maxItems":300,"description":"IDs of the folders to include in the exported package. Each folder is exported with its nested folders.","items":{"type":"string","minLength":1}},"projectIds":{"type":"array","description":"IDs of the projects to include in the exported package.","items":{"type":"string","minLength":1}},"includeVariableValues":{"type":"boolean","default":true,"description":"Whether values of variables referenced by the exported workflows are bundled into the package. When `false`, variables still travel as name/type files and are listed in the package requirements, but no values travel with the package."},"includeTags":{"type":"boolean","default":true,"description":"Whether tags assigned to the exported workflows are bundled into the package. When `false`, no tag files, tag references, or tag requirements travel with the package."},"missingWorkflowDependencyPolicy":{"type":"string","enum":["fail","reference-only","include-in-package"],"description":"Policy for missing static sub-workflow dependencies. `fail` aborts the export when any static sub-workflow is missing from the package; `include-in-package` automatically adds missing static sub-workflows. `reference-only` keeps missing static sub-workflows out of the package and lists them in the package requirements as workflows expected to already exist on the target.","default":"fail"},"workflowVersionPolicy":{"type":"string","enum":["published-strict","prefer-published","ignore-unpublished","latest"],"description":"Which version of each workflow travels in the package. `latest` exports the latest version, published or not. `published-strict` exports the published version and aborts the export if any workflow has none. `prefer-published` falls back to the latest version where there is no published one. `ignore-unpublished` leaves unpublished workflows out of the package entirely. The chosen version decides which credentials, data tables, variables and sub-workflows are bundled alongside it; the workflow's name, settings and tags are not versioned and always come from the latest version.","default":"latest"}}}},"responses":{"badRequest":{"description":"The request is invalid or provides malformed data."},"unauthorized":{"description":"Unauthorized"},"forbidden":{"description":"Forbidden"},"notFound":{"description":"The specified resource was not found."}}},"paths":{"/n8n-packages/export":{"post":{"tags":["N8nPackage"],"summary":"Beta: Export workflows, folders, or projects as an n8n package","description":"**Beta** — breaking changes may still occur without major version bump.\n\nExport workflows and/or folders, or projects, as a gzipped tar archive\n(.n8np). Provide `workflowIds`/`folderIds`, or `projectIds`, but not both\ngroups. Each exported folder includes its nested folders. Empty projects\nexport project metadata only. Statically referenced sub-workflows must also\nbe included in the resulting package, otherwise the export is rejected. The\nresponse is streamed as `application/gzip` with a `Content-Disposition`\nattachment header. Requires the n8n Packages feature to be licensed.\n\nAPI key scopes: `workflow:export` is required when exporting workflows or folders, and `project:export` is required when exporting projects. When `includeVariableValues` is true (the default) and the exported workflows reference variables, `variable:list` is also required; exports that reference no variables never need it.\n","requestBody":{"description":"Workflows, folders, or projects to include in the exported package.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/exportPackageRequest"}}}},"responses":{"200":{"description":"A gzipped tar archive containing the exported package contents.","headers":{"X-N8n-Export-Counts":{"description":"JSON-serialized per-entity counts of what actually ended up in the\npackage (after folder bundling and auto-inclusion), e.g.\n`{\"workflows\":2,\"folders\":1,\"credentials\":0,\"dataTables\":0,\"variables\":0}`.\n","schema":{"type":"string"}}},"content":{"application/gzip":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/badRequest"},"401":{"$ref":"#/components/responses/unauthorized"},"403":{"$ref":"#/components/responses/forbidden"},"404":{"$ref":"#/components/responses/notFound"}}}}}}
```

## Beta: Import an n8n package into a project

> \*\*Beta\*\* — breaking changes may still occur without major version bump.\
> \
> Imports a gzip-compressed tar package (\`.n8np\`) into the target project. Send the\
> archive as the multipart field \`package\`. Optional routing uses form fields\
> \`projectId\` and \`folderId\` (omit or send empty for defaults). Every optional\
> mode/policy field (credential, workflow, project, folder, data table, variable,\
> and tag) takes its default when omitted. The required\
> \`workflowConflictPolicy\` field controls what happens when a package workflow\
> matches an existing workflow by source id in the target project. Maximum upload\
> size is \`N8N\_ENDPOINTS\_PAYLOAD\_SIZE\_MAX\` MB (default 16).\
> \
> The package must declare its manifest at \`manifest.json\` and include every file\
> referenced by the manifest. The caller is authorised through the \`workflow:import\`\
> scope. With the default \`workflowIdPolicy=new\`, newly created workflows receive a\
> fresh local id; imported workflows arrive inactive unless \`workflowPublishingPolicy\`\
> publishes them after import.\
> \
> Credential references are resolved before any workflow is written. Credentials owned by,\
> shared with, or global to the target project (with \`credential:read\`) match.<br>

```json
{"openapi":"3.0.0","info":{"title":"n8n Public API","version":"1.1.1"},"tags":[{"name":"N8nPackage","description":"Beta — breaking changes may still occur without major version bump."}],"servers":[{"url":"/api/v1","description":"Current n8n instance (self-hosted built-in playground)"},{"url":"{url}/api/v1","description":"Self-hosted n8n instance","variables":{"url":{"default":"https://example.com"}}}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]},{"CookieAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-N8N-API-KEY"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"CookieAuth":{"type":"apiKey","in":"cookie","name":"n8n-auth"}},"responses":{"badRequest":{"description":"The request is invalid or provides malformed data."},"unauthorized":{"description":"Unauthorized"},"forbidden":{"description":"Forbidden"},"notFound":{"description":"The specified resource was not found."}},"schemas":{"importBlockingIssue":{"oneOf":[{"type":"object","description":"A workflow whose source id already matches one in the target project, under the `fail` conflict policy.\n","required":["type","sourceWorkflowId","existingWorkflowId","name"],"properties":{"type":{"type":"string","enum":["workflow-conflict"]},"sourceWorkflowId":{"type":"string"},"existingWorkflowId":{"type":"string"},"name":{"type":"string"}}},{"type":"object","description":"A `source`-policy workflow whose id is already taken on the instance. Workflow ids are globally unique, so the id cannot be created in the target project. The existing workflow may live in any project — including the target project itself — and may be archived (archived workflows keep their id but are never matched for updates).\n","required":["type","sourceWorkflowId","existingWorkflowId","existingProjectId","isArchived","name"],"properties":{"type":{"type":"string","enum":["workflow-id-conflict"]},"sourceWorkflowId":{"type":"string"},"existingWorkflowId":{"type":"string"},"existingProjectId":{"type":"string","nullable":true,"description":"Project that owns the existing workflow, or null when no owning project could be determined.\n"},"isArchived":{"type":"boolean","description":"Whether the existing workflow is archived."},"name":{"type":"string"}}},{"type":"object","description":"A workflow whose source id already matches one in the target project but lives outside the requested import folder. Folder-targeted imports cannot update workflows in place at a different location.\n","required":["type","sourceWorkflowId","existingWorkflowId","existingParentFolderId","targetFolderId","name"],"properties":{"type":{"type":"string","enum":["workflow-folder-conflict"]},"sourceWorkflowId":{"type":"string"},"existingWorkflowId":{"type":"string"},"existingParentFolderId":{"type":"string","nullable":true,"description":"Folder that currently contains the matched workflow, or null when it lives at the project root.\n"},"targetFolderId":{"type":"string","description":"Folder the import was requested to land in."},"name":{"type":"string"}}},{"type":"object","description":"A project defined by the package that already exists on this instance, under `projectConflictPolicy=fail`.\n","required":["type","kind","sourceProjectId","name"],"properties":{"type":{"type":"string","enum":["project-conflict"]},"kind":{"type":"string","enum":["fail-policy"]},"sourceProjectId":{"type":"string"},"name":{"type":"string","description":"The project's name as it appears in the package."}}},{"type":"object","description":"A package folder that cannot be imported as-is. `kind` distinguishes the cause: `parent-mismatch` (a folder matched by id sits under a different parent than the package places it), `id-in-other-project` (the folder id already exists in a different project — ids are globally unique), or `fail-policy` (the folder already exists and `folderConflictPolicy` is `fail`).\n","required":["type","kind","sourceFolderId","name"],"properties":{"type":{"type":"string","enum":["folder-conflict"]},"kind":{"type":"string","enum":["parent-mismatch","id-in-other-project","fail-policy"]},"sourceFolderId":{"type":"string"},"name":{"type":"string"},"existingParentFolderId":{"type":"string","nullable":true,"description":"For `parent-mismatch`: the matched folder's current parent in the target."},"expectedParentFolderId":{"type":"string","nullable":true,"description":"For `parent-mismatch`: the parent the package would place the folder under."},"existingProjectId":{"type":"string","nullable":true,"description":"For `id-in-other-project`: the project that already owns the id."}}},{"type":"object","description":"A node type — or a version of a node type — used by a package workflow that this instance does not have, under `missingNodeTypeMode=fail`. One issue is reported per missing `(nodeType, typeVersion)` pair.\n","required":["type","nodeType","typeVersion","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["missing-node-type"]},"nodeType":{"type":"string","description":"Full node type name as used by the package's workflows."},"typeVersion":{"type":"number","description":"Node type version the package's workflows use."},"usedByWorkflows":{"type":"array","items":{"type":"string"},"description":"Package workflow ids that use this node type and version."}}},{"type":"object","description":"A credential reference that could not be resolved in the target project.","required":["type","kind","sourceId","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["credential-unresolved"]},"kind":{"type":"string","enum":["not_found","unknown_type","source_not_found","type_mismatch"]},"sourceId":{"type":"string"},"targetId":{"type":"string","description":"Target credential id for an explicit credential binding."},"expectedType":{"type":"string","description":"For `type_mismatch`: the credential type the package's workflow node requires.\n"},"actualType":{"type":"string","description":"For `type_mismatch`: the actual type of the resolved target credential.\n"},"usedByWorkflows":{"type":"array","items":{"type":"string"}}}},{"type":"object","description":"A tag referenced by the package's workflows that could not be resolved on the target instance. `kind` distinguishes the cause: `rename-drift` (the same-id target tag carries a different name — under `tagConflictPolicy=fail`, or `rename` when the package name is held by another tag), `name-collision` (the id is free but the name belongs to a different tag under `tagMissingMode=create` with `tagConflictPolicy=fail`; also raised when two package tags collide with each other, or when the target tag a reconcile would re-key is claimed by another package tag), `invalid-name` / `invalid-id` (the package tag's name or id cannot be written on this instance), or `permission-denied` (the importing user lacks the global `tag:create` / `tag:update` scope the plan needs).\n","required":["type","kind","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["tag-unresolved"]},"kind":{"type":"string","enum":["rename-drift","name-collision","invalid-name","invalid-id","permission-denied"]},"sourceId":{"type":"string","description":"Tag id as it appears in the package. Absent for `permission-denied`."},"name":{"type":"string","description":"The (trimmed) package tag name. Absent for `permission-denied`."},"missingScope":{"type":"string","enum":["tag:create","tag:update"],"description":"For `permission-denied`: the global scope the importing user lacks."},"existingTagId":{"type":"string","description":"Id of the contested target tag — the different tag currently holding the wanted name, or the target tag a blocked reconcile would re-key. Absent when two package tags collide with each other rather than over a target tag.\n"},"existingName":{"type":"string","description":"For `rename-drift`: the current name of the same-id target tag."},"usedByWorkflows":{"type":"array","items":{"type":"string"},"description":"Package workflow ids (non-skipped) that reference the source tag — not workflows attached to the contested target tag.\n"}}},{"type":"object","description":"A variable reference that could not be resolved in the target project or the global scope, under `variableMissingMode=must-preexist`.\n","required":["type","name","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["variable-unresolved"]},"name":{"type":"string","description":"Requirement name with no match in the target project or global scope."},"usedByWorkflows":{"type":"array","items":{"type":"string"}}}},{"type":"object","description":"A variable that resolved in the target project or the global scope, but whose value differs from the one the package bundles for it, under `variableConflictPolicy=fail`. Also reported under `overwrite`, once per scope, when the projects of a package resolve one row and disagree about the value it should hold. Values are never reported — only the name and the scope the variable was found in.\n","required":["type","name","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["variable-conflict"]},"name":{"type":"string","description":"Name of the variable whose value differs."},"projectId":{"type":"string","description":"Project owning the resolved variable. Absent when it resolved at the global scope.\n"},"usedByWorkflows":{"type":"array","items":{"type":"string"}}}},{"type":"object","description":"Creating the package's variables under `create-stub` or `create-with-value` would exceed the instance variable quota (`quota:maxVariables`). Reported once for the whole import; nothing is created.\n","required":["type","limit","remaining","requested","names","usedByWorkflows"],"properties":{"type":{"type":"string","enum":["variable-limit-exceeded"]},"limit":{"type":"integer","description":"The instance variable quota."},"remaining":{"type":"integer","description":"Variable rows still available under the quota. The import is blocked because `requested` exceeds this, not because it exceeds `limit`."},"requested":{"type":"integer","description":"Number of new variable rows the import would create (destination-deduplicated)."},"names":{"type":"array","items":{"type":"string"},"description":"The unique variable names the import would create."},"usedByWorkflows":{"type":"array","items":{"type":"string"},"description":"Package workflow ids that reference any of the listed variables."}}}]}}},"paths":{"/n8n-packages/import":{"post":{"tags":["N8nPackage"],"summary":"Beta: Import an n8n package into a project","description":"**Beta** — breaking changes may still occur without major version bump.\n\nImports a gzip-compressed tar package (`.n8np`) into the target project. Send the\narchive as the multipart field `package`. Optional routing uses form fields\n`projectId` and `folderId` (omit or send empty for defaults). Every optional\nmode/policy field (credential, workflow, project, folder, data table, variable,\nand tag) takes its default when omitted. The required\n`workflowConflictPolicy` field controls what happens when a package workflow\nmatches an existing workflow by source id in the target project. Maximum upload\nsize is `N8N_ENDPOINTS_PAYLOAD_SIZE_MAX` MB (default 16).\n\nThe package must declare its manifest at `manifest.json` and include every file\nreferenced by the manifest. The caller is authorised through the `workflow:import`\nscope. With the default `workflowIdPolicy=new`, newly created workflows receive a\nfresh local id; imported workflows arrive inactive unless `workflowPublishingPolicy`\npublishes them after import.\n\nCredential references are resolved before any workflow is written. Credentials owned by,\nshared with, or global to the target project (with `credential:read`) match.\n","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["package","workflowConflictPolicy"],"properties":{"package":{"type":"string","format":"binary","description":"Gzip-compressed tar package (`.n8np`)."},"projectId":{"type":"string","description":"Target project id. Omit or send empty to import into the caller's personal project.\n"},"folderId":{"type":"string","description":"Optional folder within the target project. Omit or send empty for project root.\n"},"credentialMatchingMode":{"type":"string","enum":["id-only","name-and-type","type-only"],"default":"id-only","description":"How credential references in `requirements.credentials` are matched on the target instance. `id-only` (default) matches by id. `name-and-type` matches credentials with the exact same name and type. `type-only` matches any credential of the same type. For `name-and-type` and `type-only`, candidates are ranked by scope — a credential owned by the target project wins over one merely shared into it, which in turn wins over a global credential; if several candidates remain in the winning scope, the most recently updated one is chosen.\n"},"credentialMissingMode":{"type":"string","enum":["must-preexist","create-stub"],"default":"create-stub","description":"What to do when a credential reference cannot be resolved. `create-stub` (default) creates empty credential placeholders in the target project for missing references. `must-preexist` requires every referenced credential to already exist.\n"},"bindings":{"type":"string","default":"{}","description":"Optional JSON object of explicit source→target id bindings, keyed by entity type. Only `credentials` is supported today: send `{\"credentials\":{\"<packageCredentialId>\":\"<targetCredentialId>\"}}` to map credential ids from the package to credential ids on the target instance. These explicit bindings are validated on type and applied before `credentialMatchingMode` resolution runs.\n"},"workflowConflictPolicy":{"type":"string","enum":["new-version","fail","skip"],"description":"`new-version` updates matching workflows and creates a new version, `fail` rejects the import when any matching workflow exists, and `skip` leaves matching workflows unchanged.\n"},"workflowIdPolicy":{"type":"string","enum":["new","source"],"default":"source","description":"Controls the id each newly created workflow receives. `source` (default) reuses the package's own workflow id on the target instance, which best fits promotion use cases where the same workflow moves between environments. `new` mints a fresh id and records the package id as `sourceWorkflowId`, so the same package can be imported repeatedly without id collisions — best suited to marketplace imports. Workflows matched to an existing workflow in the target project (status `updated` or `skipped`) always keep that workflow's current id, regardless of policy.\n"},"missingNodeTypeMode":{"type":"string","enum":["fail","import-anyway"],"default":"fail","description":"What to do when a workflow in the package uses a node type — or a version of a node type — this instance does not have. `fail` (default) rejects the import before anything is written, listing every missing `(nodeType, typeVersion)` pair and the workflows that use it. `import-anyway` imports the package; workflows containing missing node types are never published by this import, regardless of `workflowPublishingPolicy`.\n"},"workflowPublishingPolicy":{"type":"string","enum":["preserve-published-state","match-source","publish-all","unpublish-all"],"default":"preserve-published-state","description":"Controls whether imported workflows are published after content is written. `preserve-published-state` keeps new workflows inactive and republishes an updated workflow only when it was already published and the package workflow is published too, so drafts are never published. `match-source` follows the package workflow's published flag. `publish-all` publishes every imported workflow. `unpublish-all` leaves new workflows inactive and unpublishes updated workflows that were published.\n"},"projectConflictPolicy":{"type":"string","enum":["merge","fail","overwrite"],"default":"merge","description":"What to do when a project the package defines already exists here (matched by id), and — unless `folderConflictPolicy` overrides it — how its contents are treated. `merge` (default) leaves the existing project's name, description, icon and custom span attributes untouched and adds the package's contents alongside. `overwrite` replaces those details with the package's; a detail the package omits is left as it is, not cleared. `fail` rejects the import before anything is written, with one `project-conflict` issue per existing project. A package project id belonging to a personal project, or to a team project the caller cannot update, always rejects the import. Ignored for workflow packages.\n"},"folderConflictPolicy":{"type":"string","enum":["merge","fail"],"default":"merge","description":"Controls what happens when a package folder (matched by id in the target project) already exists at the same position. `merge` (default) reuses the existing folder as-is and merges the package's children into it; `fail` rejects the import. A folder whose id exists under a different parent, or belongs to another project, always blocks the import. Requires the `folder:create` scope and a license that supports folders when the package contains folders.\n"},"dataTableMatchingMode":{"type":"string","enum":["by-id"],"default":"by-id","description":"How data tables referenced by the package's workflows are matched against the target project. `by-id` matches the target-project table with the same id (imported tables keep their source id) and never falls back to name matching, so a match survives a rename on the target. Currently the only mode.\n"},"dataTableMissingMode":{"type":"string","enum":["create","must-preexist","do-nothing"],"default":"create","description":"Controls what happens when a referenced data table has no match in the target project. `create` (default) creates it from the package schema, keeping the source id, with no rows; requires the `dataTable:create` scope. `must-preexist` rejects the import. `do-nothing` skips creation of missing tables — matched tables are still validated for schema compatibility and can still block the import. Matched tables are always used as-is: never renamed, altered, or filled.\n"},"dataTableSchemaConflictPolicy":{"type":"string","enum":["keep-existing","fail"],"default":"keep-existing","description":"How strictly a matched data table's schema is compared. `keep-existing` (default) accepts a target table that has every package column with the same name and type, even when the target table also has additional columns of its own. `fail` is the strict drift-detection choice: any difference, including such target-only columns, rejects the import. A missing package column or a type mismatch always rejects. Both policies are non-destructive — the matched target table is never altered, and package columns are never added to it.\n"},"variableMissingMode":{"type":"string","enum":["do-nothing","must-preexist","create-stub","create-with-value"],"default":"create-with-value","description":"Controls what happens when a variable referenced by the package's workflows is absent from the target project and the global scope (lookup order: project, then global). `create-with-value` (default) creates the variable with its package value and lists its name under `variables.created`. When the package carries no value for it — values were excluded at export, or the exported value was itself empty — it creates an empty stub listed under `variables.stubbed`. `do-nothing` imports without creating the variable and lists its name under `variables.missing`. `must-preexist` rejects the import unless every referenced variable already resolves. `create-stub` creates each missing variable with an empty value at the placement scope (see `variableParentPolicy`) and lists the created names under `variables.stubbed`. An import that actually creates a variable requires a license that permits variables and, for API key callers, the `variable:create` scope; a package whose variables all already resolve creates nothing and needs neither.\n"},"variableConflictPolicy":{"type":"string","enum":["keep-existing","overwrite","fail"],"default":"keep-existing","description":"What to do when a referenced variable resolves in the target project or global scope but the package bundles a *different* value for it. `keep-existing` (default) leaves the target value untouched and reports the name under `variables.matched`. `overwrite` silently replaces the value of the existing variable at whichever scope it was found — the target project or the global scope, so a global variable other projects also read can be rewritten by this import — and reports the name under `variables.updated`; it needs a license that permits variables, the `variable:update` / `projectVariable:update` permission on that scope, and, for API key callers, the `variable:update` scope. `fail` rejects the import with a 409 instead. Every policy leaves a resolved variable alone when there is nothing to change — either the package bundles no value for it (values were excluded at export, or the exported value was itself empty), or the value it bundles already matches the target's. The reverse does not hold: a resolved variable holding an empty value — a stub an earlier import created, say — still counts as a value, so `overwrite` fills it and `fail` rejects it. Under `overwrite`, a project package whose projects hold *different* values for a name they all resolve to one row — a global none of them shadows, typically — is rejected with a 409: one row cannot carry both values, and the import will not pick for you. Give the projects their own variables in the target, or import them separately.\n"},"variableParentPolicy":{"type":"string","enum":["project","global"],"description":"Where `create-with-value` and `create-stub` create missing variables for workflow/folder packages. `project` — also the behaviour when the field is omitted — creates them in the import target project (`projectId`, else the caller's personal project). `global` creates them at the global scope. The license and `variable:create` requirements described under `variableMissingMode` apply to both placements. Must be omitted for project packages, which reject it with a 400: their placement follows the package layout, where a variable bundled under a project is created in that project and one bundled at the top level is created globally.\n"},"tagMissingMode":{"type":"string","enum":["create","do-nothing"],"default":"create","description":"What to do when a tag referenced by the package's workflows has no tag with the same id on the target instance (tags are matched by source id, never by name). `create` (default) creates the tag globally with its package (source) id and name; when the import would create a tag this needs an API key carrying the `tag:create` scope. `do-nothing` imports the workflows without the missing tags — nothing is created and the dropped names are listed under `tags.skipped`.\n"},"tagConflictPolicy":{"type":"string","enum":["skip","fail","rename"],"default":"skip","description":"What to do when a referenced tag conflicts on the target instance — either the same-id target tag carries a different name (rename drift), or the tag's name is already held by a different tag (name collision). `skip` (default) drops the conflicted tags from the import (not created, not renamed, not attached anywhere; the import proceeds and lists them under `tags.skipped`). `fail` rejects the import with a 409. `rename` renames a drifted target tag to the package name, and reconciles a name collision by re-keying the existing tag to the package (source) id — its name, workflow and folder taggings follow; both need an API key carrying the `tag:update` scope when the import would rename or reconcile a tag. A drifted tag whose package name is held by another tag still rejects the import (rename degrades to fail).\n"}}}}}},"responses":{"200":{"description":"Import succeeded; the listed workflows were written to the target project.","content":{"application/json":{"schema":{"type":"object","required":["package","workflows","folders","projects","bindings","credentials","variables","tags"],"properties":{"package":{"type":"object","required":["sourceN8nVersion","sourceId","exportedAt"],"properties":{"sourceN8nVersion":{"type":"string"},"sourceId":{"type":"string"},"exportedAt":{"type":"string","format":"date-time"}}},"workflows":{"type":"array","items":{"type":"object","required":["sourceWorkflowId","localId","name","projectId","parentFolderId","activeVersionId","publishing","status"],"properties":{"sourceWorkflowId":{"type":"string","description":"Workflow id as it appeared in the package."},"localId":{"type":"string","description":"Workflow id on the target instance: newly assigned for `created` (fresh under `workflowIdPolicy=new`, the package id under `source`), the existing workflow's id for `updated`/`skipped`.\n"},"name":{"type":"string"},"projectId":{"type":"string"},"parentFolderId":{"type":"string","nullable":true},"activeVersionId":{"type":"string","nullable":true,"description":"Published version on the target instance, if any. `null` when the workflow is not published after import.\n"},"publishing":{"type":"object","required":["state"],"description":"Outcome of applying the selected publishing policy to this workflow.\n","properties":{"state":{"type":"string","enum":["published","unpublished","unchanged","blocked","failed"],"description":"`blocked` means the imported version could not be published and no version is active (for example because the workflow uses a stubbed credential, or uses a node type this instance does not have). When a prior published version remains active, `state` is `unchanged` with `skippedPublishReason` instead. `failed` means publish or unpublish was attempted but did not succeed.\n"},"error":{"type":"string","description":"Present when `state` is `failed`. Explains why publish or unpublish could not be applied.\n"},"blockedReason":{"type":"string","enum":["stub-credential","missing-node-type"],"description":"Present when `state` is `blocked`: the imported version could not be published and no version is active.\n"},"skippedPublishReason":{"type":"string","enum":["stub-credential","missing-node-type"],"description":"Present when `state` is `unchanged` but the policy wanted to publish the imported version: a prior published version is still active (for example after an update with stubbed credentials).\n"}}},"status":{"type":"string","enum":["created","updated","skipped"],"description":"Import outcome for this package workflow."}}}},"folders":{"type":"array","description":"Folder shells created or skipped in the target project.","items":{"type":"object","required":["sourceFolderId","localId","name","parentFolderId","status"],"properties":{"sourceFolderId":{"type":"string","description":"Folder id as it appeared in the package."},"localId":{"type":"string","description":"Folder id on the target instance (equal to `sourceFolderId`; folder ids are reused)."},"name":{"type":"string"},"parentFolderId":{"type":"string","nullable":true,"description":"Resolved parent folder on the target, or `null` at the project root."},"status":{"type":"string","enum":["created","skipped"],"description":"Import outcome for this package folder."}}}},"projects":{"type":"array","description":"Project shells created, or matched and then updated or left as-is (see `projectConflictPolicy`). Present for project packages; empty when importing loose workflows/folders.\n","items":{"type":"object","required":["sourceProjectId","localId","name","status"],"properties":{"sourceProjectId":{"type":"string","description":"Project id as it appeared in the package."},"localId":{"type":"string","description":"Project id on the target instance (equal to `sourceProjectId`; project ids are reused)."},"name":{"type":"string","description":"The project's name on the target: the package's under `overwrite`, the pre-existing one under `merge`.\n"},"status":{"type":"string","enum":["created","updated","skipped"],"description":"Import outcome for this package project. `skipped` means the project already existed and `projectConflictPolicy=merge` left its details untouched — its contents were still imported.\n"}}}},"credentials":{"type":"object","description":"Source credential ids grouped by whether they matched an existing credential or were created as stubs. Full source→target id mapping is in `bindings.credentials`.\n","required":["matched","stubbed"],"properties":{"matched":{"type":"array","items":{"type":"string"},"description":"Source credential ids from the package that matched existing credentials on the target instance.\n"},"stubbed":{"type":"array","items":{"type":"string"},"description":"Source credential ids for which empty placeholder credentials were created in the target project.\n"}}},"variables":{"type":"object","description":"Resolution of the package's variable requirements. Names only — values never travel in the response. For project packages these arrays are package-level unions of per-destination outcomes and may overlap (for example, a name may be created with a value in one project and stubbed in another); classification under concurrent external writes is best-effort.\n","required":["matched","missing","created","stubbed","updated"],"properties":{"matched":{"type":"array","items":{"type":"string"},"description":"Variable names that resolved to an existing variable (importing project's scope first, then global) and were left untouched. A resolved variable this import rewrote is listed under `updated` instead.\n"},"missing":{"type":"array","items":{"type":"string"},"description":"Variable names still unresolved after import. Under `variableMissingMode=do-nothing` these are warnings — the import still succeeds and nothing is created. A successful `create-stub` or `create-with-value` import normally leaves this empty.\n"},"created":{"type":"array","items":{"type":"string"},"description":"Variable names created with a package value under `variableMissingMode=create-with-value`. Empty stubs are listed under `stubbed`.\n"},"stubbed":{"type":"array","items":{"type":"string"},"description":"Variable names created with an empty value by this import under `variableMissingMode=create-stub`, or because `create-with-value` had no exported value. Empty for other outcomes.\n"},"updated":{"type":"array","items":{"type":"string"},"description":"Variable names whose existing value this import replaced with the package value under `variableConflictPolicy=overwrite`. Empty for other policies.\n"}}},"tags":{"type":"object","description":"Resolution of the tags referenced by the imported workflows, matched by source id. Tag names only.\n","required":["matched","created","renamed","reconciled","skipped"],"properties":{"matched":{"type":"array","items":{"type":"string"},"description":"Tags that resolved to an existing tag with the same id and name; attached as-is.\n"},"created":{"type":"array","items":{"type":"string"},"description":"Tags created by this import with their package (source) id and name, under `tagMissingMode=create`.\n"},"renamed":{"type":"array","items":{"type":"string"},"description":"Target tags renamed to the package name under `tagConflictPolicy=rename`; listed by their new name.\n"},"reconciled":{"type":"array","items":{"type":"string"},"description":"Existing target tags re-keyed to the package (source) id on a name collision under `tagConflictPolicy=rename`; their name, workflow and folder taggings are kept.\n"},"skipped":{"type":"array","items":{"type":"string"},"description":"Tags dropped from the import — not created, not renamed, and not attached to any imported workflow — under `tagMissingMode=do-nothing` or `tagConflictPolicy=skip`.\n"}}},"bindings":{"type":"object","description":"Source id → target id mappings produced during import, one map per entity type. Each value maps an id as it appeared in the package to the id on the target instance.\n","required":["workflows","credentials"],"properties":{"workflows":{"type":"object","additionalProperties":{"type":"string"}},"credentials":{"type":"object","description":"Credential id from `requirements.credentials` in the package manifest → matched credential id on the target instance.\n","additionalProperties":{"type":"string"}}}}}}}}},"400":{"$ref":"#/components/responses/badRequest"},"401":{"$ref":"#/components/responses/unauthorized"},"403":{"$ref":"#/components/responses/forbidden"},"404":{"$ref":"#/components/responses/notFound"},"409":{"description":"Import blocked by at least one conflict among the issues — a workflow source-id conflict, a folder conflict (id under a different parent, id owned by another project, or a `fail`-policy match), a tag conflict (rename drift or name collision), a variable whose bundled value differs from the resolved target's under `variableConflictPolicy=fail`, or one row two projects of a package would overwrite with different values.\n","content":{"application/json":{"schema":{"type":"object","required":["message","issues"],"properties":{"message":{"type":"string"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/importBlockingIssue"}}}}}}},"422":{"description":"Import blocked by non-conflict issues only (e.g. unresolved credentials or variables, node types this instance does not have under `missingNodeTypeMode=fail`, or variable stubs whose creation would exceed the instance variable quota).\n","content":{"application/json":{"schema":{"type":"object","required":["message","issues"],"properties":{"message":{"type":"string"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/importBlockingIssue"}}}}}}}}}}}}
```
