Updated on October 25, 2026
WhatsApp Flows are single or multi-screen forms that open inside a WhatsApp chat, with text fields, option lists, dates and buttons, without sending the customer to a website. The business defines the screens in a file called Flow JSON, sends the Flow as an interactive message or a template, and receives the answers on the same messages webhook. There is no separate price for Flows: the message carrying the Flow is charged under its own category rules.
This guide covers what Flows are for, how to build a simple one, when you need an endpoint, how to send a Flow and receive the response, and which limits apply.
What Flows are for
Meta’s Flows page mentions lead generation, product recommendations and any interaction where a fixed structure is more comfortable for the customer than free-form messaging. The official guides include examples such as pre-approved loans, insurance quotes, purchase intent collection and personalized offers.
Practical cases where a Flow usually works better than loose questions in the chat:
- Lead capture and qualification: name, email, budget range and interest on one screen.
- Booking: choose a service, date and time. See automated AI scheduling on WhatsApp.
- Satisfaction surveys and NPS: a score and a comment without the customer typing numbers. See post-sale and NPS on WhatsApp.
- Support: a ticket form with category and description.
The categories a Flow can be given at creation are SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY and OTHER.
Requirements
According to the getting started guide, you need the Cloud API set up (app, WhatsApp Business Account and phone number) and, to send Flows to customers, a verified business and high message quality. You can create Flows in two ways:
- Flow Builder: in WhatsApp Manager, under Account tools → Flows. The editor shows a live preview as you edit.
- Flows API: Graph API endpoints to create a Flow, upload its JSON, publish and deprecate it.
Want to try it while you read? Create a Vectalk account and send your first message through the official API. Create free account →
Flow JSON anatomy
Flow JSON has two required properties: version (the format version) and screens. Each screen has a unique id, a layout with components and, on the last screen, terminal: true and a Footer component. The supported versions table marks 7.3 as recommended for publishing.
A single-screen lead capture Flow:
{
"version": "7.3",
"screens": [
{
"id": "LEAD",
"title": "Get in touch",
"terminal": true,
"success": true,
"data": {},
"layout": {
"type": "SingleColumnLayout",
"children": [
{ "type": "TextHeading", "text": "Tell us a bit about you" },
{ "type": "TextInput", "name": "name", "label": "Name", "input-type": "text", "required": true },
{ "type": "TextInput", "name": "email", "label": "Email", "input-type": "email", "required": true },
{
"type": "Dropdown",
"name": "interest",
"label": "Interest",
"required": true,
"data-source": [
{ "id": "plans", "title": "See the plans" },
{ "id": "support", "title": "Technical support" },
{ "id": "partnership", "title": "Partnership" }
]
},
{
"type": "Footer",
"label": "Submit",
"on-click-action": {
"name": "complete",
"payload": {
"name": "${form.name}",
"email": "${form.email}",
"interest": "${form.interest}"
}
}
}
]
}
}
]
}
The points that trip people up most:
${form.field}reads what the customer entered on the screen;${data.field}reads data you passed to the screen.- The
completeaction ends the Flow and sends thepayloadto your webhook. Meta recommends including only user-entered data and keeping the payload small, with no base64 images. navigatemoves to another screen without calling a server.data_exchangecalls your endpoint.- Some component limits:
TextInputaccepts up to 80 characters by default;Dropdownaccepts up to 200 options without images, with titles of up to 30 characters. - Fields listed in
sensitive(from version 5.1) are hidden in the summary the customer sees after submitting.
With or without an endpoint
A Flow without an endpoint is static: screens, options and navigation all live in the JSON. That covers most forms.
A Flow with an endpoint queries your server while the customer fills it in, for example to show free calendar slots or validate an ID number before moving on. Per the endpoint documentation, setup has four parts:
- Generate an RSA key pair and upload the public key to Meta, which signs it.
- Expose an HTTPS endpoint with a valid certificate that accepts POST.
- Implement encryption: each request arrives with
encrypted_flow_data,encrypted_aes_keyandinitial_vector. The AES key is encrypted with RSA-OAEP (SHA-256), the data with AES-GCM, and the response must be encrypted with the same AES key and the initialization vector with all bits flipped. - Link the endpoint to the Flow, with
data_api_versionin the JSON and the endpoint URL.
The endpoint receives requests when the Flow opens with data_exchange, when a screen is submitted with data_exchange, when the customer goes back with refresh_on_back, and periodic health checks ("action": "ping"), which must be answered with {"data": {"status": "active"}}. If a request cannot be decrypted, the endpoint should return HTTP 421.
Meta itself recommends avoiding the endpoint when it isn’t needed, since every call adds latency. To test the endpoint on your machine, the tunnel technique from testing the webhook locally works here too. Meta keeps Node.js examples in the WhatsApp-Flows-Tools repository.
Lifecycle: draft, published and health issues
| State | What it means |
|---|---|
| Draft | Being edited. Can only be sent for testing and shows a banner at the top. Can be deleted |
| Published | Can be sent to customers. Cannot be deleted, only deprecated |
| Deprecated | Can no longer be sent. Responses from older messages may still arrive |
| Throttled | Set by Meta when the endpoint or navigation is unhealthy. Sending limited to 10 messages per hour |
| Blocked | Health got worse after Throttled. Cannot be sent or opened |
Editing the JSON of a published Flow puts it back in draft; messages already sent keep the previous version. Meta keeps the last 5 versions. For big changes, the recommendation is to clone the Flow. Errors 132068 (Flow blocked) and 132069 (Flow throttled) appear when you try to send in those states; see WhatsApp API errors.
How to send a Flow
There are two paths, described in Send a Flow message.
Inside the customer service window, as an interactive message of type flow:
{
"messaging_product": "whatsapp",
"to": "15551234567",
"type": "interactive",
"interactive": {
"type": "flow",
"body": { "text": "Takes less than a minute." },
"action": {
"name": "flow",
"parameters": {
"flow_message_version": "3",
"flow_id": "FLOW_ID",
"flow_cta": "Fill in",
"flow_token": "lead-8f2c1a",
"flow_action": "navigate",
"flow_action_payload": { "screen": "LEAD" }
}
}
}
}
flow_cta is the button text (Meta advises 30 characters or less, no emoji). flow_token is an identifier you generate; it comes back in the response and is how you tell which send it belongs to, since the response does not include the Flow ID. Use unpredictable values, such as a session ID.
Outside the window, as a template with a FLOW button. When creating the template, the button points to the Flow by flow_id, flow_name or the flow_json itself, and the button text is limited to 25 characters. When sending, the button component with sub_type: "flow" can carry a flow_token and data for the first screen. The template category follows the usual rules.
Receiving the response on the webhook
When the customer taps the final button, the response arrives on the messages webhook as an interactive message of type nfm_reply:
{
"from": "15551234567",
"id": "wamid.HBgL...",
"type": "interactive",
"interactive": {
"type": "nfm_reply",
"nfm_reply": {
"name": "flow",
"body": "Sent",
"response_json": "{\"flow_token\": \"lead-8f2c1a\", \"name\": \"Maria\", \"email\": \"maria@example.com\", \"interest\": \"plans\"}"
}
}
}
response_json is a string: parse it before saving. The webhook structure is the same as for any other message.
Pricing
Meta’s pricing page has no line item for Flows. The cost depends on how the Flow was sent:
- Template with a Flow button: charged under the template’s category (marketing, utility or authentication), per delivered message.
- Interactive message inside the customer service window: a service message. Each phone number gets 1,000 free delivered service messages per month; from the 1,001st on, each message is charged.
- The customer’s response (
nfm_reply) is not charged: Meta does not charge for messages from users to businesses.
How this works with Vectalk
Vectalk exposes Flow management in its own API, using an instance token: GET /api/flows to list, POST /api/flows to create (with name, categories and an optional clone_flow_id), POST /api/flows/{flowId}/assets to upload flow.json, POST /api/flows/{flowId}/publish to publish and POST /api/flows/{flowId}/deprecate to deprecate. Details are under Create Flow and Flow assets.
Sending uses the same POST /api/messages with the interactive payload of type flow shown above, per the messages overview, and the nfm_reply response arrives on your registered webhooks in Meta’s format. Create your account at apps.vectalk.com.br/register. To send your first message from code, see how to send a message through the WhatsApp API.
Frequently asked questions
Do WhatsApp Flows cost extra?
There is no specific charge per Flow. You pay for the message that carries it, by category: a template under its own category, an interactive message in the window as a service message. The customer’s response is not charged.
Do I need a server to use Flows?
No. Flows without an endpoint work with Flow JSON alone, and the response arrives on the webhook you already use. You only need an endpoint when screens depend on data from your system while the customer fills them in.
Can I send a Flow to someone who hasn’t messaged me in 24 hours?
Yes, with an approved template that has a Flow button. Interactive flow messages can only be sent inside the customer service window.
How do I know which Flow a response came from?
The response does not include the Flow ID. Use flow_token, which you set when sending and which comes back in response_json, or add an identifier field to the complete payload.
Do Flows work on WhatsApp Web?
According to Meta’s changelog, Flows support on WhatsApp Web started rolling out in early December 2025, with no action required from businesses.
Official sources consulted on October 25, 2026: WhatsApp Flows, Get started with WhatsApp Flows, Flow JSON, Components, Implement endpoints for Flows, Lifecycle of a Flow, Send a Flow message, Flows webhooks, Flows changelog, WhatsApp Business Platform pricing, Vectalk docs: Flows.
Try the official WhatsApp API today
Create your account, generate a token and send your first message with the quick-start guide. Same payloads and webhooks as Meta's Cloud API.
