Workflow imports and workspace sync

Import an exported workflow as a draft, or fork and synchronize workspaces through the v2 preview-and-apply protocol. Preview the destination bindings, apply those exact choices, then poll the returned operation to verify copies and deployment readiness. The CLI workflow guide uses the same protocol.

Choose the interface

HTTP paths below are relative to /api/v2. {workspaceId} is the current workspace you explicitly selected.

CLI commandHTTP request
sim workflows export <id> --include-referencesGET /workflows/{workflowId}/export?includeReferences=true
sim workflows import-preview / sim workflows importPOST /workflows/import/preview / POST /workflows/import
sim workspaces fork-availability / sim workspaces lineageGET /workspaces/{workspaceId}/fork/availability / .../fork/lineage
sim workspaces children / sim workspaces fork-resourcesGET /workspaces/{workspaceId}/fork/children / .../fork/resources?kind=tables
sim workspaces fork-preview / sim workspaces forkPOST /workspaces/{workspaceId}/fork/preview / .../fork
sim workspaces push-preview / sim workspaces push --yesPOST /workspaces/{workspaceId}/fork/push/preview / .../fork/push
sim workspaces pull-preview / sim workspaces pull --yesPOST /workspaces/{workspaceId}/fork/pull/preview / .../fork/pull
sim workspaces mappings get / sim workspaces mappings updateGET / PUT /workspaces/{workspaceId}/fork/mappings
sim selectors list / sim selectors getPOST /selectors/list / POST /selectors/get
sim workspaces operations get <id> / sim workspaces operations wait <id>GET /workspaces/{workspaceId}/operations/{operationId}; wait polls this endpoint
sim workspaces operations listGET /workspaces/{workspaceId}/operations

The sync reference documents fields and includes rollback, unlink, and exclusions. Children, resource discovery, mappings, and operations are paginated: follow nextCursor with the same scope and filters.

Prerequisites and access

Set BASE_URL to your deployment origin, without /api/v2. Use a personal API key in X-API-Key, or an OAuth token in Authorization: Bearer. Examples use separate authorized source/destination keys where applicable. Replace all example resource IDs with IDs from your export and destination.

OperationRequired access
ExportWorkflow read access
Import preview/applyDestination write access; binding credentials also requires an acting user with credential access
Fork discovery, preview, creationSource workspace Admin; creation policy must allow a new workspace
Sync preview/apply and mapping read/updateAdmin on both workspaces on a direct parent/child fork edge
Rollback / unlinkTarget Admin / acting-side Admin, respectively
Selector discoveryRead access in the discovery workspace and access to the selected credential
Operation get/listRead access in the receipt workspace

Workspace keys can import where authoring policy allows, but cannot bind credentials, administer forks, or execute selectors. The key owner is not a substitute for an acting user. Workspace policies, permission groups, credential access, and workspace creation limits still apply.

OAuth import/fork/sync previews require api:write, even though previews do not commit changes. Export, fork discovery, mapping reads, selectors, and operation reads use api:read.

Forking and sync require the owning organization's Enterprise entitlement on billing-enabled deployments. On billing-disabled deployments, deployment configuration must enable forking. Check Fork availability before starting. Imports, selector discovery, and operation reports have their own access rules and do not inherit the fork-specific gate.

Import a portable workflow

Export and inspect the source

Default exports clear registered credential fields and workspace bindings. includeReferences=true adds a versioned manifest of resource IDs and their source occurrences, including nested tools. The manifest contains identities, not secret values. Unresolved environment-variable references remain, and ordinary workflow variable values or literal configuration can remain in the full export. Inspect the payload before sharing it.

Source IDs and imported provenance are labels; they do not grant access to an alleged source workspace. includeWorkspaceBindings=true can retain non-secret bindings for a same-workspace round trip; otherwise configure any required bindings reported by import.

Raw HTTP wraps the result in data; the CLI unwraps a single resource. Extract that payload before saving it:

curl -sS --fail-with-body \
  -H "X-API-Key: $SOURCE_API_KEY" \
  "$BASE_URL/api/v2/workflows/$WORKFLOW_ID/export?includeReferences=true" \
  | jq '.data' > workflow.json

Map destination resources

Save import-mappings.json, using source IDs from the manifest and authorized destination IDs:

[
  { "kind": "credential", "sourceId": "source-connection", "targetId": "destination-connection" },
  { "kind": "sandbox", "sourceId": "source-sandbox", "targetId": "destination-sandbox" }
]

mappings applies to every occurrence of a resource's kind and sourceId. Destination type, provider, and parent/child compatibility are validated. targetId:null requests clearing and cannot satisfy a required binding. Conflicting instructions for one occurrence are rejected.

For older exports, bindings addresses individual registered occurrences. Entries are flat objects, without sourceId or an occurrence wrapper:

[
  {
    "kind": "credential",
    "blockId": "source-agent",
    "subBlockKey": "tools",
    "valuePath": [0, "params", "oauthCredential"],
    "encoding": "scalar",
    "targetId": "destination-connection"
  }
]

A top-level field uses valuePath:[]. Other registered encodings are array, csv, files, and environment; multi-value occurrences can include positions. Use a returned registered occurrence rather than inventing a path.

