About this appointment booking request flow
Most booking conversations on WhatsApp take five to eight messages: which service, which day, morning or afternoon, which staff member, and a name for the booking. This flow collects all of it in one form the client fills out without leaving the chat, and your team gets a single structured request to confirm.
Screen one handles the booking itself. Services are a radio list with short descriptions, so clients choose the right treatment instead of typing a vague "a haircut". Screen two captures contact details and notes, and ends the flow. Because the phone number already comes with the WhatsApp message, the form does not ask for it again.
This is a static flow: it records a request rather than checking live availability. That keeps it free to run with no server, and it works well for businesses that confirm bookings manually or have flexible calendars.
Fields this flow returns
When the customer taps the final button, the complete action sends these keys back in response_json. Fields from earlier screens are pulled in with global references (${screen.SCREEN_ID.form.field}), so nothing is lost between screens.
| Key | Component | Screen | Required | Returns | Example |
|---|---|---|---|---|---|
servicehaircut, colour, facial, massage, consultation |
RadioButtonsGroup | BOOKING | Yes | item id | "facial" |
preferred_date |
DatePicker | BOOKING | Yes | YYYY-MM-DD | "2026-10-14" |
time_windowmorning, afternoon, evening |
RadioButtonsGroup | BOOKING | Yes | item id | "afternoon" |
staff_preferenceno_preference, staff_1, staff_2, staff_3 |
Dropdown | BOOKING | No | item id | "no_preference" |
full_name |
TextInput | DETAILS | Yes | string | "Alex Morgan" |
email |
TextInput (email) | DETAILS | No | string | "[email protected]" |
notes |
TextArea | DETAILS | No | string | "Sensitive skin, please use fragrance-free products." |
Optional fields the customer leaves empty may be missing from response_json or arrive empty. Treat every optional key as nullable in your handler.
Send the Appointment Booking Request flow without touching code
You do not need to be technical to use WhatsApp Flows. Connect your WhatsApp number, set the flow up in our drag-and-drop editor and send it to customers in a few clicks. No JSON, no API calls, no WhatsApp Manager.
Connect your number
Log in with Facebook and connect your WhatsApp number in a few minutes. No API keys or servers to set up.
Set up the flow
Start from a ready-made form or import this one, then drag fields in, change the wording and try it on a live phone preview. Click Publish when it looks right.
Send it anywhere
Send it from any chat in the Team Inbox, on web or mobile, send it automatically from an automation, or broadcast it to a list.
Get the answers
Every answer is saved on the customer's profile and chat, and your team can be notified the moment a form comes in.
Sample webhook payload (nfm_reply)
This is what your webhook receives when a customer submits the flow. response_json is a JSON string: parse it, then match flow_token to the record you created when you sent the message. The customer's WhatsApp number is in messages[0].from.
{
"flow_token": "bk_8f2c41",
"service": "facial",
"preferred_date": "2026-10-14",
"time_window": "afternoon",
"staff_preference": "no_preference",
"full_name": "Alex Morgan",
"email": "[email protected]",
"notes": "Sensitive skin, please use fragrance-free products."
}
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "15550001234",
"phone_number_id": "PHONE_NUMBER_ID"
},
"contacts": [
{
"profile": {
"name": "Alex Morgan"
},
"wa_id": "14155550123"
}
],
"messages": [
{
"context": {
"from": "15550001234",
"id": "wamid.SENT_FLOW_MESSAGE_ID"
},
"from": "14155550123",
"id": "wamid.INCOMING_MESSAGE_ID",
"timestamp": "1760000000",
"type": "interactive",
"interactive": {
"type": "nfm_reply",
"nfm_reply": {
"name": "flow",
"body": "Sent",
"response_json": "{\"flow_token\":\"bk_8f2c41\",\"service\":\"facial\",\"preferred_date\":\"2026-10-14\",\"time_window\":\"afternoon\",\"staff_preference\":\"no_preference\",\"full_name\":\"Alex Morgan\",\"email\":\"[email protected]\",\"notes\":\"Sensitive skin, please use fragrance-free products.\"}"
}
}
}
]
}
}
]
}
]
}
Deploy with the WhatsApp Cloud API
Prefer code over WhatsApp Manager? Save the template as appointment-booking-request.json and run these calls with a system user token that has whatsapp_business_management and whatsapp_business_messaging permissions.
1. Create the flow
curl -X POST 'https://graph.facebook.com/v23.0/{WABA_ID}/flows' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-H 'Content-Type: application/json' \
-d '{"name": "appointment_booking_request", "categories": ["APPOINTMENT_BOOKING"]}'
# => {"id": "{FLOW_ID}"}2. Upload the Flow JSON
curl -X POST 'https://graph.facebook.com/v23.0/{FLOW_ID}/assets' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-F '[email protected];type=application/json' \
-F 'name=flow.json' \
-F 'asset_type=FLOW_JSON'
# => {"success": true, "validation_errors": []}3. Publish it
curl -X POST 'https://graph.facebook.com/v23.0/{FLOW_ID}/publish' \
-H 'Authorization: Bearer {ACCESS_TOKEN}'Publishing is permanent: a published flow cannot be edited. To change it later, create a new flow (or clone it with clone_flow_id) and publish the new version.
4. Send it to a customer
Inside the 24-hour customer service window, send an interactive flow message. Outside it, create a message template with a Flow button that points to this flow, and send the template instead.
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "14155550123",
"type": "interactive",
"interactive": {
"type": "flow",
"header": {
"type": "text",
"text": "Book your next visit"
},
"body": {
"text": "Pick a service and a time that suits you. It takes less than a minute and we will confirm your slot by message."
},
"footer": {
"text": "Reply STOP to opt out"
},
"action": {
"name": "flow",
"parameters": {
"flow_message_version": "3",
"flow_token": "bk_8f2c41",
"flow_id": "YOUR_FLOW_ID",
"flow_cta": "Request appointment",
"flow_action": "navigate",
"flow_action_payload": {
"screen": "BOOKING"
}
}
}
}
}curl -X POST 'https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-H 'Content-Type: application/json' \
-d @send-appointment-booking-request.jsonWhen to send it
Keyword reply
Send it when a customer messages "book", "appointment" or "available?", so the first reply is the booking form rather than a question.
Click-to-WhatsApp ads
Ad traffic converts better when the first message is something to tap. Send the flow as the opening reply to ad conversations.
Rebooking broadcast
Attach it to a marketing template's Flow button and send it to clients whose last visit was six to eight weeks ago.
Missed-call follow-up
If you log missed calls, follow up with the flow instead of a callback so the client can book on their own schedule.
How to customise this template
- Replace the service ids (haircut, colour, facial...) with your own. Keep ids stable once live, because your webhook handler maps on them.
- Use the item description to show duration and starting price, for example "45 min, from $40". Clients pick faster when price is visible.
- If you have one staff member, delete the staff Dropdown. If you have more than 20, keep it a Dropdown: RadioButtonsGroup is capped at 20 items.
- Change the time windows to match your opening hours, or replace them with specific slots if your schedule is fixed.
Open this template in the Flow Builder to make these changes visually. The builder keeps field names unique and regenerates the completion payload for you.
Common mistakes to avoid
- Do not promise a confirmed slot in the TextBody. A static flow cannot check availability, so say "we will confirm by message".
- TextInput labels are limited to 20 characters. "Your full name as on ID" will fail validation in Meta; "Full name" will not.
- DatePicker returns YYYY-MM-DD from Flow JSON 5.0 onwards. Parse it as a date without time zone conversion, or it can shift by a day.
- Keep the flow_token unique per send (for example the booking or contact id). It is the only way to match a submission to the message you sent.
Need live availability instead of a "preferred time"?
A static flow can only collect a requested time, so your team still has to confirm it by hand. Whautomate ships a built-in appointment booking flow that reads your real services, staff and open slots, books the appointment directly and sends the confirmation. It is created and published in your WhatsApp account from an automation template, and it runs on an encrypted endpoint Whautomate hosts. There is no endpoint code for you to write.
- Live services, staff and time slots from your calendar
- Books directly, with no manual confirmation step
- Multi-location version picks the branch first
7-day free trial, no credit card required.