Conversation Flows
A conversation flow is a branching, action-driven script that the platform runs as a conversation with a member or prospect. The same flow runs on WhatsApp (driven by inbound webhooks) and on the web chat (driven by the public /api/public/chat/* endpoints) — so you build the flow once and it works wherever you publish it.
When to use it
- A welcome / onboarding flow that registers a new member, asks for consent, and points them at the loyalty program.
- A campaign entry flow that collects a receipt, validates it, and runs an instant-win spin.
- A cashback claim flow that walks the member through uploading evidence and choosing a payout method.
- Any conversational micro-product that's too rich for a single web form but too small to be a standalone app.
How it works
A flow is a directed graph of nodes. Each node either sends a message (text, buttons, list, image, video, document, audio, CTA URL) or runs an action (the action types are listed below). Transitions between nodes match on button id, exact text, or a wildcard.
When a member sends a message or taps a button, the flow interpreter:
- Locks the per-sender thread (so two simultaneous webhook deliveries can't race).
- Looks at the current node, picks the matching transition, and walks to the next node.
- Sends any outbound messages, runs any actions.
- Records a funnel event so you can observe the conversion path.
- Releases the lock.
If a member sends free text that doesn't match any transition, the flow falls back to the AI fallback handler (an LLM-backed responder) — useful for FAQs and small talk that don't deserve their own branch.
The flow editor
Flows live under Communications → Flows. The editor opens as a fullscreen modal with three panes:
- Canvas — drag nodes around, draw transitions, pinch-to-zoom.
- Inspector — collapsible side panel that edits the selected node's properties.
- Library — your saved flows, plus a template gallery.
Persistent cards — node cards stay where you put them across reloads, so a complex flow stays readable.
Template gallery
The template gallery contains built-in flow templates you can drop in and customise. Current set:
- welcome — onboard a new contact: greet, ask for opt-in, register member.
- registration_earn — register a new member and award welcome points.
- cashback_claim — collect a receipt, route to the cashback engine, deliver disbursement status.
- evidence_only — collect a receipt for human review, no automatic payout.
- evidence_capture — same as evidence_only with light annotation.
- instantwin_spin — accept an entry and run the instant-win spin.
- nps_survey_placeholder — outline for an NPS survey flow.
- post_purchase_upsell_placeholder — outline for a post-purchase nudge.
Templates are versioned in code and ship with default languages (Spanish, English, Italian, French). Pick one, click Instantiate, and the editor opens with a working draft you can rename and customise.
Action types
Actions are the work-doing nodes — they don't send messages, they change state. The most useful:
| Action | What it does |
|---|---|
register_member | Create a member (or look one up) by phone and email. |
register_participant | Enrol the contact in the active campaign for raffle/draws. |
accept_terms | Record a MemberConsent row tied to the active Terms version. Use before any data-collection step in regulated markets. |
award_points | Earn points for the member through the loyalty engine (multipliers apply). |
redeem_pin | Validate a PIN code the member typed; on success, consume the PIN and award its prize. |
add_to_segment | Tag the member with a segment (e.g. cashback-eligible). |
assign_to_campaign | Mark the member as a participant in a campaign. |
launch_instantwin_game | Run the instant-win lottery; send the outcome to the next node. |
verify_age | Block under-18s (or your configured min age). |
verify_geofence | Check the contact is in the allowed countries — phone prefix + IP cross-check (see below). |
verify_postal_code | Confirm the contact's postal code matches the campaign's allowed list. |
set_phone_from_input | Capture the phone number from the most recent text input. |
store_input | Store the most recent text into a flow variable. |
send_form_link | Send a one-time link to a web form (e.g. data collection). |
show_data_confirmation | Echo what you've collected so the contact can confirm. |
route_by_channel | Branch based on whether the conversation is on WhatsApp or web chat. |
auto_continue | Move forward automatically (no member input required). |
close_conversation | End the thread cleanly and reset state. |
Step-by-step
Pick a template
- Go to Communications → Flows and click Create flow.
- Open the Template gallery and pick the closest match.
- Click Instantiate. The editor opens on the new flow.
Customise
- Click a node to edit it in the inspector pane. Change message text, button labels, action parameters.
- Drag a node from the palette to add new branches.
- Save. The flow lives in Draft until you publish.
Publish
- Set the flow's Status to Active.
- Link the flow to a delivery surface:
- WhatsApp: in the channel configuration, pick this flow as the inbound handler (or trigger on specific keywords).
- Web chat: configure Trigger keywords so the public
/api/public/chat/startendpoint can find it by name or keyword.
Test
For WhatsApp, the platform has a simulate-inbound panel in dev mode so you can play through a flow without sending real messages. For web chat, hit the public endpoint with flowSlug to start a session and walk through it.
Limits and gotchas
- One active conversation per sender at a time. The per-sender lock prevents races; if two webhooks arrive in the same second, the second one waits.
- Free text falls back to the AI handler when no transition matches. If you don't want an AI fallback (regulated industries, simple flows), add a catch-all transition that routes to a "I didn't understand" node.
- Templates ship in code. New templates are added by engineering, not via UI — but the gallery list will grow.
accept_termsrequires an activeTermsVersionfor the tenant. If no version is active, the action throws.- Funnel observability: every action records a
FunnelEvent. Check the funnel dashboard to see where flows drop off. - Permission:
Pages.Communications.Flows.