Preview and complete configuration

Build one request file and preview it:

jq -n --arg workspaceId "$DESTINATION_WORKSPACE" \
  --slurpfile workflow workflow.json --slurpfile mappings import-mappings.json \
  '{workspaceId: $workspaceId, workflow: $workflow[0], mappings: $mappings[0]}' \
  > import-request.json

curl -sS --fail-with-body -H "X-API-Key: $DESTINATION_API_KEY" \
  -H 'Content-Type: application/json' --data @import-request.json \
  "$BASE_URL/api/v2/workflows/import/preview" > import-preview.json

Inspect data.unresolvedBindings, data.configuration, data.unresolvedConfiguration, and data.discovery. Dependent configuration choices have a different shape from bindings:

[
  { "blockId": "source-agent", "subBlockKey": "tools[0].folder", "value": "destination-label" }
]

Add them as dependentValues to the request and preview again. A multiSelect:true field uses a comma-separated string of selected IDs.

For credential-backed selectors, use the import destination workspace and the preview's selectorKey and context to discover options:

curl -sS --fail-with-body -H "X-API-Key: $DESTINATION_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg workspaceId "$DESTINATION_WORKSPACE" \
    '{workspaceId: $workspaceId, selectorKey: "gmail.labels", context: {oauthCredential: "destination-connection"}, limit: 50}')" \
  "$BASE_URL/api/v2/selectors/list"

Selector lists return { "data": [...], "nextCursor": null, "truncated": false }; check pagination and truncation. Detail uses /selectors/get with the same workspace/key/context and an id. MCP tool discovery uses mcp.tools with mcpServerId. A missing OAuth connection can require human authorization; changing a resource ID cannot create the connection.

Keep selector workspace, key, context, and search unchanged when paging. A changed provider page can return 409, requiring discovery to restart. Detail can return data:null for a missing choice or 413 when verification exceeds provider bounds. See List selector and Get selector.

Apply the reviewed import

When data.ready is true, choose a stable IMPORT_REQUEST_ID for this mutation and retain it with the complete request. Apply the exact reviewed choices and fingerprint:

jq --arg requestId "$IMPORT_REQUEST_ID" \
  --arg fingerprint "$(jq -er '.data.previewFingerprint' import-preview.json)" \
  '. + {requestId: $requestId, previewFingerprint: $fingerprint}' \
  import-request.json > import-apply.json

curl -sS --fail-with-body -H "X-API-Key: $DESTINATION_API_KEY" \
  -H 'Content-Type: application/json' --data @import-apply.json \
  "$BASE_URL/api/v2/workflows/import" > import-result.json

Mapped import atomically creates the draft, graph, variables, required inline custom tools, and receipt. Remapping happens before graph ID regeneration; the result includes idMap. Plain imports without mapping options retain their earlier behavior and return no operation receipt. Supplying mapping options, even empty arrays, requires requestId and previewFingerprint.

Imported workflows remain drafts. Check reported configuration and deploy before using ordinary deployed execution.

Fork a workspace

Fork preview and apply start with the same choices:

{
  "name": "Review environment",
  "copy": { "tables": ["source-table"] }
}

POST the request to /workspaces/{workspaceId}/fork/preview. Inspect its plan and fingerprint, then POST the same choices to /workspaces/{workspaceId}/fork with a stable requestId and the returned previewFingerprint.

Eligible deployed source workflows become child drafts. Resources are copied only when selected explicitly. Fork creation uses copy; sync uses copyResources. Fork copy.files contains workspace file IDs, while sync copyResources.files contains storage keys. Credentials and secret values are not copied. Inspect destination configuration before deploying a fork's workflows.

Push or pull a sync

Push sends deployed workflows from the current workspace to otherWorkspaceId. Pull brings them from otherWorkspaceId into the current workspace. Either endpoint can run from either side of a direct parent/child edge, with Admin access to both.

Sync can create target workflows, replace mapped target workflows, and archive mapped targets whose source was deleted or archived. It schedules deployments of the admitted snapshots. An undeployed source alone does not archive its mapped target. Excluded workflows remain excluded; review target replacements and retiring trigger URLs before apply.

Select mappings and copies

For a pull into the workspace in the URL, save sync-request.json:

{
  "otherWorkspaceId": "source-workspace",
  "mappings": [
    { "resourceType": "oauth_credential", "sourceId": "source-connection", "targetId": "destination-connection" }
  ],
  "dependentValues": [
    { "sourceWorkflowId": "source-workflow", "sourceBlockId": "source-agent", "subBlockKey": "tools[0].folder", "value": "destination-label" }
  ],
  "copyResources": { "tables": ["source-table"] }
}

Sync mappings use edge resourceType names such as oauth_credential, service_account_credential, knowledge_base, custom_tool, and sandbox. Imports instead use kind names such as credential, knowledge-base, and custom-tool. Workflow identity is system-managed. Choose a knowledge document through its parent knowledge base's dependent selector instead of writing a knowledge_document edge mapping.

