WhatsApp Flows: Multi-Screen Forms Inside the Chat
Collecting five pieces of information over WhatsApp usually takes ten messages. You ask for a name, wait, ask for a date, wait, ask which branch, get a voice note, ask again. Half the customers drop off before the booking is done.
WhatsApp Flows fix that by putting a real form inside the chat. The customer taps a button and gets native screens with text fields, dropdowns, date pickers and checkboxes, fills them in without leaving WhatsApp, and you get the answers back as structured JSON in one webhook.
This guide covers what Flows are good for, how they are built with Flow JSON, when you need your own endpoint, how to send a Flow and read the response, and the limits and states Meta enforces, as of October 2026.
What a Flow is, and what teams build with it
A Flow is a small app made of screens, defined in a JSON document Meta calls Flow JSON. Each screen holds components, such as text, inputs, dropdowns, date pickers, opt-in checkboxes and images, plus a footer button that moves to the next screen or completes the Flow. When the customer finishes, WhatsApp posts a summary message in the chat and sends you the data.
Meta's own starter guides are for pre-approved loan offers, insurance quotes, purchase-intent surveys and personalised offers. In practice teams use Flows for:
- Appointment booking: service, date, time slot, notes.
- Lead qualification: budget, timeline, location, consent to be contacted.
- Order and delivery issues: pick the order, describe the problem, upload a photo.
- Feedback after a visit: a rating plus a comment, tied to a specific booking.
- Account sign-up or profile completion inside the chat.
Meta's best practice is that a Flow should take under 5 minutes, with one task per screen. If a task needs 15 fields, it probably belongs on a web page.
How Flows are built
There are three ways to create one, all producing Flow JSON:
- Flow Builder in WhatsApp Manager (Account tools, then Flows). A visual editor with a live preview, the easiest place to start.
- The Flows Playground on Meta's developer site, for sketching a Flow and copying the JSON.
- The Flows API, for creating, updating, publishing and deprecating Flows from code.
A minimal one-screen booking Flow looks like this. It uses Flow JSON 7.3, which Meta lists as the recommended version as of October 2026:
{
"version": "7.3",
"screens": [
{
"id": "BOOKING",
"title": "Book a visit",
"terminal": true,
"success": true,
"data": {},
"layout": {
"type": "SingleColumnLayout",
"children": [
{ "type": "TextHeading", "text": "Pick a time that works" },
{ "type": "TextInput", "name": "full_name", "label": "Your name", "input-type": "text", "required": true },
{
"type": "Dropdown",
"name": "slot",
"label": "Preferred slot",
"required": true,
"data-source": [
{ "id": "morning", "title": "Morning, 9 am to 12 pm" },
{ "id": "afternoon", "title": "Afternoon, 12 pm to 4 pm" }
]
},
{
"type": "Footer",
"label": "Confirm booking",
"on-click-action": {
"name": "complete",
"payload": { "full_name": "${form.full_name}", "slot": "${form.slot}" }
}
}
]
}
}
]
}
The rules that matter most:
- Each screen has an
id, a layout (SingleColumnLayoutis the only one), and up to 50 components. - A terminal screen must have a
Footer, and a screen can have only one footer. - Actions are
navigate(go to another screen),data_exchange(call your endpoint),complete(finish and send the payload), plusopen_urlandupdate_datafrom Flow JSON 6.0. - Form values are referenced as
${form.field_name}, and data passed into a screen as${data.field_name}.
With or without an endpoint
The biggest design decision is whether the Flow needs live data from your server.
| Without an endpoint | With an endpoint | |
|---|---|---|
| How screens get data | Static content, or data passed in when you send the Flow | Your server answers each data_exchange request |
| Good for | Fixed forms: feedback, lead capture, sign-up | Live availability, prices, eligibility checks |
| Setup | Flow JSON only | Key pair, encryption, HTTPS endpoint, health checks, a Meta app linked to the Flow |
| Monitoring | None | Error rate, latency and availability are watched by WhatsApp |
Endpoint-powered Flows are much more work. Each request arrives encrypted: an AES key encrypted with your public key, plus the encrypted payload. You decrypt, process, and return an encrypted response. Meta's endpoint requests time out after 10 seconds, and its health guide asks you to aim for under 1 second. If decryption fails, return HTTP 421. Your endpoint must also answer periodic ping health checks.
Meta's advice is to use an endpoint only for the screens that truly need live data, and to keep the first screen endpoint-free so the Flow opens quickly. Meta publishes Node.js endpoint examples on GitHub, which save a lot of time on the encryption code.
Sending a Flow and reading the result
There are two ways to deliver a Flow, matching WhatsApp's window rule:
- Inside a customer service window: send an interactive message of type
flow. It is a service message and needs no approval. - Outside the window: create a template with a
FLOWbutton, get it approved, and send the template. Meta's sending guide also asks that you verify your business and maintain high message quality.
Here is the in-window version. The examples use v23.0; use the current Graph API version from Meta's changelog.
curl -X POST "https://graph.facebook.com/v23.0/PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $WHATSAPP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "+919811122233",
"type": "interactive",
"interactive": {
"type": "flow",
"body": { "text": "Book your visit in under a minute." },
"action": {
"name": "flow",
"parameters": {
"flow_message_version": "3",
"flow_id": "FLOW_ID",
"flow_token": "booking-cust-4821",
"flow_cta": "Book now",
"flow_action": "navigate",
"flow_action_payload": { "screen": "BOOKING" }
}
}
}
}'
The flow_token is yours to set, and it matters: the response webhook does not include the Flow ID, so the token is how you tie a completed form back to a customer, booking or campaign. Keep the call-to-action text to about 30 characters with no emoji, as Meta advises.
When the customer completes the Flow, your normal messages webhook receives an interactive message of type nfm_reply:
{
"type": "interactive",
"interactive": {
"type": "nfm_reply",
"nfm_reply": {
"name": "flow",
"body": "Sent",
"response_json": "{\"flow_token\": \"booking-cust-4821\", \"full_name\": \"Priya Sharma\", \"slot\": \"morning\"}"
}
}
}
response_json is a string, so parse it before use. Its shape comes from your complete payload, or from your endpoint's final response for endpoint-powered Flows. Our guide to WhatsApp API webhooks covers subscribing and verifying signatures.
Lifecycle, limits and gotchas
A Flow moves through states, and some are set by WhatsApp, not by you:
| State | What it means |
|---|---|
| Draft | Editable, sendable only for testing, deletable |
| Published | Live; editing returns it to Draft, and new sends use the new version |
| Deprecated | Can no longer be sent. Published Flows can't be deleted, only deprecated |
| Throttled | Set by WhatsApp when endpoint health slips: sending limited to 10 messages per hour (error 132069 beyond that) |
| Blocked | Set by WhatsApp if health worsens: no new sends, and customers can't open earlier ones (error 132068) |
Other points worth knowing before you commit:
- Versions. Meta supports the last 5 versions of a Flow, and Flow JSON versions themselves get frozen and expire, so check the supported list in the Flows changelog before publishing.
- Routing. For endpoint Flows you define a
routing_model, with a maximum of 10 branches. - Devices. Flows run on Android 6.0+ and iOS 12+. Meta's changelog says WhatsApp Web support began rolling out in December 2025.
- Pricing. Flows have no separate fee. A Flow template is billed at its template category, and an in-window Flow message as a service message.
- Library forms. Meta's Template Library includes a few ready-made Flow-powered forms, such as customer feedback and delivery failure, for accounts with raised messaging limits.
For the simpler tappable formats, see WhatsApp interactive messages, and for template mechanics, WhatsApp message templates.
Where Tenashi fits
Flows are a strong fit when you run structured, repeatable intake at volume on the official API. Tenashi doesn't build or send Flows. It is a team workspace on your own WhatsApp number, connected as a linked device rather than through Meta's API, and its API sends text, media and quoted replies only.
Where it helps is the human part around the form. If your intake form lives on your website or in an ad, Tenashi's API can message the lead from your existing number (with their consent), and their reply lands in a shared inbox where a teammate qualifies them, with the lead's details in the CRM under the chat. Our guide to sending form submissions to WhatsApp shows the pattern. Sends are paced, new chats per number are capped each day, there is no green tick, and WhatsApp can still ban numbers that spam. Pricing is flat from $18/mo. For background on both routes, see our complete guide to the WhatsApp API.
Read the API docs · Get started
FAQ
What are WhatsApp Flows used for?
Flows put multi-screen forms inside a WhatsApp chat. Businesses use them for appointment booking, lead qualification, loan or insurance quotes, delivery problem reports, feedback after a visit and profile completion. The customer fills in native fields without leaving WhatsApp, and the business receives the answers as structured JSON in a single webhook.
Do WhatsApp Flows need a server endpoint?
No. A Flow with static content, or with data you pass in when sending, needs only Flow JSON. You need an endpoint when screens depend on live data such as availability or prices. Endpoint Flows require encryption with your own key pair, fast responses, health checks, and are monitored and throttled if they degrade.
How do I receive the data from a completed Flow?
It arrives on your normal messages webhook as an interactive message of type nfm_reply. The response_json field is a JSON string containing your flow_token and the fields from your completion payload. The response does not include the Flow ID, so set a meaningful flow_token when you send the Flow.
Can I send a WhatsApp Flow outside the 24-hour window?
Yes, through a template with a FLOW button. Create the template with the Flow attached, get it approved, then send it like any template, billed at the template's category rate. Inside an open customer service window you can send the Flow directly as an interactive message, which needs no approval.
What happens if my Flow endpoint is slow or failing?
WhatsApp monitors error rate, latency and availability for endpoint Flows and sends alert webhooks first. If metrics keep worsening, the Flow becomes Throttled, limited to 10 sends per hour, then Blocked, when no one can send or open it. Once the endpoint recovers, the Flow steps back to Published automatically.
Flows handle the structured intake; your team handles the conversation that follows. For that part, get started with Tenashi.