(302) 414-9101
1001 S Main St, STE 600, Kalispell, MT 59901
contact@zarghamlabs.com

WhatsApp Flows: How to Build Interactive In-Chat Forms for Business in 2026

What Are WhatsApp Flows?

WhatsApp Flows is a Meta feature that lets businesses embed rich, interactive UI components directly inside a WhatsApp conversation — without redirecting users to a website or external app. Think of it as a multi-screen mini-application that opens inside WhatsApp: a booking form, a product configurator, a survey, a checkout flow, or an onboarding wizard — all completed without the user ever leaving the chat.

Introduced in 2023 and significantly expanded in 2024–2026, WhatsApp Flows is now one of the most powerful features in the WhatsApp Business API. It solves the biggest friction point in conversational commerce: the drop-off that happens when users are redirected to a browser or external form.

WhatsApp Flows vs. Standard Interactive Messages

Feature Standard Buttons/Lists WhatsApp Flows
Max choices per message 3 buttons / 10 list items Unlimited (multi-screen)
Text input fields ✅ (text, email, phone, date)
Multi-step forms
Dynamic content from server ✅ (Data Exchange mode)
Form validation ✅ (required fields, regex)
Image support in UI Limited ✅ (product images, banners)

Top Use Cases for WhatsApp Flows

1. Appointment Booking

A multi-step Flow that collects service type → preferred date → preferred time slot → contact details — all inside WhatsApp. When submitted, a webhook fires to your backend, creates the booking, and sends a confirmation message. Conversion rates are dramatically higher than sending a booking link to an external website.

2. Lead Qualification Forms

Capture structured lead data — name, company, budget range, timeline, specific requirements — via a multi-screen form triggered when a prospect messages your business. The submitted data goes directly into your CRM via webhook. No chatbot back-and-forth needed for data collection.

3. Customer Support Ticket Creation

When a customer needs support, a Flow collects: issue category, order number, description, preferred resolution, and contact preference. The structured submission creates a support ticket in your system without requiring a human agent to ask 5 clarifying questions.

4. Product Configuration / Quote Request

For businesses selling configurable products (furniture, software, services), a Flow lets customers build their configuration step by step — selecting options, quantities, and specifications — generating a quote instantly upon submission.

5. Surveys and NPS Collection

Post-purchase or post-service surveys with rating scales, checkboxes, and open-text fields. WhatsApp Flows surveys achieve 40–60% completion rates vs. 5–15% for email survey links — simply because they’re native to the conversation.

How WhatsApp Flows Work: Technical Overview

A Flow is defined as a JSON document describing screens, components, and routing logic. There are two modes of operation: Static Flows (all content defined in the JSON, no server needed) and Data Exchange Flows (your server responds dynamically to screen events — useful for real-time availability checks, validation, or personalization).

Basic Flow JSON Structure

{
  "version": "6.1",
  "screens": [
    {
      "id": "APPOINTMENT_SCREEN_1",
      "title": "Book an Appointment",
      "layout": {
        "type": "SingleColumnLayout",
        "children": [
          {
            "type": "TextInput",
            "required": true,
            "label": "Full Name",
            "input-type": "text",
            "name": "full_name"
          },
          {
            "type": "TextInput",
            "required": true,
            "label": "Phone Number",
            "input-type": "phone",
            "name": "phone"
          },
          {
            "type": "Dropdown",
            "label": "Service Type",
            "name": "service_type",
            "data-source": [
              { "id": "consultation", "title": "Free Consultation" },
              { "id": "demo", "title": "Product Demo" },
              { "id": "onboarding", "title": "Onboarding Session" }
            ]
          },
          {
            "type": "DatePicker",
            "label": "Preferred Date",
            "name": "preferred_date",
            "min-date": "today",
            "max-date": "+30d"
          },
          {
            "type": "Footer",
            "label": "Next",
            "on-click-action": {
              "name": "navigate",
              "next": { "type": "screen", "name": "CONFIRMATION_SCREEN" },
              "payload": {
                "full_name": "${form.full_name}",
                "phone": "${form.phone}",
                "service_type": "${form.service_type}",
                "preferred_date": "${form.preferred_date}"
              }
            }
          }
        ]
      }
    },
    {
      "id": "CONFIRMATION_SCREEN",
      "title": "Confirm Booking",
      "terminal": true,
      "layout": {
        "type": "SingleColumnLayout",
        "children": [
          {
            "type": "TextBody",
            "text": "Please review your booking details and confirm."
          },
          {
            "type": "Footer",
            "label": "Confirm Booking",
            "on-click-action": {
              "name": "complete",
              "payload": {
                "full_name": "${screen.APPOINTMENT_SCREEN_1.full_name}",
                "service_type": "${screen.APPOINTMENT_SCREEN_1.service_type}",
                "preferred_date": "${screen.APPOINTMENT_SCREEN_1.preferred_date}"
              }
            }
          }
        ]
      }
    }
  ]
}