Mapping inspection requires otherWorkspaceId and direction query fields. Read rows include a storage id; writes accept only resourceType, sourceId, and targetId. Project a read page with jq '[.data[] | {resourceType, sourceId, targetId}]' before reusing it, and follow nextCursor for further pages.

Preview does not persist inline mappings. Apply saves them in the sync transaction. Dependent overrides use source workflow/block/field identities, including original nested-tool indices. Omitting dependentValues reuses saved choices; supplying it replaces choices for affected workflows, and [] clears them. Values in a target draft alone are not saved sync configuration.

dropReferences acknowledges references deleted in the source; it cannot discard live source resources.

Preview and inspect trigger choices

curl -sS --fail-with-body -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' --data @sync-request.json \
  "$BASE_URL/api/v2/workspaces/$CURRENT_WORKSPACE/fork/pull/preview" > sync-preview.json

Review unresolvedBindings, configuration, planned workflow actions, and retiring URLs. For selector discovery, use each configuration field's discoveryWorkspaceId: the source when its parent will be copied, the destination when mapped. Pass the returned context and preview any changed choices again. ready:true means the apply plan is ready, not that all destination deployments will be ready.

triggerSlots uses stable sourceWorkflowId and sourceBlockId identities and includes ownPath, adoptablePaths, and defaultAdoptPath:

  • A slot with ownPath preserves that URL and accepts no override.
  • An arriving trigger can adopt an offered retiring path, or request a new URL with adoptPath:null.
  • Unknown identities, duplicate choices, or paths outside the slot's candidates are rejected. Candidates stay within the same target workflow and provider.

Include the same triggerMappings choices on preview and apply:

[
  { "sourceWorkflowId": "source-workflow", "sourceBlockId": "source-trigger", "adoptPath": "retiring-trigger-path" }
]

Apply the sync

Choose a stable SYNC_REQUEST_ID and preserve the exact reviewed request:

jq --arg requestId "$SYNC_REQUEST_ID" \
  --arg fingerprint "$(jq -er '.data.previewFingerprint' sync-preview.json)" \
  '. + {requestId: $requestId, previewFingerprint: $fingerprint, confirm: true}' \
  sync-request.json > sync-apply.json

curl -sS --fail-with-body -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' --data @sync-apply.json \
  "$BASE_URL/api/v2/workspaces/$CURRENT_WORKSPACE/fork/pull" > sync-result.json

For push, use /fork/push/preview and /fork/push with the same direction-relative rules. confirm:true acknowledges target replacement. Changes to mappings or trigger choices require another preview before apply.

Verify operations and recover

Apply returns a single-resource envelope. A completed sync report can look like:

{
  "data": {
    "operationId": "operation-id",
    "requestId": "release-2026-10-13",
    "workspaceId": "current-workspace",
    "kind": "workspace_pull",
    "applied": true,
    "status": "completed",
    "resourceIds": ["destination-workflow"],
    "issues": [],
    "deployments": [
      {
        "operationId": "deployment-id",
        "workflowId": "destination-workflow",
        "version": 2,
        "status": "active",
        "ready": true,
        "pendingComponents": []
      }
    ]
  }
}

Poll under the returned workspaceId:

MutationReceipt workspace
ImportDestination
Fork creationSource workspace on which /fork ran
Push/pullCurrent workspace in the request URL, including a push that changes the other workspace
OPERATION_ID=$(jq -er '.data.operationId' sync-result.json)
OPERATION_WORKSPACE=$(jq -er '.data.workspaceId' sync-result.json)

curl -sS --fail-with-body -H "X-API-Key: $SIM_API_KEY" \
  "$BASE_URL/api/v2/workspaces/$OPERATION_WORKSPACE/operations/$OPERATION_ID"

Poll with a delay while status is processing. Terminal outcomes are completed, completed_with_warnings, requires_configuration, and failed. Inspect issues, copyProgress, deployments[].ready, pendingComponents, and triggerUrlChanges.

applied:true stays true after a follow-up failure: the transaction committed. Completed imports and forks remain drafts. For sync, check the exact admitted deployments in the receipt before treating the destination as ready.

Retry an uncertain response

Request IDs deduplicate within the receipt workspace. Retain the complete apply request and original ID. Identical authorized retries return the original operation before preview-freshness checks. A changed payload under the same ID, stale preview, or blocked apply returns HTTP 409 with the v2 error envelope; other invalid input can return 400. Follow-up failures appear on a committed operation.

After an uncertain response, retry the identical request with its original ID, or query GET /workspaces/{workspaceId}/operations?requestId=.... Lists return { "data": [...], "nextCursor": ... }; use operation get for refreshed copy/deployment status.

If a stale preview is refused before commit, obtain a new preview and use a new request ID for the revised request. Do not replace a lost-response request with a fresh ID just to retry; that can create another mutation.

Rollback restores the latest inbound sync's prior deployed versions. It can archive sync-created workflows and restore archived targets, but does not promise to restore arbitrary target drafts or undo all resource copies. Inspect pendingActivations; another rollback attempt may be needed to finish activation.

Unlink removes the direct relationship and its mappings while retaining workspace content. Exclusions keep selected workflows out of later syncs.