Create a workflow
POST
/api/v1/workflows
workflows:write
MCP:
cascades_create_workflow
Creates a cascade from a JSON definition (see CascadeDefinition
for the node grammar), owned by the account behind the token.
API-created cascades default to trigger_type: manual so they can
be run through triggerWorkflow.
active defaults to true. Accounts without production access
always get a draft (active: false) — silently, with a note in
the response explaining why. Drafts can still be triggered in test
mode; only live runs need an activated cascade and an approved
account. Requires workflows:write.
Request body
The cascade to create: its name, use case and node definition.
-
namestring required -
definitionCascadeDefinition The node graph. Omit or pass `[]` to create an empty draft you fill in later. -
use_casestring Optional use case label. -
trigger_typestring API-created cascades default to `manual` so they can be triggered through this API. Unknown values fall back to `manual`. One ofmanualeventscheduled -
activeboolean Whether the cascade is immediately triggerable in live mode. Omitted or `null` means `true`; pass `false` for a draft. Accounts without production access always receive a draft regardless of this value, and the response carries a `note` explaining why.
Example request
{
"name": "Tenant Screening Standard",
"use_case": "tenant_screening",
"trigger_type": "manual",
"definition": [
{
"id": "step_applicant",
"type": "ApplicantSource",
"name": "Applicant",
"next_step": [
"step_credit"
]
},
{
"id": "step_credit",
"type": "BillingProduct",
"name": "Credit report",
"billing_product_code": "EQF1003",
"next_step": [
"step_score_check"
]
},
{
"id": "step_score_check",
"type": "IfElse",
"name": "Score at least 650?",
"branches": {
"pass": {
"condition_groups": [
{
"conditions": [
{
"source_node_id": "step_credit",
"field": "creditScore.fico9",
"operator": "greater_than_or_equal",
"value": 650
}
]
}
]
}
},
"pass_steps": [
"step_approve"
],
"fail_steps": [
"step_adverse_action"
]
},
{
"id": "step_approve",
"type": "Action",
"name": "Approve",
"action_type": "Approve"
},
{
"id": "step_adverse_action",
"type": "Action",
"name": "Adverse action",
"action_type": "AdverseAction",
"adverse_action": {
"recipient": "{{applicant.email}}",
"action_taken": "denied",
"send_strategy": "draft_first",
"reason": "Credit score below the property minimum."
}
}
]
}Responses
-
201 Created.
noteis present only when the account lacks production access and the cascade was saved as a draft.application/json-
dataWorkflow + SandboxDraftNote-
idinteger required -
objectstring required -
codestring, nullable Short human-readable code assigned by Cascades. -
namestring required -
activeboolean required `true` = activated and triggerable in live mode. Drafts (`false`) can still be triggered in test mode. -
trigger_typestring required One ofmanualeventscheduled -
use_casestring, nullable -
created_atstring (date-time) -
updated_atstring (date-time) -
notestring Present only when the account lacks production access and the cascade was therefore created as a draft.
-
-
metaMetaSchema: Meta
-
request_idstring required Correlation id for this request. Also sent as the `X-Request-Id` response header; quote it when contacting support.
-
201 example{ "data": { "id": 41, "object": "workflow", "code": "TSS-41", "name": "Tenant Screening Standard", "active": true, "trigger_type": "manual", "use_case": "tenant_screening", "created_at": "2026-09-09T14:00:00Z", "updated_at": "2026-09-09T14:00:00Z" }, "meta": { "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f" } } -
-
400
malformed_body(unparseable JSON) orbad_requestapplication/json400 example{ "error": { "code": "malformed_body", "message": "The request body could not be parsed. Send valid JSON matching the Content-Type header.", "details": [], "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f", "doc_url": "https://cascades.crscreditapi.com/docs/api/errors/malformed_body" } } -
401 Missing, malformed, expired or revoked bearer token. The
WWW-Authenticateheader carries the RFC 6750 challenge.application/json401 example{ "error": { "code": "unauthorized", "message": "A valid bearer token is required.", "details": [], "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f", "doc_url": "https://cascades.crscreditapi.com/docs/api/errors/unauthorized" } } -
403 Token does not hold the required scope.
detailslists the scope(s) that were checked.application/json403 example{ "error": { "code": "insufficient_scope", "message": "This token does not have the required scope.", "details": [ { "field": "scope", "message": "executions:write" } ], "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f", "doc_url": "https://cascades.crscreditapi.com/docs/api/errors/insufficient_scope" } } -
422
validation_failed— e.g. blankname, adefinitionthat is not an array of objects, or more than oneApplicantSourcenode.application/json422 example{ "error": { "code": "validation_failed", "message": "The workflow could not be created.", "details": [ { "field": "name", "message": "can't be blank" } ], "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f", "doc_url": "https://cascades.crscreditapi.com/docs/api/errors/validation_failed" } } -
429 Rate limit exceeded (60 req/min per IP on
/api/v1, 600 req/hour per token prefix, or 300 req/5 min per IP globally). The body is the standard error envelope andRetry-Aftergives the seconds until the window resets.application/json429 example{ "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry later.", "details": [], "request_id": "7d4c2f48-9a1b-4c3d-8e2f-1a2b3c4d5e6f", "doc_url": "https://cascades.crscreditapi.com/docs/api/errors/rate_limited" } }