import-cloudflow-flow
dci import-cloudflow-flow [body] [flags]
Creates every flow of a previously exported bundle in the authenticated tenant. Imports are create-only: each call creates new draft flows with new IDs — nothing is published and no schedule is activated until the target tenant publishes.
Requirements declared by the bundle are resolved through bindings (requirement key →
target-tenant resource ID). Unbound connections and Datastore tables leave the
referencing nodes flagged incomplete; unbound global variables are auto-created. Pass
options.createMissingTables: true to create missing Datastore tables from the schemas
embedded in the bundle (structure only, never row data).
Dry-run: pass ?dryRun=true to validate without writing. The response is an import
plan: per-requirement resolutions with candidate bindings in the target tenant, the
flows that would be created, and every validation issue at once.
Pass the request body as name: value arguments or pipe JSON on stdin — see Command structure.
- A bare bundle is wrapped for you. Piping the output of
export-cloudflow-flowstraight in works: the CLI nests it under the request'sbundlefield. Send the fullbundle/bindings/optionsshape only when you need bindings or options. --dry-runis the API's dry run, not a local preview: the request is sent, nothing is written, and the response is the import plan. The CLI generates a throwaway idempotency key for dry runs, so--idempotency-keyis only needed on the real import — where the API requires it (idempotency_key_required). Generate a fresh one per import; re-sending the same key returns the cached response instead of importing again.
Imports are create-only and land as drafts. Requirement keys for bindings come from the
dry-run plan (or the bundle's requirements); connection IDs come from
dci list-cloudflow-connections. Unbound connections and tables leave their nodes flagged
incomplete; unbound global variables are created automatically. After importing, validate
and exercise the draft with dci test-run-cloudflow-flow.
Examples
# Validate a bundle first — writes nothing and returns the import plan.
dci import-cloudflow-flow --dry-run < bundle.json
`valid`, every validation `error` at once, the `flowsToCreate`, and each requirement's `resolution` (`bound`, `suggested`, `willCreate`, or `unbound`) with candidate IDs in this tenant.
# Import for real; a fresh idempotency key is required on every real import.
dci import-cloudflow-flow --idempotency-key "$(uuidgen)" < bundle.json
`flows[]` with each created flow's new `id`, `status: draft`, and any `incompleteNodes` to finish in the builder before publishing.
# Bind a connection requirement and set import options by sending the full request shape.
dci import-cloudflow-flow --idempotency-key "$(uuidgen)" < import.json
# import.json — the exported bundle under "bundle", plus bindings and options
{"bundle": {"kind": "cloudflow.doit.com/FlowBundle", "schemaVersion": 1, "rootFlow": "main",
"flows": [{"key": "main", "name": "Nightly cleanup", "firstNode": "trigger",
"nodes": [{"key": "trigger", "name": "Manual trigger", "type": "manualTrigger"}]}],
"requirements": {"connections": [{"key": "aws-main", "name": "AWS production", "provider": "amazon-web-services"}]}},
"bindings": {"connections": {"aws-main": "<connection-id>"}},
"options": {"createMissingTables": true, "namePrefix": "Copy of "}}
Request
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
bundle | object | yes | Portable, tenant-neutral export of one or more flows. Contains no credentials, tenant identifiers, schedules, or execution state; tenant-scoped references are declared under requirements and appear inside node parameters as $req:<section>/<key> tokens (subflow references as $bundle:flows/<flowKey>). |
bundle.kind | string | yes | One of: "cloudflow.doit.com/FlowBundle". |
bundle.schemaVersion | integer | yes | Bundle format version. The server exports the newest version and accepts every version it has ever shipped. One of: 1. |
bundle.exportedAt | string (date-time) | Informational export timestamp; ignored on import. | |
bundle.rootFlow | string | yes | Key (into flows) of the flow that was exported; the rest are its subflows. |
bundle.flows | array of object | yes | |
bundle.flows[].key | string | yes | Bundle-local flow key. Opaque — the server generates new IDs at import. |
bundle.flows[].name | string | yes | |
bundle.flows[].description | string | ||
bundle.flows[].tags | map of array of string | ||
bundle.flows[].triggerType | string | ||
bundle.flows[].firstNode | string | yes | Key of this flow's entry node. |
bundle.flows[].nodes | array of object | yes | |
bundle.flows[].nodes[].key | string | yes | |
bundle.flows[].nodes[].name | string | yes | |
bundle.flows[].nodes[].description | string | ||
bundle.flows[].nodes[].type | string | yes | Node type (e.g. triggerNode, actionNode, datastoreNode). Validated against the supported node-type set at import. |
bundle.flows[].nodes[].parameters | object | Node parameters with tenant-scoped scalar references replaced by $req:/$bundle: tokens. | |
bundle.flows[].nodes[].approval | object | Approval configuration without recipients (recipients are tenant-scoped and removed at export). Nested fields omitted — see the raw JSON schema. | |
bundle.flows[].nodes[].transitions | array of object | Nested fields omitted — see the raw JSON schema. | |
bundle.flows[].localVariables | array of object | ||
bundle.flows[].localVariables[].key | string | yes | |
bundle.flows[].localVariables[].name | string | yes | |
bundle.flows[].localVariables[].description | string | ||
bundle.flows[].localVariables[].required | boolean | ||
bundle.flows[].localVariables[].type | string | yes | |
bundle.flows[].localVariables[].elementType | string | ||
bundle.flows[].localVariables[].value | string | Present unless the export stripped variable values. Connection-typed values are $req:connections/<key> tokens. | |
bundle.flows[].unsupportedReferences | array of object | Tenant-scoped references removed at export (policy IDs, Slack channels); import flags the affected nodes incomplete. | |
bundle.flows[].unsupportedReferences[].nodeKey | string | yes | |
bundle.flows[].unsupportedReferences[].kind | string | yes | One of: "policy", "slackChannel". |
bundle.flows[].unsupportedReferences[].detail | string | ||
bundle.requirements | object | Tenant-scoped resources the bundle needs; each is bound to a target-tenant resource at import. | |
bundle.requirements.connections | array of object | ||
bundle.requirements.connections[].key | string | yes | |
bundle.requirements.connections[].provider | string | yes | Cloud provider the bound connection must have (e.g. amazon-web-services). |
bundle.requirements.connections[].name | string | yes | The source connection's display name, as a matching hint. |
bundle.requirements.connections[].usedByNodes | array of string | ||
bundle.requirements.datastoreTables | array of object | ||
bundle.requirements.datastoreTables[].key | string | yes | |
bundle.requirements.datastoreTables[].name | string | yes | |
bundle.requirements.datastoreTables[].description | string | ||
bundle.requirements.datastoreTables[].fields | array of object | yes | Nested fields omitted — see the raw JSON schema. |
bundle.requirements.datastoreTables[].usedByNodes | array of string | ||
bundle.requirements.globalVariables | array of object | ||
bundle.requirements.globalVariables[].key | string | yes | |
bundle.requirements.globalVariables[].name | string | yes | |
bundle.requirements.globalVariables[].description | string | ||
bundle.requirements.globalVariables[].type | string | yes | |
bundle.requirements.globalVariables[].elementType | string | ||
bundle.requirements.globalVariables[].value | string | Present unless the export stripped variable values. | |
bundle.requirements.globalVariables[].usedByNodes | array of string | ||
bindings | object | Requirement key → target-tenant resource ID. Keys must be declared in the bundle's requirements. Run with ?dryRun=true first to list required keys and candidate IDs. | |
bindings.connections | map of string | ||
bindings.datastoreTables | map of string | ||
bindings.globalVariables | map of string | ||
options | object | ||
options.createMissingTables | boolean | Create unbound Datastore tables from the schemas embedded in the bundle (structure only, never row data). A same-named existing table with an incompatible schema is a validation error. Default: false. | |
options.namePrefix | string | Optional prefix for every created flow's name. |
Raw JSON schema
{
"type": "object",
"required": [
"bundle"
],
"properties": {
"bundle": {
"type": "object",
"description": "Portable, tenant-neutral export of one or more flows. Contains no credentials, tenant identifiers, schedules, or execution state; tenant-scoped references are declared under `requirements` and appear inside node parameters as `$req:<section>/<key>` tokens (subflow references as `$bundle:flows/<flowKey>`).",
"required": [
"kind",
"schemaVersion",
"rootFlow",
"flows"
],
"properties": {
"kind": {
"type": "string",
"enum": [
"cloudflow.doit.com/FlowBundle"
]
},
"schemaVersion": {
"type": "integer",
"description": "Bundle format version. The server exports the newest version and accepts every version it has ever shipped.",
"enum": [
1
]
},
"exportedAt": {
"type": "string",
"format": "date-time",
"nullable": true,
"description": "Informational export timestamp; ignored on import."
},
"rootFlow": {
"type": "string",
"description": "Key (into `flows`) of the flow that was exported; the rest are its subflows."
},
"flows": {
"type": "array",
"maxItems": 20,
"items": {
"type": "object",
"required": [
"key",
"name",
"firstNode",
"nodes"
],
"properties": {
"key": {
"type": "string",
"description": "Bundle-local flow key. Opaque — the server generates new IDs at import."
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"tags": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"triggerType": {
"type": "string",
"nullable": true
},
"firstNode": {
"type": "string",
"description": "Key of this flow's entry node."
},
"nodes": {
"type": "array",
"maxItems": 150,
"items": {
"type": "object",
"required": [
"key",
"name",
"type"
],
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"type": {
"type": "string",
"description": "Node type (e.g. `triggerNode`, `actionNode`, `datastoreNode`). Validated against the supported node-type set at import."
},
"parameters": {
"type": "object",
"additionalProperties": true,
"description": "Node parameters with tenant-scoped scalar references replaced by `$req:`/`$bundle:` tokens."
},
"approval": {
"type": "object",
"description": "Approval configuration without recipients (recipients are tenant-scoped and removed at export).",
"properties": {
"required": {
"type": "boolean"
},
"message": {
"type": "string"
},
"rejectApprovalAfterTime": {
"type": "boolean"
},
"rejectTimeValue": {
"type": "integer"
},
"rejectTimeUnit": {
"type": "string"
}
}
},
"transitions": {
"type": "array",
"items": {
"type": "object",
"required": [
"target"
],
"properties": {
"target": {
"type": "string",
"description": "Key of the node this transition points at."
},
"label": {
"type": "string",
"nullable": true
},
"pathId": {
"type": "string",
"nullable": true
}
}
}
}
}
}
},
"localVariables": {
"type": "array",
"maxItems": 50,
"items": {
"type": "object",
"required": [
"key",
"name",
"type"
],
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"required": {
"type": "boolean"
},
"type": {
"type": "string"
},
"elementType": {
"type": "string"
},
"value": {
"type": "string",
"description": "Present unless the export stripped variable values. Connection-typed values are `$req:connections/<key>` tokens."
}
}
}
},
"unsupportedReferences": {
"type": "array",
"description": "Tenant-scoped references removed at export (policy IDs, Slack channels); import flags the affected nodes incomplete.",
"items": {
"type": "object",
"required": [
"nodeKey",
"kind"
],
"properties": {
"nodeKey": {
"type": "string"
},
"kind": {
"type": "string",
"enum": [
"policy",
"slackChannel"
]
},
"detail": {
"type": "string"
}
}
}
}
}
}
},
"requirements": {
"type": "object",
"description": "Tenant-scoped resources the bundle needs; each is bound to a target-tenant resource at import.",
"properties": {
"connections": {
"type": "array",
"maxItems": 50,
"items": {
"type": "object",
"required": [
"key",
"provider",
"name"
],
"properties": {
"key": {
"type": "string"
},
"provider": {
"type": "string",
"description": "Cloud provider the bound connection must have (e.g. `amazon-web-services`)."
},
"name": {
"type": "string",
"description": "The source connection's display name, as a matching hint."
},
"usedByNodes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"datastoreTables": {
"type": "array",
"maxItems": 50,
"items": {
"type": "object",
"required": [
"key",
"name",
"fields"
],
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"fields": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"dataType"
],
"properties": {
"name": {
"type": "string"
},
"dataType": {
"type": "string"
},
"isUnique": {
"type": "boolean"
},
"description": {
"type": "string"
}
}
}
},
"usedByNodes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"globalVariables": {
"type": "array",
"maxItems": 50,
"items": {
"type": "object",
"required": [
"key",
"name",
"type"
],
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"type": {
"type": "string"
},
"elementType": {
"type": "string"
},
"value": {
"type": "string",
"description": "Present unless the export stripped variable values."
},
"usedByNodes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
},
"bindings": {
"type": "object",
"description": "Requirement key → target-tenant resource ID. Keys must be declared in the bundle's requirements. Run with `?dryRun=true` first to list required keys and candidate IDs.",
"properties": {
"connections": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"datastoreTables": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"globalVariables": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"options": {
"type": "object",
"properties": {
"createMissingTables": {
"type": "boolean",
"default": false,
"description": "Create unbound Datastore tables from the schemas embedded in the bundle (structure only, never row data). A same-named existing table with an incompatible schema is a validation error."
},
"namePrefix": {
"type": "string",
"description": "Optional prefix for every created flow's name."
}
}
}
}
}
Flags
| Flag | Type | Default | Example | Description |
|---|---|---|---|---|
--dry-run | boolean | false | If true, validates the bundle and resolves its requirements against the tenant without committing changes, returning the import plan. |
Every command also accepts the CLI-wide flags for output shaping — see Output formats and Table output options.
Output
Dry-run import plan (no writes performed).
By default dci renders the result as a table. Use --output json to get the full structure described below — see Output formats.
| Field | Type | Description |
|---|---|---|
valid | boolean | |
requirements | array of object | |
requirements[].section | string | One of: "connections", "datastoreTables", "globalVariables". |
requirements[].key | string | |
requirements[].resolution | string | One of: "bound", "suggested", "willCreate", "unbound". |
requirements[].boundTo | string | |
requirements[].candidates | array of object | |
requirements[].candidates[].id | string | |
requirements[].candidates[].name | string | |
requirements[].candidates[].provider | string | |
requirements[].consequenceIfUnbound | string | |
flowsToCreate | array of object | |
flowsToCreate[].key | string | |
flowsToCreate[].name | string | |
flowsToCreate[].nodeCount | integer | |
flowsToCreate[].incompleteNodeCount | integer | |
errors | array of object | |
errors[].code | string | One of: "bundle_schema_invalid", "bundle_version_unsupported", "bundle_limits_exceeded", "binding_not_found", "binding_provider_mismatch", "table_schema_incompatible", "global_variable_type_conflict", "internal_field_rejected". |
errors[].field | string | |
errors[].message | string |
Raw JSON schema
{
"type": "object",
"description": "Dry-run result — what an import of this request would do, with every validation issue reported at once.",
"required": [
"valid",
"requirements",
"flowsToCreate",
"errors"
],
"properties": {
"valid": {
"type": "boolean"
},
"requirements": {
"type": "array",
"items": {
"type": "object",
"required": [
"section",
"key",
"resolution"
],
"properties": {
"section": {
"type": "string",
"enum": [
"connections",
"datastoreTables",
"globalVariables"
]
},
"key": {
"type": "string"
},
"resolution": {
"type": "string",
"enum": [
"bound",
"suggested",
"willCreate",
"unbound"
]
},
"boundTo": {
"type": "string"
},
"candidates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"provider": {
"type": "string"
}
}
}
},
"consequenceIfUnbound": {
"type": "string"
}
}
}
},
"flowsToCreate": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"nodeCount": {
"type": "integer"
},
"incompleteNodeCount": {
"type": "integer"
}
}
}
},
"errors": {
"type": "array",
"items": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"enum": [
"bundle_schema_invalid",
"bundle_version_unsupported",
"bundle_limits_exceeded",
"binding_not_found",
"binding_provider_mismatch",
"table_schema_incompatible",
"global_variable_type_conflict",
"internal_field_rejected"
]
},
"field": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
}
}
}
Errors
On failure, dci prints a single error message — with a hint when one is available — and exits with a typed code your scripts can branch on. See Errors and exit codes for the full contract.
HTTP status to exit code mapping
| HTTP status | Exit code | Error code | Meaning |
|---|---|---|---|
| 400, 422 | 30 | VALIDATION_ERROR | The arguments or request body were rejected. Review the command's flags and payload. |
| 401 | 10 | AUTHENTICATION_FAILED | Not signed in, or the API token is invalid. Run dci login or check DCI_API_KEY. |
| 403 | 11 | PERMISSION_DENIED | The DoiT user or the active customer context does not have access. |
| 500 | 40 | API_SERVER_ERROR | The API failed to process the request. Retryable; contact DoiT support if it persists. |
Related
- export-cloudflow-flow — Export a flow as a portable bundle
- test-run-cloudflow-flow — Test-run a flow
- list-cloudflow-connections — List connections
- build-cloud-flow — Build a new CloudFlow from scratch
- list-cloudflows — List CloudFlows
- API reference: POST /cloudflow/v1/flows/actions/import
Aliases: importcloudflowflow