About this course enrollment flow
Placing a student in a group needs four things: the course, the level, the times they can attend and their age. Parents usually send these across several messages over several days, and the admin team pieces them together by scrolling. This flow collects them in one submission you can sort into groups directly.
Screen one is about the course. A Dropdown handles long course lists, the level radio uses descriptions so parents can self-assess ("can hold a simple conversation" rather than "A2"), the schedule CheckboxGroup lets families tick every slot that works, and the age group and start date complete the placement data. Screen two collects the student's name and the parent or guardian's name and email, and ends with an OptIn confirming they accept your enrolment and cancellation policy.
Asking for all workable schedules, not just one, is the detail that makes this useful. A student who can do weekday evenings or Saturday mornings can be placed in whichever group has space, which fills classes more evenly and cuts waitlists.
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 |
|---|---|---|---|---|---|
courseenglish_group, spanish_group, maths_tutoring, piano_private, guitar_group, ballet_class, hip_hop_class |
Dropdown | COURSE | Yes | item id | "spanish_group" |
student_levellevel_new, level_beginner_plus, level_intermediate, level_advanced, level_assess |
RadioButtonsGroup | COURSE | Yes | item id | "level_beginner_plus" |
schedule_preferencesched_weekday_afternoon, sched_weekday_evening, sched_saturday_morning, sched_saturday_afternoon, sched_sunday, sched_online |
CheckboxGroup | COURSE | Yes | array of ids | ["sched_weekday_evening","sched_saturday_morning"] |
age_groupage_under_7, age_7_12, age_13_17, age_adult |
RadioButtonsGroup | COURSE | Yes | item id | "age_13_17" |
start_date |
DatePicker | COURSE | Yes | YYYY-MM-DD | "2026-10-05" |
student_name |
TextInput | STUDENT_DETAILS | Yes | string | "Lucas Ferreira" |
guardian_name |
TextInput | STUDENT_DETAILS | No | string | "Ana Ferreira" |
guardian_email |
TextInput (email) | STUDENT_DETAILS | Yes | string | "[email protected]" |
policy_agreement |
OptIn | STUDENT_DETAILS | Yes | boolean | true |
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 Course Enrollment 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",
"course": "spanish_group",
"student_level": "level_beginner_plus",
"schedule_preference": [
"sched_weekday_evening",
"sched_saturday_morning"
],
"age_group": "age_13_17",
"start_date": "2026-10-05",
"student_name": "Lucas Ferreira",
"guardian_name": "Ana Ferreira",
"guardian_email": "[email protected]",
"policy_agreement": true
}
{
"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\",\"course\":\"spanish_group\",\"student_level\":\"level_beginner_plus\",\"schedule_preference\":[\"sched_weekday_evening\",\"sched_saturday_morning\"],\"age_group\":\"age_13_17\",\"start_date\":\"2026-10-05\",\"student_name\":\"Lucas Ferreira\",\"guardian_name\":\"Ana Ferreira\",\"guardian_email\":\"[email protected]\",\"policy_agreement\":true}"
}
}
}
]
}
}
]
}
]
}
Deploy with the WhatsApp Cloud API
Prefer code over WhatsApp Manager? Save the template as course-enrollment.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": "course_enrollment", "categories": ["SIGN_UP"]}'
# => {"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": "Enrolment is open"
},
"body": {
"text": "Choose a course and level, tell us which times suit you and we will place you in the right group. It takes about two minutes."
},
"footer": {
"text": "Places are limited per group"
},
"action": {
"name": "flow",
"parameters": {
"flow_message_version": "3",
"flow_token": "bk_8f2c41",
"flow_id": "YOUR_FLOW_ID",
"flow_cta": "Enrol now",
"flow_action": "navigate",
"flow_action_payload": {
"screen": "COURSE"
}
}
}
}
}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-course-enrollment.jsonWhen to send it
Term enrolment campaigns
Broadcast a Flow-button template to current and past families three to four weeks before term starts, so group sizes are known before timetables are fixed.
Trial lesson follow-up
Send the flow the evening after a trial lesson, when the student and parent are most likely to commit.
Course enquiries
Reply with the flow when someone asks about a course, levels or timetables. It answers "which group?" by collecting what you need to decide.
Level progression
At the end of term, send it to students finishing a level to enrol them into the next one before their spot is offered to new students.
How to customise this template
- Use a Dropdown for courses so you can list many (Dropdowns take up to 200 items) and keep course ids tied to your timetable system, for example spanish_group or piano_private.
- Describe each level in outcomes, not codes. Parents rarely know what "Grade 3" or "B1" means but can recognise "reads simple music" or "can order in a restaurant".
- Replace the schedule options with your real teaching blocks. If groups run only at fixed times, name the exact slot, like "Tue & Thu 5pm - 6:30pm".
- Point the policy EmbeddedLink at your real terms page, and name the essentials in the OptIn label: fees per term, notice period and missed-lesson rules.
- For adult-only schools, remove the guardian name field and the under-12 age group.
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 make the guardian name required for adult learners. Either keep it optional, as here, or send a separate adult flow, or students over 18 will abandon the form.
- An OptIn marked required blocks submission until ticked. Make sure the linked policy is reachable on mobile; a broken link means nobody can enrol.
- The student_name and guardian_name fields must stay distinct names. Field names are payload keys, and a duplicate "name" field fails Meta validation.
- Collecting data about minors carries extra obligations in many countries. Ask only what you need for placement and keep medical or safeguarding details for your formal registration form.
Sell memberships and packages in chat
When the enquiry turns into a purchase, Whautomate has a built-in buy-plan flow. Clients pick a plan, see a summary and subscribe inside WhatsApp. It is published in your account automatically and reads your live plans.
- Your real plans and pricing
- Subscription created on submit
- Single and multi-location versions
7-day free trial, no credit card required.