Returning.AIDocs
v1

API reference / Workflow Builder

.md

Duplicate a router branch

Copies one branch, including the steps that belong to it, and appends the copy to the router.

Last updated 28 Oct 2026API v1

Method
POST
Path
https://api.returning.ai/v1/workflow-builder/data-workflows/{workflowId}/nodes/{nodeId}/branches/{branchIndex}/duplicate
Permission
workflowBuilder
Retries
Not idempotent: two accepted calls create two branches.

When to use this

Use it to build a variant quickly: duplicate a branch, change its conditions, and add it as another case.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
workflowBuilder

Authorization: Bearer <API_KEY> with workflowBuilder, on a workflow of the key's community. If-Match is optional. Send the revision you read to avoid overwriting a concurrent change (a stale value is refused with 409 VERSION_CONFLICT); omit it and your write wins as the last one. A deployed workflow is edited with the same call: the change applies immediately.

FailureMeaningRecovery
404 BRANCH_NOT_FOUNDNo branch at that indexRead the router and use an existing index.

Behaviour#

The copy's steps are new steps with new ids, and references between them are rewired to the copies, including a {{<stepId>.path}} template.

Request#

Path parameters#

workflowId#stringREQUIRED
Workflow identifier: 24 hexadecimal characters, as returned in _id.

Rule^[0-9a-fA-F]{24}$

Eg65f1a2b3c4d5e6f708192a3b

nodeId#stringREQUIRED
Step identifier: 24 hexadecimal characters, as returned in the step's _id.

Rule^[0-9a-fA-F]{24}$

Eg65f1a2b3c4d5e6f708192a3c

branchIndex#integerREQUIRED
Zero-based index of the branch inside the router step, in stored order.

RuleMin 0

Eg0

Headers#

Authorization#stringREQUIRED
Community API key: Bearer <API_KEY>.

EgBearer <API_KEY>

If-Match#stringOPTIONAL
Optional. Send the revision the change is based on, bare or quoted, to avoid overwriting a concurrent change: a stale value is refused with 409 VERSION_CONFLICT. Omit it for last-write-wins.

Eg162af81f5de4ff2b557a4087de9a9a73a0ed4e621f737787e35a93614cb50d1c

Watch for

  • The copy has the same conditions as the original. Change them, or the second branch can never be reached when executePaths is first_matching.
  • The copied branch is appended last, so a duplicated fallback ends up after the original fallback and never runs.
  • Credentials inside copied steps are copied as stored and are redacted in the response.
  • A Code step inside the copied branch is copied like any other step, with its source.
More examples and details
BASH
curl --request POST \
  --url "https://api.returning.ai/v1/workflow-builder/data-workflows/65f1a2b3c4d5e6f708192a3b/nodes/65f1a2b3c4d5e6f708192a3e/branches/0/duplicate" \
  --header "Authorization: Bearer <API_KEY>" \
  --header "If-Match: 162af81f5de4ff2b557a4087de9a9a73a0ed4e621f737787e35a93614cb50d1c"
JSON
{
  "data": {
    "node": {
      "_id": "65f1a2b3c4d5e6f708192a3e",
      "name": "XP over 100?",
      "type": "router",
      "order": 2,
      "continueOnFailure": false,
      "retryOnFailure": false,
      "options": {
        "executePaths": "first_matching",
        "branches": [
          { "branchName": "XP > 100", "branchType": "CONDITION", "workflowNodeIds": ["65f1a2b3c4d5e6f708192a3d"] },
          { "branchName": "XP > 100 (Copy)", "branchType": "CONDITION", "workflowNodeIds": ["65f1a2b3c4d5e6f708192a4a"] }
        ]
      }
    },
    "revision": "68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501",
    "redactedPaths": []
  }
}
curl --request POST \
  --url 'https://api.returning.ai/v1/workflow-builder/data-workflows/<workflowId>/nodes/<nodeId>/branches/<branchIndex>/duplicate' \
  --header 'Authorization: Bearer <API_KEY>'

