Skip to content

Building your first flow

This guide assumes you’ve completed the Quickstart and have a workspace with WhatsApp connected. We’ll build a competition entry flow that collects a name and South African ID, validates the ID, and branches on whether the contact is over 18.

start
→ message "Welcome! Please enter the competition."
→ question "What's your full name?" → stored in full_name
→ question "Enter your ID number." → stored in sa_id
→ validation is_valid_sa_id(sa_id)
├─ valid → condition age_from_id(sa_id) >= 18
│ ├─ true → submission
│ └─ false → message "You must be 18 or older." → end
└─ invalid → message "That ID looks wrong. Try again."
→ loop back to sa_id question (max 2 retries)
  1. Create the flow shell. Flows → New flow → name it Competition entry. Open the builder.

  2. Add the opening message. Drag a Message node onto the canvas, connect it from start, and set the body:

    Welcome! Please enter the competition.
  3. Add the name question. Drag a Question node, connect from the message. Configure:

    • Prompt: What's your full name?
    • Variable name: full_name
    • Required: yes
  4. Add the ID question. Another Question node:

    • Prompt: Great. Now enter your ID number.
    • Variable name: sa_id
    • Required: yes
  5. Add validation. Drag a Validation node. Pick the built-in sa_id_checksum validator against the sa_id variable. The node automatically produces two outgoing edges: valid and invalid.

  6. Handle the invalid path. From the invalid edge, drag a Message node:

    That ID looks wrong. Try again.

    Wire its output back to the ID question. Use the Retry limit on the validation node (default 2) so the contact can’t loop forever.

  7. Add an age branch. From the valid edge, drag a Condition node. Configure:

    • Variable: sa_id
    • Operator: custom:age_from_id
    • Compare to: 18
    • Comparison: >=
  8. Submission path (18+). From the condition’s true edge, drag a Submission node. Title it Competition entry. This writes { full_name, sa_id } to the entries table.

  9. Rejection path (under 18). From the condition’s false edge, drag a Message node:

    Sorry, you must be 18 or older to enter.

    Then an End node.

  10. Preview. Click Preview in the top-right. Voxa spawns a sandbox conversation scoped to your own account — step through the flow as if you were a contact. Catch wording, variable-name, and branching bugs here before a real contact ever sees them.

  11. Publish. Click Publish. Voxa snapshots this flow as version 1 (or the next number) and marks it as the active published version. A fresh draft version is created automatically for any future edits — live conversations keep running on the version they started on.

  • Name your variables consistently. full_name, email, sa_id, address_line_1 — future-you reading an entry export will thank you.
  • Always validate free-text input. Especially emails and IDs; invalid data at collection time becomes a data-cleanup job later.
  • Use Delay sparingly. A 1–2 second pause before a follow-up question reads as natural; 10+ seconds feels broken and WhatsApp will think the contact has abandoned.
  • Keep flows small. Prefer five focused flows over one 40-node monster. Small flows are easier to version, debug, and retire.
  • Collecting sensitive personal information without a clear reason. You are the Responsible Party under POPIA / Controller under GDPR — see Voxa’s Privacy Policy.
  • Hard-coding tenant-specific literals inside flow copy. Store them in contact custom_fields or flow variables so one flow can serve many campaigns.
  • Publishing a flow without clicking Preview first.