Deploying a Flow via the Meta API

import httpx
import json

WABA_ID = "your_waba_id"
ACCESS_TOKEN = "your_access_token"

# Step 1: Create the Flow
response = httpx.post(
    f"https://graph.facebook.com/v18.0/{WABA_ID}/flows",
    headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
    json={
        "name": "Appointment Booking Flow",
        "categories": ["APPOINTMENT_BOOKING"]
    }
)
flow_id = response.json()["id"]

# Step 2: Upload the Flow JSON
with open("flow.json") as f:
    flow_json = json.load(f)

httpx.post(
    f"https://graph.facebook.com/v18.0/{flow_id}/assets",
    headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
    files={"file": ("flow.json", json.dumps(flow_json), "application/json")},
    data={"name": "flow.json", "asset_type": "FLOW_JSON"}
)

# Step 3: Publish the Flow (after validation)
httpx.post(
    f"https://graph.facebook.com/v18.0/{flow_id}/publish",
    headers={"Authorization": f"Bearer {ACCESS_TOKEN}"}
)

print(f"Flow published: {flow_id}")

Sending a Flow to a User

# Send the Flow as an interactive message
httpx.post(
    f"https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages",
    headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
    json={
        "messaging_product": "whatsapp",
        "to": "15559876543",
        "type": "interactive",
        "interactive": {
            "type": "flow",
            "header": { "type": "text", "text": "Book Your Appointment" },
            "body": { "text": "Use the form below to schedule your session with us." },
            "footer": { "text": "Takes less than 2 minutes" },
            "action": {
                "name": "flow",
                "parameters": {
                    "flow_message_version": "3",
                    "flow_token": "unique_token_for_this_send",
                    "flow_id": flow_id,
                    "flow_cta": "Book Now",
                    "flow_action": "navigate",
                    "flow_action_payload": {
                        "screen": "APPOINTMENT_SCREEN_1"
                    }
                }
            }
        }
    }
)

Handling Flow Completion Webhooks

When a user completes a Flow, your webhook receives the submitted data as a message of type interactive with interactive.type = "nfm_reply". The response_json field contains all the form data as a JSON string:

async def handle_flow_completion(message: dict):
    if (message.get("type") == "interactive" and 
        message["interactive"]["type"] == "nfm_reply"):
        
        response_json = json.loads(
            message["interactive"]["nfm_reply"]["response_json"]
        )
        flow_token = message["interactive"]["nfm_reply"]["name"]
        
        # response_json contains all submitted form data
        print(response_json)
        # {"full_name": "Ahmed Ali", "service_type": "demo", "preferred_date": "2026-06-15"}
        
        # Create the booking, send confirmation, update CRM...
        await create_booking(response_json, flow_token)

WhatsApp Flows with Messenjo

Messenjo includes a visual Flow builder that lets you create, preview, and deploy WhatsApp Flows without writing JSON by hand. You configure screens, fields, and routing visually — Messenjo generates the Flow JSON and handles the Meta API calls, webhook reception, and CRM data routing automatically.

For businesses that need structured data collection from WhatsApp customers, Flows deployed through Messenjo consistently deliver 3–5x higher completion rates compared to chatbot-based data collection via sequential text messages.

For more on what’s possible with WhatsApp Business API, see our guides on WhatsApp message templates, setting up WhatsApp webhooks, and building WhatsApp chatbots without coding.

Leave A Comment