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.