Response#

HTTP 201 with the router step and the workflow's new revision. The response is the readback: the copied branch is the last entry in options.branches, with a (Copy) suffix and its own member ids.

Read GET /{workflowId} to see the copied steps nested under the new branch. They carry new ids, so anything that referenced the originals still points at the originals.

data#object
One step with the workflow revision it left behind.

Eg{ ... }

node#object
A step as returned by the API.

Eg{ ... }

_id#string
Step identifier.

Eg"65f1a2b3c4d5e6f708192a3c"

name#string
Step name.

Eg"XP over 100?"

type#string
Step type.

Eg"router"

order#integer
Position on the main line, from 1.

Eg1

continueOnFailure#boolean
Whether a failure stops the run.

Egfalse

retryOnFailure#boolean
Whether the step is retried on failure.

Egfalse

options#object
Stored step options, with every credential replaced by ["__REDACTED__"].

RuleNullable

Eg{ ... }

status#string
Last run state of the step, when one exists.

Eg"success"

nestedNodes#object[]
Present on a router: each branch carries its own workflowNodeIds and nestedNodes.
revision#string
Revision after the write.

Eg"68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501"

redactedPaths#string[]
Credential locations replaced in this response.

Eg[]

{
  "data": {
    "node": {
      "_id": "65f1a2b3c4d5e6f708192a3c",
      "name": "XP over 100?",
      "type": "router",
      "order": 1,
      "continueOnFailure": false,
      "retryOnFailure": false,
      "options": {
        "executePaths": "first_matching",
        "branches": [
          {
            "branchName": "XP > 100",
            "branchType": "CONDITION",
            "workflowNodeIds": []
          },
          {
            "branchName": "XP > 100 (Copy)",
            "branchType": "CONDITION",
            "workflowNodeIds": []
          }
        ]
      }
    },
    "revision": "68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501",
    "redactedPaths": []
  }
}

Errors#

Fix the request04

400VALIDATION_FAILEDFix the request
The step is not a router, or an id is malformed. Use a router step and valid ids.
401AUTHENTICATION_REQUIREDFix the request
No key, or an unknown key. Send a valid key.
401API_KEY_REQUIREDFix the request
A valid admin session was used, because this API accepts community API keys only. Use a community API key.
403API_KEY_PERMISSION_DENIEDFix the request
No workflowBuilder. Grant the permission.

Fix the data04

404NODE_NOT_FOUNDFix the data
The step is not part of this workflow. Read the workflow for its step ids.
404BRANCH_NOT_FOUNDFix the data
No branch at that index. Read the router and use an existing index.
409VERSION_CONFLICTFix the data
You sent an If-Match that is not the current revision. meta.currentRevision carries the live value. Re-read and resend.
409WORKFLOW_LOCKEDFix the data
Another write to this workflow held the lock for too long, and this write was not applied. Re-read and retry.

Retry with backoff03

429RATE_LIMITEDRetry with backoff
The community's API rate limit was reached. Wait for the window to reset, then retry.
500INTERNAL_ERRORRetry with backoff
Unexpected failure. Re-read the router before retrying.
503LOCK_UNAVAILABLERetry with backoff
The write lock store did not answer, so nothing was written. Retry shortly.

Retries

Not idempotent: two accepted calls create two branches. A retry after a timeout can leave a duplicate, so read the router before resending.

{
  "meta": {
    "status": "error",
    "statusCode": 400,
    "code": "VALIDATION_FAILED",
    "errors": [
      {
        "path": "params.workflowId",
        "message": "Id must be a 24 character hex string"
      }
    ],
    "requestId": "3f4d0e8b-7a6c-4f1e-9b2d-5a7c8e1f0a3b"
  },
  "message": "API request rejected error.",
  "detail": "The request body is not valid.",
  "solution": "Read error detail and try again."
}

Next step#

Validate a stored workflowPOST/v1/workflow-builder/data-workflows/{workflowId}/validate