Add a router branch
Appends one branch to a router step.
- Method
- POST
- Path
https://api.returning.ai / v1/ workflow-builder/ data-workflows/ {workflowId}/ nodes/ {nodeId}/ branches - Permission
- workflowBuilder
- Retries
- Not idempotent: two accepted calls create two branches with the same name.
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.
| Failure | Meaning | Recovery |
|---|---|---|
400 VALIDATION_FAILED | The step is not a router, branchName is empty, or branchType is neither CONDITION nor FALLBACK | Send a branch for a router step, with both required fields. |
Behaviour#
A branch is a condition group plus the steps that run when it matches, or a fallback that runs when nothing else did.
The new branch is appended at the end of the router's branch list, and its step list starts empty. Steps are added to it with POST /{workflowId}/nodes and position: {routerNodeId, branchIndex}.
Request#
Path parameters#
Headers#
Bearer <API_KEY>.EgBearer <API_KEY>
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
Ruleapplication/json
Body#
Rule1-200 chars
Eg"Coins > 500"
CONDITION for a rule, FALLBACK for the default path.RuleCONDITION, FALLBACK
Eg"CONDITION"
AND: the runtime treats OR and WHERE groups as always true, and validate reports ROUTER_OPERATOR_UNSAFE as a warning. Send [] for a fallback.Eg[ ... ]
Watch for
- Conditions use
ANDgroups. A group withORorWHEREis stored, andPOST /{workflowId}/validatereportsROUTER_OPERATOR_UNSAFEas a warning: the runtime treats those groups as always true, so the branch fires more often than you meant. Deploy still proceeds, so useANDgroups and read the warnings. - Each condition needs an
id, akey, atype, anoperatorand avalue, all as non-empty arrays forkeyandvalue. - A branch's steps are named in
workflowNodeIds. A branch that names a step of another workflow is400 NODE_NOT_IN_WORKFLOW: that is a tenant check, not a validation warning. - A router needs at least one branch to be runnable;
POST /{workflowId}/validatereportsBRANCH_REQUIREDas a warning when it has none, and deploy still proceeds.executePathsdecides whether the first match wins or every match runs; a fallback only runs when no condition matched. - Deleting the last branch is refused, so build the replacement before removing the old one.
More examples and details
A condition branch:
curl --request POST \
--url "https://api.returning.ai/v1/workflow-builder/data-workflows/65f1a2b3c4d5e6f708192a3b/nodes/65f1a2b3c4d5e6f708192a3e/branches" \
--header "Authorization: Bearer <API_KEY>" \
--header "Content-Type: application/json" \
--header "If-Match: 162af81f5de4ff2b557a4087de9a9a73a0ed4e621f737787e35a93614cb50d1c" \
--data '{"branchName":"Coins > 500","branchType":"CONDITION","conditions":[{"id":"group-2","operator":"AND","nestedGroups":[{"id":"nested-2","operator":"AND","conditions":[{"id":"condition-2","key":["{{65f1a2b3c4d5e6f708192a3c.Total Coins}}"],"type":"number","operator":"greater_than","value":["500"]}]}]}]}'
A fallback branch, with an empty conditions array:
curl --request POST \
--url "https://api.returning.ai/v1/workflow-builder/data-workflows/65f1a2b3c4d5e6f708192a3b/nodes/65f1a2b3c4d5e6f708192a3e/branches" \
--header "Authorization: Bearer <API_KEY>" \
--header "Content-Type: application/json" \
--header "If-Match: 68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501" \
--data '{"branchName":"Otherwise","branchType":"FALLBACK","conditions":[]}'
{
"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": "Otherwise", "branchType": "FALLBACK", "workflowNodeIds": [] }
]
}
},
"revision": "68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501",
"redactedPaths": []
}
}
curl --request POST \
--url 'https://api.returning.ai/v1/workflow-builder/data-workflows/<workflowId>/nodes/<nodeId>/branches' \
--header 'Authorization: Bearer <API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"branchName": "Coins > 500",
"branchType": "CONDITION",
"conditions": [
{
"id": "group-2",
"operator": "AND",
"nestedGroups": [
{
"id": "nested-2",
"operator": "AND",
"conditions": [
{
"id": "condition-2",
"key": ["{{65f1a2b3c4d5e6f708192a3c.Total Coins}}"],
"type": "number",
"operator": "greater_than",
"value": ["500"]
}
]
}
]
}
]
}'
Response#
HTTP 201 with the router step in { node, revision, redactedPaths }, and the revision in the ETag header. The response is the readback: options.branches shows the new branch at the index you will use to add steps to it.
The branch index is its position in options.branches, counted from 0.
Eg{ ... }
Eg{ ... }
Eg"65f1a2b3c4d5e6f708192a3c"
Eg"XP over 100?"
Eg"router"
Eg1
Egfalse
Egfalse
["__REDACTED__"].RuleNullable
Eg{ ... }
Eg"success"
workflowNodeIds and nestedNodes.Eg"68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501"
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": []
}
]
}
},
"revision": "68f78253046393414dec404e5442c140bb5db0393a7d1c389ff57bba71585501",
"redactedPaths": []
}
}
Errors#
Fix the request06
VALIDATION_FAILEDFix the requestbranchName and branchType, and conditions for a condition branch.AUTHENTICATION_REQUIREDFix the requestAPI_KEY_REQUIREDFix the requestAPI_KEY_PERMISSION_DENIEDFix the requestworkflowBuilder. Grant the permission.VALIDATION_FAILEDFix the requestUNSUPPORTED_MEDIA_TYPEFix the requestapplication/json. Send the header.Fix the data04
NODE_NOT_FOUNDFix the dataBRANCH_NOT_FOUNDFix the dataVERSION_CONFLICTFix the dataIf-Match that is not the current revision. meta.currentRevision carries the live value. Re-read and resend.WORKFLOW_LOCKEDFix the dataRetry with backoff03
RATE_LIMITEDRetry with backoffINTERNAL_ERRORRetry with backoffLOCK_UNAVAILABLERetry with backoffRetries
Not idempotent: two accepted calls create two branches with the same name. A retry after a timeout can leave a duplicate branch, 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."
}