Decision Flows are the heart of KaireonAI’s decisioning engine. Each flow defines a composable pipeline of nodes (enrichment, qualification, scoring, ranking, filtering) that selects and ranks Offers for a given customer context.
Unique machine-readable key (used in the Recommend API).
name
Yes
string (1-255)
Human-readable name.
description
No
string
Flow description.
status
No
enum
draft (default), active, paused, archived.
autoAssembly
No
boolean
Auto-assemble when offers/channels change. Default true.
couplingOverride
No
"partial" | "atomic" | null
Per-flow override of the channel’s couplingMode. Resolution at decision time: flow.couplingOverride > channel.couplingMode > "partial". Use this when a single channel serves both atomic flows (e.g. email weekly digest) and partial flows (e.g. email transactional). null (default) defers to the channel.
draftConfig
No
object
Initial pipeline configuration (V2 schema). If omitted, the flow is created with a minimal default { version: 2, nodes: [], flowConfig: {} }. When provided it is validated structurally before write.
isDefault
No
boolean
When true, marks this flow as the tenant default and unsets isDefault on every other flow. The first flow in a tenant is auto-marked default regardless of this field.
Updates an existing Decision Flow. When draftConfig is provided, it is validated against the pipeline schema and goes through the pipeline validator for structural correctness.
Protected flows cannot be deleted (auto-set to true on publish).
isDefault
No
boolean
Mark this flow as the tenant default. Setting true unsets isDefault on every other flow in the tenant.
couplingOverride
No
"partial" | "atomic" | null
Per-flow override of the channel’s couplingMode. See create body table above for resolution order. Send null to clear the override and fall back to the channel’s mode.
draftConfig
No
object
Updated pipeline configuration.
rowVersion
No
integer
Optimistic concurrency control. If provided and it does not match the current rowVersion, the update is rejected with 409.
Always send rowVersion when updating draftConfig to prevent overwriting concurrent edits. On conflict, the API returns 409 with a message to refresh and retry.
Supports formulaExtras for adding personalized computed values to the response. Each extra defines a key, formula, and outputType that are evaluated per candidate at decision time.
The cascaded field indicates how many related records (if any) were also soft-deleted.
This endpoint uses soft-delete — the record is not physically removed. It is excluded from GET results by default. To include soft-deleted records, pass ?includeDeleted=true on the GET request.
When the tenant setting requirePublishApproval is true, publish is gated:
the flow must have a fresh, approvedApprovalRequest
with entityType: "decisionFlow", action: "publish", and entityId equal to
the flow’s id. Because approval-stage walking already rejects self-approval and
duplicate approvers, an approved request implies two distinct identities.One approval authorizes exactly one publish: the successful publish stamps
the approval’s approvalId onto the publishedVersions[] entry it creates, so a
second publish on the same approval is rejected as consumed. The next publish
needs a new approval.The gate fails closed — if the tenant-settings lookup errors, publish is
blocked unless a valid approval already exists. The default
(requirePublishApproval: false) keeps one-click publish for existing tenants.A blocked publish returns 422 and writes a publish_blocked audit entry:
reason is "no_approval" (no fresh approved request) or "consumed" (the most
recent approval was already used by a previous publish). The audit reason is
publish_approval_missing or publish_approval_consumed respectively.
Decision Flows use soft-delete with audit snapshots. When a flow is deleted:
The deletedAt timestamp is set (record is retained).
An audit snapshot is captured with the full state before deletion.
Updates also create audit snapshots via auditedUpdate, incrementing the rowVersion on each change. The first flow created in a tenant is automatically marked as the default (isDefault: true).To include soft-deleted flows in GET responses, add ?includeDeleted=true to the query string.
Decision Flows
Learn more about building Decision Flows in the platform UI.