cases — ordered conditions where the first match wins (see Conditions and variables). time nodes use a single to instead, and end nodes have no exit. When no case matches, the execution moves to the node’s on_no_match, or the definition-wide one if the node doesn’t declare its own.
The Node Types API returns this catalog programmatically — every parameter with defaults and bounds, generated from the same models that publish enforces.
Definition limits: at most 200 nodes, 25 cases per node, 10 effects per case, 50 declared start fields, and 512 KB of definition JSON.
start
The entry point. Exactly one per workflow, referenced byentry_node_id, and it must have at least one case. It declares the contact fields the workflow accepts — the schema that single runs and campaign uploads are validated against.
Four system fields are always accepted without declaring them:
reference_id, mobile_number, name, email. Declaring one (for example to make mobile_number required) refines the built-in rather than duplicating it.
entry.* variables — entry.loan_amount in the example — usable in any downstream condition. Typed fields are coerced at upload, so "42000" in a CSV compares numerically.
agent
Places a call with one of your Bolna voice agents and waits for it to finish.
After the call, the node writes
call.* variables and its cases branch on them:
call.status—completed,busy,no_answer,failed,voicemail,cancelled,rejected,timeout, orerrorcall.duration_s— call duration when knowncall.error— set whenstatusiserror(for examplemissing_recipientwhen the recipient variable is blank)
extraction
Exposes fields your agent extracted from the call — its dispositions — asextraction.* variables for branching.
An extraction node must directly follow its linked agent node. At publish, the field types are filled in server-side from the agent’s dispositions — numeric dispositions compare numerically.
api
Calls an external HTTP endpoint, maps values out of the response, and branches on the result.
After the request, cases branch on
response.*:
response.status— the HTTP status code as a number. A 4xx/5xx is not retried away — it reaches your cases so you decide what happens.response.<name>— everyresponse_mapentry.response.error—"transport"on DNS failure, connection refusal or timeout (noresponse.statusin that case).
time
Waits, then moves on. The only node with a single exit — it takesto instead of cases.
Exactly one of
delay or at must be set.
retry
Re-runs an earlier node on a schedule — the only legal way to close a cycle in the graph. Any other loop back upstream is rejected at publish withunbounded_cycle.
Each time the execution reaches the retry node it consumes the next attempt: waits out that entry’s schedule, then jumps back to the target. Once all attempts are consumed, the node’s
cases are evaluated instead — that’s your “gave up” path. The target therefore runs at most attempts + 1 times.
aisensy_whatsapp
Sends a WhatsApp template message through your connected AiSensy account.whatsapp.status (sent or failed), with whatsapp.message_id and whatsapp.error alongside.
end
Terminates the execution.label becomes a row in the campaign report, and the outcomes drive the success_count / failure_count / neutral_count rollups everywhere.
Next Steps
Conditions and variables
The expression language cases are written in
Node Types API
This catalog, programmatically

