Nexaflow Editor
Version: 27 October 2026. Scope: connection, templates, outbound booking notifications, inbound replies, delivery receipts and failure recovery.
This is a test procedure, not a record of completed live testing. Test against the deployed build containing the communication fixes. A passing unit test or a green “queued” toast does not prove a message reached a phone.
Use four checkpoints in order:
Use a staging clinic and synthetic patient records. Use actual consenting test handsets; do not use invented numbers that might belong to someone. Keep the clinic sender separate from patient and doctor recipient numbers. Do not use a real clinical history, diagnosis or financial transaction.
| Test asset | Setup | | --- | --- | | Clinic sender | Dedicated test Cloud API number or staging clinic number, connected to Nexaflow | | Patient A | Tester-controlled WhatsApp number; normal booking recipient | | Patient B | Second tester-controlled number; guardian and wrong-recipient tests | | Doctor A | Provider profile with a tester-controlled mobile number | | Doctor B | Different provider; preferably a different test handset | | Service | “Test consultation”, 30 minutes, INR 1,000 | | Treatment | “Test treatment course”, agreed cost INR 10,000, four instalments | | Location | “Staging clinic”, timezone Asia/Kolkata, future availability |
If handsets are limited, run recipient roles sequentially, but do at least one reschedule with different patient and doctor numbers. Otherwise a routing error is difficult to spot.
Create a test register with: case ID, build/version, clinic/module, sender phone-number ID, booking ID, action time with timezone, expected recipient, outbox ID, Meta message ID, final status, handset evidence, result and defect reference. Never record access tokens or app secrets.
For an initial transport check, Meta's developer setup provides test assets. Add and verify the recipient numbers allowed by the test setup, then send the supplied sample template from Meta's API Setup/Get Started screen. Screen labels may vary.
For a full Nexaflow test, use the actual embedded onboarding flow with a dedicated staging account/number, or an already connected staging sender. A sample message sent from Meta alone does not prove the sender is connected to Nexaflow's booking module.
For your Tech Provider setup, use the clinic account owner/admin to select the correct WhatsApp assets during onboarding. Keep the WABA/account ID, phone-number ID, and display telephone number distinct. The phone-number ID is the numeric sender identifier used by the API; it is not the telephone number.
Pass: the correct sender is selectable. Do not continue by selecting another clinic's sender.
The application endpoint is:
https://YOUR-STAGING-HOST/api/whatsapp/webhooktext
On the server, verify the deployed environment has the intended META_APP_ID, META_APP_SECRET, META_GRAPH_API_VERSION, META_WEBHOOK_CALLBACK_URL, and META_WEBHOOK_VERIFY_TOKEN. Use your existing server configuration; do not paste secrets into test records. Embedded onboarding also uses the configured signup IDs and phone-registration PIN.
messages webhook field. Nexaflow's webhook-sync action can be used to check or repair the account subscription.Hello, this is an E2E booking test to the clinic number.Pass: both inbound content and outbound status receipts reach the application. A successful webhook verification handshake alone is insufficient. If a real clinic recipient is outside the app's developer/test users, check the app's production access and the connected business assets as well.
In WhatsApp Manager, select the clinic's account, open Message Templates, create a template, choose its language and submit it for approval. Use Utility content describing a requested booking or transaction; Meta decides the final category and approval. Enter realistic synthetic examples for every variable when requested.
Current Nexaflow contract: BODY-only templates, positional variables, no header, footer or buttons. The variable count and order below must match exactly. Use the exact approved identifier and language code in Nexaflow; en and en_US are different configurations. Suggested names below are examples, not templates that already exist.
| Purpose | Suggested name | Positional parameters, in exact order |
| --- | --- | --- |
| General appointment update | booking_appointment_update | 1 event; 2 booking reference; 3 location; 4 local date/time |
| Patient registration | patient_registration_confirmation | 1 clinic; 2 patient; 3 patient ID; 4 mobile; 5 DOB |
| Walk-in booking | walk_in_booking_confirmation | 1 patient; 2 patient ID; 3 service and provider; 4 date/time; 5 location |
| Reminder | booking_reminder | 1 patient; 2 doctor; 3 date; 4 time; 5 visit instructions |
| Estimate | treatment_estimate | 1 patient; 2 treatment; 3 doctor; 4 visit date; 5 estimate; 6 clinic |
| Treatment bill | treatment_bill | 1 patient; 2 treatment; 3 total cost; 4 total paid; 5 balance; 6 payment plan |
| Payment receipt | payment_receipt | 1 patient; 2 treatment; 3 receipt number; 4 payment amount; 5 cumulative paid; 6 balance; 7 method; 8 receipt URL |
| Reschedule proposal | appointment_reschedule_proposal | 1 clinic; 2 doctor; 3 original date/time; 4 proposed date/time; 5 confirmation URL |
| Patient reschedule confirmation | Reuse booking_appointment_update | Same four parameters as general appointment update |
| Doctor reschedule confirmation | doctor_reschedule_confirmation | 1 doctor; 2 patient; 3 service; 4 new date/time; 5 location |
Patient and doctor confirmation settings can fall back to the main four-parameter appointment template. A dedicated doctor template gives clearer wording.
General appointment update — 4 variables
Appointment update: {{1}}. Reference: {{2}}. Location: {{3}}. Date and time: {{4}}. Please contact the clinic if you need assistance.text
Patient registration — 5 variables
Registration confirmed at {{1}}. Patient: {{2}}. Patient ID: {{3}}. Registered mobile: {{4}}. Date of birth: {{5}}. Please contact the clinic to correct any details.text
Walk-in appointment — 5 variables
Hello {{1}}, your appointment is registered. Patient ID: {{2}}. Service and provider: {{3}}. Date and time: {{4}}. Location: {{5}}. Please contact reception when you arrive.text
Reminder — 5 variables
Hello {{1}}, this is a reminder of your appointment with {{2}} on {{3}} at {{4}}. Visit instructions: {{5}}. Thank you.text
Estimate — 6 variables
Hello {{1}}, your requested estimate for {{2}} with {{3}}, scheduled for {{4}}, is {{5}}. Clinic: {{6}}. Please contact us if you have questions about this estimate.text
Treatment bill — 6 variables
Hello {{1}}, your bill for {{2}} has been updated. Total cost: {{3}}. Total paid: {{4}}. Balance: {{5}}. Payment plan: {{6}}. Please contact the clinic if a correction is needed.text
Receipt — 8 variables
Hello {{1}}, payment for {{2}} has been recorded. Receipt: {{3}}. Amount received: {{4}}. Total paid: {{5}}. Balance: {{6}}. Payment method: {{7}}. View your receipt: {{8}}. Thank you.text
Reschedule proposal — 5 variables
Appointment change from {{1}}: your visit with {{2}} is proposed to move from {{3}} to {{4}}. Review and confirm here: {{5}}. Your original appointment remains active until the change is confirmed.text
Doctor reschedule confirmation — 5 variables
Hello {{1}}, the appointment for {{2}}, service {{3}}, has been rescheduled to {{4}} at {{5}}. Please check your updated appointment list.text
Do not assume submission means approval. Continue only when each template needed for the next test is approved and available in the sender's account. You can start with the general template and add the remaining templates in stages.
BOOKING_WHATSAPP_ENABLED=trueenv
Restart the backend using the project's normal deployment/service process. Starting only the Vite frontend does not run the booking notification worker; the worker starts through the backend server entrypoint. It checks approximately every 10 seconds, but that is not a delivery guarantee.
Pass: the app no longer reports server sending as disabled, the sender is linked, and the notification log is available. Keep the gate restricted to your staging sender/test recipients during this exercise.
For each action, verify all three layers:
| Nexaflow status | Meaning and test action |
| --- | --- |
| pending | Queued; check worker/server gate if it persists |
| sending | Claimed by worker; do not trigger another send |
| accepted | Meta accepted the request; not yet proof of handset delivery |
| sent | Sending status reported by WhatsApp |
| delivered | Delivery reported; verify the intended handset too |
| read | Read reported when available; do not require this for every pass |
| blocked | No send attempted; inspect template, sender or configuration |
| failed | Definite provider failure; inspect error and supported retry action |
| unknown | Delivery outcome ambiguous; do not blindly resend |
| skipped | Suppressed, e.g. opt-out, superseded reminder or missed window; inspect reason |
Notifications can arrive out of order or omit intermediate states. Do not require every run to visibly show every status. Missing read alone is not a failure.
Use one future booking for most of this sequence; create fresh bookings where the scenario needs it. Record evidence after every step.
| Case | Action | Required result | | --- | --- | --- | | E01 Inbound connection | Patient A sends a greeting | Correct agent receives it; response returns to A | | E02 Registration | Register synthetic Patient A using reception/QR flow | Correct registration message, patient ID and synthetic DOB go to A | | E03 Appointment | Book with explicit WhatsApp consent | Exactly one applicable confirmation; patient, doctor, date/time and location are correct | | E04 Appointment list | Search by A's name and mobile | Name and mobile remain visible, even in filtered results | | E05 Estimate | Open payment tracker and send estimate | Exactly one estimate; amount/range and currency correct; UI says queued until real delivery | | E06 Bill | Set INR 10,000, four instalments; enable bill checkbox | Bill shows 10,000 total, 0 paid, 10,000 balance; no payment is created | | E07 First payment | Record INR 2,500 with receipt checkbox enabled | One payment and one receipt; paid 2,500, balance 7,500; receipt URL opens on A's phone | | E08 Reminder | Create a booking more than 30 minutes away, then wait until the 30-minute threshold | One timely reminder; current doctor/date/time and instructions are correct | | E09 Reschedule proposal | Propose a future slot | A receives proposed time and working confirmation link; original slot is still booked | | E10 Confirm proposal | Open link and accept | Original slot released; new slot reserved; one patient and one doctor confirmation; calendars updated | | E11 Follow-up | Create another visit and manually link the ongoing treatment | Follow-up label; shared bill counted once; another instalment updates the same account | | E12 Unrelated visit | Book A with Doctor B for a different treatment | It does not show or charge the first treatment's payment account | | E13 Final payment | Pay the remaining balance on the treatment account | Correct cumulative paid, zero balance, settled status and matching receipt | | E14 Cancellation | Cancel a separate future appointment | Slot released; appropriate cancellation message; no duplicate confirmation/cancellation | | E15 Complete/no-show | Complete one visit and mark another no-show | Correct configured notification behavior and final booking states |
For E08, choose a slot around 35–40 minutes away for a 30-minute reminder, or prepare a future test slot appropriately. Do not move the production clock or lower the supported reminder lead time. A reminder more than 15 minutes late is intentionally skipped in this implementation.
Do not complete/cancel/reschedule a booking immediately after creating it during the initial confirmation test. A newer event can legitimately suppress an older unsent event. Test this suppression separately.
Have Patient A send: “I would like an appointment with Doctor A tomorrow.” Verify the agent discovers actual availability, confirms the selected slot and patient identity, obtains the required confirmation/consent and creates one booking. Verify the slot in the admin UI. Do not pass this case based on an AI reply alone.
Repeat for an unavailable slot and two testers competing for the last slot. Exactly one appointment should reserve it; the other tester should be asked to choose another slot.
Book a synthetic dependent with Patient B as guardian. Confirm the intended guardian receives notices and receipt/estimate messages, and Patient A is not notified by mistake. Change the booking contact and verify consent/contact routing is re-evaluated appropriately. Opening a link must not expose unrelated patient records.
STOP; verify acknowledgement.RECIPIENT_OPTED_OUT.START; verify acknowledgement.Use new events for step 5. Do not assume START retroactively resends previously skipped messages. Also test UNSUBSCRIBE and RESUME; ordinary sentences containing “stop” should not be interpreted as the exact opt-out command.
Test recall campaigns separately: send one recall, reply YES, verify the booking link, select an available slot, then verify the booking/campaign state. Use another recipient to test NO and a preferred-time reply.
For a reschedule proposal, use its secure confirmation URL for the deterministic end-to-end test. A generic YES reply is not proof that a specific reschedule proposal was applied. Check the Known gaps section before signing off any reply-to-confirm claim.
Run the critical outbound cases twice:
An outbound message from the clinic does not reset the customer's inbound-message window. Approved templates are the intended path for proactively sending these notifications. Changing a Nexaflow database timestamp is not a valid simulation of Meta's real messaging window.
Repeat appointment confirmation, reminder, estimate, bill, receipt and reschedule confirmation under both conditions. Add cancellation and recall to this run specifically to expose any remaining direct-text paths.
| Case | Deliberate condition | Expected result | | --- | --- | --- | | F01 | Server gate off | No actual send; financial action reports not queued, not sent | | F02 | Module WhatsApp channel off | No actual send; booking/payment still saves correctly | | F03 | Missing financial template name | Explicit configuration error; no false delivery success | | F04 | Wrong template name/language or not approved | Blocked before send; visible error in notification log | | F05 | Wrong variable count/order | Count mismatch blocked; order checked on handset against expected values | | F06 | Unlink sender or disable agent-module link | Sender rejected; no other clinic's number used | | F07 | Invalid/missing patient or doctor mobile | Explicit failure/warning; no fallback to another person's number | | F08 | Receipt delivery fails | Recorded payment and balance remain correct; do not record the payment again just to resend a receipt | | F09 | Same confirmation request retried with same idempotency key | One booking mutation and one set of applicable notifications | | F10 | Meta redelivers same inbound message/webhook | No duplicate booking/payment/proposal application | | F11 | Delivered/read callback arrives before an older sent/failed callback | Final status does not regress | | F12 | Network timeout after dispatch | Unknown outcome; no automatic duplicate resend; late callback can resolve it | | F13 | Restart or two workers claim messages | No duplicate dispatch for one queued event | | F14 | Reschedule/cancel before old reminder sends | Old reminder suppressed; future reminder uses new time | | F15 | Finish/reschedule after payment receipt is queued | Receipt is not discarded merely because appointment lifecycle changed | | F16 | Same contact used in two staging clinics | Correct sender/module handles replies, opt-out and booking links; no cross-clinic mutations | | F17 | Invalid webhook signature | Rejected; no business mutation or status update | | F18 | Status persistence failure | Webhook is not falsely acknowledged as successfully persisted |
Use controlled test fixtures for transport faults, signatures, out-of-order callbacks and worker races. Keep manual handset tests for actual delivery, identity, wording and link behavior. Never replay signed production webhooks against production as a test.
| Symptom | First checks | | --- | --- | | Sender absent in booking settings | WhatsApp number → intended agent → enabled booking-module link; owner match | | No outbox entry after financial action | Server gate, channel, dedicated template, recipient and returned error | | Pending indefinitely | Backend/worker running, sending gate, database access, worker logs | | Blocked | Exact approved template name/language, parameter contract, linked sender, opt-out reason | | Accepted but no delivery confirmation | Real handset receipt, Meta failure callbacks, webhook subscription and correct callback deployment | | Handset received it but log is stale | Signed status callbacks, sender/account/recipient/message correlation, persistence errors | | Patient got update but doctor did not | Doctor's stored mobile, selected doctor, event/channel settings and doctor outbox entry | | Nothing arrives inbound | Webhook verification AND account subscription/messages field; assigned agent; app/account access | | Receipt link fails | Public APP_URL/APP_BASE_URL, HTTPS host, route availability and receipt identity | | Works only after tester sends “Hi” | Possible direct-text dependency; repeat closed-window template test | | Wrong booking confirmed by YES | Separate recall vs reschedule context; inspect exact proposal/campaign and module scope |
For a blocked event, correct the captured template/account configuration and use the supported retry. Retrying does not rewrite the original recipient, template name or language. An event captured with the wrong values needs a deliberately corrected new notification; do not blindly repeat the financial action. Unknown outcomes are not retryable through the normal UI.
Code inspection identified these paths; the tutorial does not claim they are already live-tested:
Sign off only when:
Run the unit tests after changes to communication code. Example from the repository root:
npm test -- tests/unit/TransactionalWhatsApp.test.ts tests/unit/BookingPaymentService.test.ts tests/unit/BookingRescheduleService.test.ts tests/unit/BookingCommunicationSettings.test.ts tests/unit/BookingWhatsAppDelivery.test.ts tests/unit/BookingWhatsAppRegression.test.tsbash
Frontend checks:
cd frontend npm run test:run -- src/components/modules/booking/BookingPaymentTracker.test.tsx src/components/modules/booking/BookingReschedule.test.tsx src/components/modules/booking/BookingWhatsAppSettings.test.tsx src/components/modules/booking/BookingNotifications.test.tsxbash
Database integration tests require a dedicated DATABASE_URL_TEST and run sequentially because setup resets the test schema. Do not point the test runner at a live clinic database. Re-run the short real-handset smoke journey after deployment, sender reconnection, template changes or webhook changes.
Session 1: connection, inbound/outbound smoke, general template, registration and booking. Session 2: estimates, bills, receipts, reminders and link-based rescheduling. Session 3: guardian, STOP/START, recalls, failure recovery and isolation. Next day: closed-24-hour-window repetitions and release sign-off.
Application details above were checked against the repository; Meta screen labels and account eligibility should be verified against the current dashboard and documentation.
Help us improve the world of AI agents.
Have a custom workflow need? Our engineers are ready to help.