{"workflow":{"id":13697,"name":"Send WhatsApp appointment reminders and reschedule bookings with Wati and Google Sheets","views":193,"recentViews":1,"totalViews":193,"createdAt":"2026-02-25T09:59:02.564Z","description":"Streamline your clinic's operations with a fully automated patient communication system. This workflow manages the entire appointment lifecycle—from automated morning reminders to real-time confirmations and self-service rescheduling—all through WhatsApp using WATI and Google Sheets.\n\n---\n\n## 🎯 What This Workflow Does\n\nTurns WhatsApp into a 24/7 automated medical receptionist:\n\n- 📝 **Automated Reminder Dispatch**  \n  A scheduled trigger runs daily at 9 AM to identify upcoming appointments and send personalized WhatsApp reminders.\n\n- 🚦 **Smart Patient Routing**  \n  A Switch node detects patient replies and triggers the correct operational path:\n  - **confirm:** Marks the appointment as confirmed in the database.\n  - **cancel:** Updates the status to cancelled and alerts the clinic.\n  - **reschedule:** Initiates the automated slot-selection flow.\n  - **myappointment:** Provides the patient with their full booking history.\n\n- 👁️ **Self-Service Rescheduling**  \n  The bot reads available time slots from Google Sheets, presents them as a numbered list, and handles the booking update automatically once a patient picks a slot.\n\n- 📊 **Live Database Synchronization**  \n  Every action—confirmation, cancellation, or time change—is instantly updated in Google Sheets, ensuring the clinic staff always sees the latest status.\n\n---\n\n## ✨ Key Features\n\n- **Morning \"Pulse\" Check:** Automatically filters today’s and tomorrow’s appointments to ensure high attendance rates.\n- **Slot Memory:** Uses a \"Reschedule Session\" tab to maintain chat context, allowing patients to simply type `slot 2` to rebook.\n- **Visual Appointment Cards:** Sends patients a clean summary of their upcoming and past visits with status emojis (✅, ⏳, 🔁).\n- **Admin Alerting (Optional):** Built-in logic to notify doctors or administrators via WhatsApp for any schedule changes.\n- **Zero-Friction Updates:** Patients manage their bookings without downloading an app or calling the front desk.\n\n---\n\n## 💼 Perfect For\n\n- **Medical Clinics:** Reducing \"no-shows\" with automated 24-hour reminders.\n- **Dental Practices:** Allowing patients to easily reschedule cleanings via chat.\n- **Wellness & Spas:** Managing therapist availability and booking confirmations.\n- **Professional Services:** Automating client reminders for consultations or coaching sessions.\n\n---\n\n## 🔧 What You'll Need\n\n### Required Integrations\n\n- **WATI** – To trigger reminders and receive patient responses.\n- **Google Sheets** – To serve as the master database for appointments and available slots.\n\n### Optional Customizations\n\n- **Google Calendar Sync:** Although current logic is Sheets-based, you can add nodes to sync these updates to a visual doctor's calendar.\n- **AI Triage:** Add an OpenAI node to understand patient questions that fall outside of standard commands.\n\n---\n\n## 🚀 Quick Start\n\n1. **Import Template** – Copy the JSON and import it into your n8n instance.\n2. **Set Credentials** – Connect your WATI and Google Sheets accounts.\n3. **Configure Sheets** – Ensure your Google Sheet has three tabs:\n\n   **Appointments:**  \n   `appointmentId`, `phone`, `patientName`, `doctorName`, `appointmentDate`, `appointmentTime`, `clinicName`, `status`\n\n   **AvailableSlots:**  \n   `slotId`, `date`, `time`, `doctorName`, `status`\n\n   **RescheduleSessions:**  \n   `phone`, `slotsData`, `createdAt`\n\n4. **Test the Flow** – Add a test row to your sheet and manually trigger the 9 AM node.\n5. **Simulate a Reply** – Reply `confirm` or `reschedule` to your WATI number to see the database update live.\n\n---\n\n## 🎨 Customization Options\n\n- **Urgency Tags:** The workflow automatically flags appointments happening TODAY in red for higher visibility.\n- **Doctor Specificity:** Filter slot availability by specific doctor names if your clinic has multiple practitioners.\n- **Flexible Matching:** Uses phone number matching to ensure patients only see and edit their own private records.\n\n---\n\n## 📈 Expected Results\n\n- 30–50% reduction in appointment \"no-shows\" through proactive reminders.\n- Faster re-booking: Cancellations are instantly replaced by rescheduling requests.\n- Staff efficiency: Front desk spends less time on the phone and more time on patient care.\n- Accurate records: Eliminates manual data entry errors by having the patient confirm their own status.\n\n---\n\n## 🏆 Use Cases\n\n### High-Volume Clinics\nA multi-doctor clinic sends 100+ reminders every morning; patients confirm via chat, and the staff arrives to a perfectly updated \"Confirmed\" list in Sheets.\n\n### Out-of-Hours Rebooking\nA patient realizes at 10 PM they can’t make it; they type `reschedule` and pick a new time for next week without waiting for the clinic to open.\n\n### Booking Verification\nA patient forgets their visit time and simply types `myappointment` to receive an instant digital summary card.\n\n---\n\n## 💡 Pro Tips\n\n- **International Formats:** Always ensure phone numbers in your Sheets include the country code for reliable WATI delivery.\n- **Slot Maintenance:** Keep your AvailableSlots tab updated with future dates to ensure the bot always has options to offer.\n- **Status Check:** If the bot doesn't respond, ensure the WATI Trigger node is active and the webhook URL is correctly registered in your WATI dashboard.\n\n---\n\nReady to automate your clinic's schedule? Import this template and connect your Google Sheets to start reducing no-shows today!","workflow":{"meta":{"instanceId":"277842713620d9f5554de3b1518b865a152c8c4db680008bd8aec536fc18b4a8","templateCredsSetupCompleted":true},"nodes":[{"id":"587768b6-db4d-4cb8-91f9-defc74f86a98","name":"📋 Flow Overview","type":"n8n-nodes-base.stickyNote","position":[-1664,-464],"parameters":{"width":660,"height":802,"content":"## 🏥 WhatsApp Appointment Reminder System with Rescheduling\n\n**How it works:**\n1. A scheduled trigger runs every morning and reads today's + tomorrow's appointments from Google Sheets\n2. Automated reminder messages are sent via WATI to each patient\n3. Patient replies *confirm*, *cancel* or *reschedule* directly on WhatsApp\n4. If rescheduling → bot shows available slots → patient picks one → Google Sheets updated\n5. Doctor/admin gets notified of any cancellations or reschedules\n6. Patient can also type *myappointment* anytime to check their booking\n\n**Credentials needed:** WATI, OpenAI API Key (Header Auth), Google Sheets OAuth2, Google Calendar OAuth2"},"typeVersion":1},{"id":"4eb92018-6466-4079-9175-82b3965ff326","name":"Sticky – Scheduled Reminders","type":"n8n-nodes-base.stickyNote","position":[1600,896],"parameters":{"color":7,"width":1264,"height":386,"content":"### 1️⃣ Scheduled Reminder Dispatch\n**Schedule Trigger** fires every morning at 9 AM.\n**Sheets – Read Appointments** fetches all appointments for today and tomorrow.\n**Filter Upcoming Code** keeps only confirmed/pending appointments within 24 hours.\n**Send Reminders Loop** sends a personalised reminder to each patient via WATI with confirm/cancel/reschedule options."},"typeVersion":1},{"id":"0ffa61fa-5bc4-430a-b338-cfa73cfdb9a5","name":"Sticky – Inbound Routing","type":"n8n-nodes-base.stickyNote","position":[-672,736],"parameters":{"color":7,"width":672,"height":722,"content":"### 2️⃣ Inbound Reply Routing\n**WATI Trigger** receives patient replies.\n**Route Message Switch** detects the reply keyword:\n- `confirm` → mark confirmed in Sheets + send confirmation\n- `cancel` → mark cancelled + notify admin\n- `reschedule` → show available slots\n- `myappointment` → show current booking details\n- `slot <number>` → book the selected slot\n- anything else → help message"},"typeVersion":1},{"id":"cc1be22d-b584-4126-add9-8e7d74486051","name":"Sticky – Confirm & Cancel","type":"n8n-nodes-base.stickyNote","position":[240,256],"parameters":{"color":7,"width":1024,"height":578,"content":"### 3️⃣ Confirm & Cancel\n**Confirm Flow:** Reads patient's appointment → updates status to Confirmed in Sheets → updates Google Calendar event → sends warm confirmation message.\n**Cancel Flow:** Updates status to Cancelled → removes/updates Google Calendar event → notifies admin via WATI → sends cancellation confirmation to patient."},"typeVersion":1},{"id":"f6b88221-1a95-47fc-bb8a-0aedcf2db192","name":"Sticky – Reschedule","type":"n8n-nodes-base.stickyNote","position":[240,880],"parameters":{"color":7,"width":1036,"height":610,"content":"### 4️⃣ Reschedule Flow\n**Show Slots Code** reads available time slots from Sheets (AvailableSlots tab), filters out already-booked ones and sends a numbered list to patient.\n**Slot Selection Code** parses *slot 2* reply, validates availability, updates Sheets with new datetime, updates Google Calendar event, sends new confirmation."},"typeVersion":1},{"id":"6b67e5a5-2c05-4d16-b9ec-aee0d34585c5","name":"Sticky – Status & Admin","type":"n8n-nodes-base.stickyNote","position":[256,1536],"parameters":{"color":7,"width":852,"height":340,"content":"### 5️⃣ My Appointment & Admin Notify\n**My Appointment Flow:** Reads Sheets for this patient's phone → sends current booking details card.\n**Admin Notify:** On cancel or reschedule, sends a summary message to the admin/doctor's WhatsApp number configured in the workflow."},"typeVersion":1},{"id":"3caddb03-b62c-40e1-b18c-c540ffa91ac5","name":"Schedule Trigger – 9AM Daily","type":"n8n-nodes-base.scheduleTrigger","position":[1696,1056],"parameters":{"rule":{"interval":[{"field":"hours","hoursInterval":24}]}},"typeVersion":1.2},{"id":"b5cd7697-4ea0-4560-b04e-d27e72e934e5","name":"Google Sheets – Read Appointments","type":"n8n-nodes-base.googleSheets","position":[1936,1056],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"8c629765-fb0c-4f8b-8f79-0e6a89ae34d3","name":"Filter Upcoming Appointments","type":"n8n-nodes-base.code","position":[2176,1056],"parameters":{"jsCode":"// Filter Upcoming Appointments\n// Keeps only appointments scheduled for today or tomorrow\n// with status Pending or Confirmed (not already Cancelled)\n\nconst allRows = $input.all();\nconst now = new Date();\nconst todayStr = now.toISOString().split('T')[0];\n\nconst tomorrow = new Date(now);\ntomorrow.setDate(tomorrow.getDate() + 1);\nconst tomorrowStr = tomorrow.toISOString().split('T')[0];\n\nconst upcoming = allRows.filter(r => {\n  const apptDate = (r.json.appointmentDate || '').split('T')[0];\n  const status = (r.json.status || '').toLowerCase();\n  return (\n    (apptDate === todayStr || apptDate === tomorrowStr) &&\n    (status === 'pending' || status === 'confirmed')\n  );\n});\n\nif (upcoming.length === 0) {\n  return [{ json: { message: 'No upcoming appointments to remind', count: 0 } }];\n}\n\n// Return each appointment as a separate item for the loop\nreturn upcoming.map(r => ({ json: r.json }));"},"typeVersion":2},{"id":"094b69e1-deaa-40f0-90a0-084f47620302","name":"Build Reminder Message","type":"n8n-nodes-base.code","position":[2400,1056],"parameters":{"jsCode":"// Build Personalised Reminder Message\n// Creates a WhatsApp reminder with appointment details\n// and action options for the patient\n\nconst appt = $json;\n\nconst patientName = $('Google Sheets – Read Appointments').first().json.patientName|| 'Patient';\nconst phone =  $('Google Sheets – Read Appointments').first().json.phone|| '';\nconst doctorName = $('Google Sheets – Read Appointments').first().json.doctorName || 'your doctor';\nconst appointmentDate = $('Google Sheets – Read Appointments').first().json.appointmentDate || '';\nconst appointmentTime = $('Google Sheets – Read Appointments').first().json.appointmentTime || '';\nconst clinicName = $('Google Sheets – Read Appointments').first().json.clinicName || 'our clinic';\nconst appointmentId =  $('Google Sheets – Read Appointments').first().json.appointmentId|| appt.rowIndex || '';\nconst speciality = $('Google Sheets – Read Appointments').first().json.speciality || '';\n\n// Format date nicely\nlet formattedDate = appointmentDate;\ntry {\n  const d = new Date(appointmentDate);\n  formattedDate = d.toLocaleDateString('en-IN', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });\n} catch(e) {}\n\nconst isToday = appointmentDate.split('T')[0] === new Date().toISOString().split('T')[0];\nconst urgency = isToday ? '🔴 *TODAY*' : '📅 *TOMORROW*';\n\nconst lines = [\n  `👋 Hello *${patientName}!*`,\n  '',\n  `⏰ *Appointment Reminder* ${urgency}`,\n  '',\n  `🏥 *Clinic:* ${clinicName}`,\n  `👨‍⚕️ *Doctor:* ${doctorName}${speciality ? ` (${speciality})` : ''}`,\n  `📅 *Date:* ${formattedDate}`,\n  `🕐 *Time:* ${appointmentTime}`,\n  '',\n  '━━━━━━━━━━━━━━━━━━',\n  'Please reply with one of:',\n  '',\n  '✅ *confirm* – I will be there',\n  '🔁 *reschedule* – I need another time',\n  '❌ *cancel* – I need to cancel',\n  '',\n  'Reply *myappointment* to see full details.'\n];\n\nreturn {\n  json: {\n    phone,\n    patientName,\n    appointmentId,\n    reminderMessage: lines.join('\\n')\n  }\n};"},"typeVersion":2},{"id":"1105af0a-7f00-4fad-91bd-90883c730cd6","name":"Route Message","type":"n8n-nodes-base.switch","position":[-336,1024],"parameters":{"rules":{"values":[{"outputKey":"Confirm","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"1dff507b-1b33-4032-af35-569caaef849d","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"confirm"}]},"renameOutput":true},{"outputKey":"Cancel","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"b7ad7026-f9a7-4acc-a711-829d0ef3ef1c","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"cancel"}]},"renameOutput":true},{"outputKey":"Reschedule","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"22960e42-4f8e-4913-aeb9-4e6b00044e42","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"reschedule"}]},"renameOutput":true},{"outputKey":"My Appointment","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"5746e0f3-ac08-4aa0-ad12-82f5dea21fac","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"myappointment"}]},"renameOutput":true},{"outputKey":"Slot Selection","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"4ffcf9fe-51e5-4c6e-afe4-7fe4aa0bdcc4","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"slot "}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"}},"typeVersion":3},{"id":"d4537013-0a96-45cf-bedb-75e71ae772d4","name":"Google Sheets – Read for Confirm","type":"n8n-nodes-base.googleSheets","position":[352,416],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"8f8451ad-4ccd-44e0-b16f-d5c94266df73","name":"Process Confirmation","type":"n8n-nodes-base.code","position":[560,416],"parameters":{"jsCode":"// Find & Confirm Appointment\n// Finds the next upcoming appointment for this phone number\n// Returns appointment details + confirmation message\n\nconst phone =$input.first().json.phone;\nconst patientName = $input.first().json.patientName || 'Patient';\nconst allRows = $input.all();\nconst now = new Date();\n\n// Find the soonest upcoming appointment for this phone\nconst myAppts = allRows\n  .filter(r => r.json.phone === phone && ['pending','confirmed'].includes((r.json.status||'').toLowerCase()))\n  .sort((a, b) => new Date(a.json.appointmentDate) - new Date(b.json.appointmentDate));\n\nif (myAppts.length === 0) {\n  return [{ json: {\n    phone,\n    confirmMessage: `⚠️ *No upcoming appointment found.*\\n\\nReply *myappointment* to check your bookings.`,\n    hasAppointment: false\n  }}];\n}\n\nconst appt = myAppts[0].json;\nlet formattedDate = appt.appointmentDate;\ntry {\n  formattedDate = new Date(appt.appointmentDate).toLocaleDateString('en-IN', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });\n} catch(e) {}\n\nconst confirmLines = [\n  `✅ *Appointment Confirmed!*`,\n  '',\n  `Thank you, *${patientName}!* We have noted your confirmation.`,\n  '',\n  `🏥 *Clinic:* ${appt.clinicName || 'Our Clinic'}`,\n  `👨‍⚕️ *Doctor:* ${appt.doctorName || 'Your Doctor'}`,\n  `📅 *Date:* ${formattedDate}`,\n  `🕐 *Time:* ${appt.appointmentTime}`,\n  '',\n  '📍 Please arrive 10 minutes early.',\n  '📄 Bring any previous reports or prescriptions.',\n  '',\n  'See you soon! 😊'\n];\n\nreturn [{ json: {\n  phone,\n  appointmentId: appt.appointmentId || appt.rowIndex,\n  calendarEventId: appt.calendarEventId || '',\n  confirmMessage: confirmLines.join('\\n'),\n  hasAppointment: true,\n  appointmentDate: appt.appointmentDate,\n  appointmentTime: appt.appointmentTime,\n  doctorName: appt.doctorName,\n  patientName\n}}];"},"typeVersion":2},{"id":"a70d35fe-7f7d-43fc-82fc-9cbec4db162e","name":"Google Sheets – Update Status Confirmed","type":"n8n-nodes-base.googleSheets","position":[768,416],"parameters":{"columns":{"value":{"phone":"={{ $('Google Sheets – Read for Confirm').item.json.phone }}","status":"=confirm"},"schema":[{"id":"appointmentId","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"phone","type":"string","display":true,"removed":false,"required":false,"displayName":"phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"patientName","type":"string","display":true,"removed":true,"required":false,"displayName":"patientName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"doctorName","type":"string","display":true,"removed":true,"required":false,"displayName":"doctorName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"appointmentDate","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentDate","defaultMatch":false,"canBeUsedToMatch":true},{"id":"appointmentTime","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentTime","defaultMatch":false,"canBeUsedToMatch":true},{"id":"clinicName","type":"string","display":true,"removed":true,"required":false,"displayName":"clinicName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"speciality","type":"string","display":true,"removed":true,"required":false,"displayName":"speciality","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"row_number","type":"number","display":true,"removed":true,"readOnly":true,"required":false,"displayName":"row_number","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["phone"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"c47004c0-95f6-455c-a443-5fc3083a5f4f","name":"Google Sheets – Read for Cancel","type":"n8n-nodes-base.googleSheets","position":[352,656],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"51cfff13-6e93-4013-a3dc-ba9534c867e8","name":"Process Cancellation","type":"n8n-nodes-base.code","position":[608,656],"parameters":{"jsCode":"// Process Cancellation\n// Finds appointment, builds cancel + admin notification messages\n\nconst phone =  $input.first().json.phone|| $('WATI Trigger').item.json.from;\nconst patientName = $input.first().json.patientName || 'Patient';\nconst allRows = $input.all();\n\nconst myAppts = allRows\n  .filter(r => r.json.phone === phone && ['pending','confirmed'].includes((r.json.status||'').toLowerCase()))\n  .sort((a, b) => new Date(a.json.appointmentDate) - new Date(b.json.appointmentDate));\n\nif (myAppts.length === 0) {\n  return [{ json: {\n    phone,\n    cancelMessage: `⚠️ *No upcoming appointment found to cancel.*`,\n    adminMessage: '',\n    hasAppointment: false\n  }}];\n}\n\nconst appt = myAppts[0].json;\nlet formattedDate = appt.appointmentDate;\ntry {\n  formattedDate = new Date(appt.appointmentDate).toLocaleDateString('en-IN', { weekday: 'long', month: 'long', day: 'numeric' });\n} catch(e) {}\n\nconst cancelLines = [\n  `❌ *Appointment Cancelled*`,\n  '',\n  `We have cancelled your appointment, *${patientName}.*`,\n  '',\n  `🗑️ *Cancelled:* ${appt.doctorName || 'Doctor'} on ${formattedDate} at ${appt.appointmentTime}`,\n  '',\n  'If you wish to rebook, send *courses* or contact us directly.',\n  'We hope to see you again soon! 🙏'\n];\n\nconst adminLines = [\n  `🚨 *Appointment Cancelled*`,\n  '',\n  `👤 *Patient:* ${patientName}`,\n  `📞 *Phone:* ${phone}`,\n  `👨‍⚕️ *Doctor:* ${appt.doctorName || 'N/A'}`,\n  `📅 *Date:* ${formattedDate}`,\n  `🕐 *Time:* ${appt.appointmentTime}`,\n  '',\n  'Slot is now available for rebooking.'\n];\n\nreturn [{ json: {\n  phone,\n  patientName,\n  appointmentId: appt.appointmentId || '',\n  calendarEventId: appt.calendarEventId || '',\n  cancelMessage: cancelLines.join('\\n'),\n  adminMessage: adminLines.join('\\n'),\n  hasAppointment: True\n}}];"},"typeVersion":2},{"id":"2712317e-a6c7-4c90-b239-0661081c7f44","name":"Google Sheets – Update Status Cancelled","type":"n8n-nodes-base.googleSheets","position":[816,656],"parameters":{"columns":{"value":{"phone":"={{ $json.phone }}"},"schema":[{"id":"appointmentId","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"phone","type":"string","display":true,"removed":false,"required":false,"displayName":"phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"patientName","type":"string","display":true,"removed":true,"required":false,"displayName":"patientName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"doctorName","type":"string","display":true,"removed":true,"required":false,"displayName":"doctorName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"appointmentDate","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentDate","defaultMatch":false,"canBeUsedToMatch":true},{"id":"appointmentTime","type":"string","display":true,"removed":true,"required":false,"displayName":"appointmentTime","defaultMatch":false,"canBeUsedToMatch":true},{"id":"clinicName","type":"string","display":true,"removed":true,"required":false,"displayName":"clinicName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"speciality","type":"string","display":true,"removed":true,"required":false,"displayName":"speciality","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"row_number","type":"number","display":true,"removed":true,"readOnly":true,"required":false,"displayName":"row_number","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["phone"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"c4af005b-b3c6-403c-a615-9374cac32c95","name":"Google Sheets – Read Available Slots","type":"n8n-nodes-base.googleSheets","position":[368,1024],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":658324122,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=658324122","cachedResultName":"Available Slots"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"5a32891a-5e54-496d-8929-a13e6151ab0a","name":"Build Available Slots","type":"n8n-nodes-base.code","position":[624,1024],"parameters":{"jsCode":"// Build Available Slots Message\n// Reads AvailableSlots sheet, filters out booked slots\n// Sends a numbered list to the patient\n\nconst phone = $('Wati Trigger').first().json.waId || $('WATI Trigger').item.json.from;\nconst patientName =  $('Wati Trigger').first().json.senderName|| 'Patient';\nconst allSlots = $input.all();\n\n// Filter only available (not booked) slots in the future\nconst now = new Date();\nconst availableSlots = allSlots.filter(r => {\n  const slotDate = new Date(`${r.json.date} ${r.json.time}`);\n  return (r.json.status || '').toLowerCase() === 'available' && slotDate > now;\n}).slice(0, 8); // show max 8 slots\n\nif (availableSlots.length === 0) {\n  return [{ json: {\n    phone,\n    slotsMessage: `⚠️ *No available slots right now.*\\n\\nPlease call us directly to reschedule.\\n📞 Contact: YOUR_CLINIC_PHONE`,\n    slots: []\n  }}];\n}\n\nconst lines = [\n  `🔁 *Reschedule Appointment*`,\n  `Hi *${patientName}*, here are the available slots:`,\n  ''\n];\n\nconst slotsData = [];\nfor (let i = 0; i < availableSlots.length; i++) {\n  const s = availableSlots[i].json;\n  let formattedDate = s.date;\n  try {\n    formattedDate = new Date(s.date).toLocaleDateString('en-IN', { weekday: 'short', month: 'short', day: 'numeric' });\n  } catch(e) {}\n  lines.push(`*${i + 1}.* 📅 ${formattedDate} at 🕐 ${s.time} — Dr. ${s.doctorName || 'Available'}`);\n  slotsData.push({ index: i + 1, date: s.date, time: s.time, doctorName: s.doctorName, slotId: s.slotId || `${s.date}_${s.time}` });\n}\n\nlines.push('');\nlines.push('Reply *slot <number>* to confirm.');\nlines.push('Example: *slot 2*');\n\n// Store slots data as JSON string for next step\nreturn [{ json: {\n  phone,\n  patientName,\n  slotsMessage: lines.join('\\n'),\n  slotsData: JSON.stringify(slotsData)\n}}];"},"typeVersion":2},{"id":"0dc22898-bdf1-4bee-9a16-243edc5c9422","name":"Google Sheets – Save Reschedule Session","type":"n8n-nodes-base.googleSheets","position":[880,1024],"parameters":{"columns":{"value":{"phone":"={{ $json.phone }}","createdAt":"={{ new Date().toISOString() }}"},"schema":[{"id":"phone","type":"string","display":true,"required":false,"displayName":"phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Slotsdate","type":"string","display":true,"removed":false,"required":false,"displayName":"Slotsdate","defaultMatch":false,"canBeUsedToMatch":true},{"id":"createdAt","type":"string","display":true,"required":false,"displayName":"createdAt","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":241863058,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=241863058","cachedResultName":"RescheduleSessions"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"d0c8c7c1-a871-4553-a6f5-d312617962b5","name":"Google Sheets – Read Reschedule Session","type":"n8n-nodes-base.googleSheets","position":[384,1280],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":241863058,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=241863058","cachedResultName":"RescheduleSessions"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"987860c3-237a-49d6-84b6-9ac8d70fb921","name":"Process Slot Selection","type":"n8n-nodes-base.code","position":[624,1280],"parameters":{"jsCode":"// Process Slot Selection\n// Input: 'slot 2'\n// Reads saved session, finds the slot, updates appointment\n\nconst text = ($('WATI Trigger').item.json.text || '').trim();\nconst phone = $('WATI Trigger').item.json.waId || $('WATI Trigger').item.json.from;\nconst patientName = $('WATI Trigger').item.json.senderName || 'Patient';\n\n// Parse slot number\nconst slotNum = parseInt(text.replace(/^slot\\s+/i, '').trim());\nif (isNaN(slotNum) || slotNum < 1) {\n  return [{ json: {\n    phone,\n    slotMessage: `⚠️ Invalid slot number. Reply *reschedule* to see available slots again.`,\n    success: False\n  }}];\n}\n\n// Find the most recent session for this phone\nconst allSessions = $input.all();\nconst mySessions = allSessions\n  .filter(r => r.json.phone === phone)\n  .sort((a, b) => new Date(b.json.createdAt) - new Date(a.json.createdAt));\n\nif (mySessions.length === 0) {\n  return [{ json: {\n    phone,\n    slotMessage: `⚠️ No active reschedule session found.\\nSend *reschedule* to start again.`,\n    success: False\n  }}];\n}\n\nlet slots = [];\ntry {\n  slots = JSON.parse(mySessions[0].json.slotsData || '[]');\n} catch(e) { slots = []; }\n\nconst selected = slots.find(s => s.index === slotNum);\nif (!selected) {\n  return [{ json: {\n    phone,\n    slotMessage: `⚠️ Slot *${slotNum}* not found. Send *reschedule* to see the list again.`,\n    success: False\n  }}];\n}\n\nlet formattedDate = selected.date;\ntry {\n  formattedDate = new Date(selected.date).toLocaleDateString('en-IN', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });\n} catch(e) {}\n\nconst confirmLines = [\n  `✅ *Appointment Rescheduled!*`,\n  '',\n  `Great choice, *${patientName}!* Your appointment has been updated.`,\n  '',\n  `👨‍⚕️ *Doctor:* Dr. ${selected.doctorName || 'Available'}`,\n  `📅 *New Date:* ${formattedDate}`,\n  `🕐 *New Time:* ${selected.time}`,\n  '',\n  '📍 Please arrive 10 minutes early.',\n  'Reply *myappointment* to verify your booking.',\n  '',\n  'See you soon! 😊'\n];\n\nconst adminLines = [\n  `🔁 *Appointment Rescheduled*`,\n  `👤 *Patient:* ${patientName}`,\n  `📞 *Phone:* ${phone}`,\n  `📅 *New Date:* ${formattedDate}`,\n  `🕐 *New Time:* ${selected.time}`,\n  `👨‍⚕️ *Doctor:* Dr. ${selected.doctorName || 'N/A'}`\n];\n\nreturn [{ json: {\n  phone, patientName,\n  newDate: selected.date,\n  newTime: selected.time,\n  newDoctorName: selected.doctorName,\n  slotId: selected.slotId,\n  slotMessage: confirmLines.join('\\n'),\n  adminMessage: adminLines.join('\\n'),\n  success: True\n}}];"},"typeVersion":2},{"id":"2f67337e-a68c-4c41-87f1-74015c5db23b","name":"Google Sheets – Update Rescheduled","type":"n8n-nodes-base.googleSheets","position":[880,1280],"parameters":{"columns":{"value":{"status":"Rescheduled","doctorName":"={{ $json.newDoctorName }}","appointmentDate":"={{ $json.newDate }}","appointmentTime":"={{ $json.newTime }}"},"schema":[{"id":"phone","type":"string","display":true,"required":true,"displayName":"phone","defaultMatch":true,"canBeUsedToMatch":true},{"id":"appointmentDate","type":"string","display":true,"required":false,"displayName":"appointmentDate","defaultMatch":false,"canBeUsedToMatch":false},{"id":"appointmentTime","type":"string","display":true,"required":false,"displayName":"appointmentTime","defaultMatch":false,"canBeUsedToMatch":false},{"id":"doctorName","type":"string","display":true,"required":false,"displayName":"doctorName","defaultMatch":false,"canBeUsedToMatch":false},{"id":"status","type":"string","display":true,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":false}],"mappingMode":"defineBelow","matchingColumns":["phone"]},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"89deab9b-54fa-4723-a57d-6fdfed6db894","name":"Google Sheets – Read My Appointment","type":"n8n-nodes-base.googleSheets","position":[368,1680],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit#gid=0","cachedResultName":"Appointments"},"documentId":{"__rl":true,"mode":"list","value":"1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1u_tiPHcDwuI-zCQr7kyLMYgUqvFudIkU2zQSXjoieKU/edit?usp=drivesdk","cachedResultName":"Wati - Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"db98d5c0-914a-48c7-82cf-6dd385b4c519","name":"Build My Appointment Card","type":"n8n-nodes-base.code","position":[624,1680],"parameters":{"jsCode":"// Build My Appointment Status Card\n// Shows patient's current and past appointments\n\nconst phone =  $input.first().json.phone|| $('WATI Trigger').item.json.from;\nconst patientName =  $input.first().json.patientName|| 'Patient';\nconst allRows = $input.all();\n\nconst myAppts = allRows\n  .filter(r => r.json.phone === phone)\n  .sort((a, b) => new Date(b.json.appointmentDate) - new Date(a.json.appointmentDate));\n\nif (myAppts.length === 0) {\n  return [{ json: {\n    phone,\n    myApptMessage: `📋 *No appointments found, ${patientName}!*\\n\\nPlease contact us to book an appointment.`\n  }}];\n}\n\nconst upcoming = myAppts.filter(r => ['pending','confirmed','rescheduled'].includes((r.json.status||'').toLowerCase()));\nconst past = myAppts.filter(r => ['cancelled','completed'].includes((r.json.status||'').toLowerCase())).slice(0, 3);\n\nconst lines = [`📋 *My Appointments*`, `👤 *${patientName}*`, ''];\n\nconst statusEmoji = { confirmed: '✅', pending: '⏳', rescheduled: '🔁', cancelled: '❌', completed: '🏁' };\n\nif (upcoming.length > 0) {\n  lines.push('*Upcoming:*');\n  for (const r of upcoming) {\n    let fd = r.json.appointmentDate;\n    try { fd = new Date(r.json.appointmentDate).toLocaleDateString('en-IN', { weekday: 'short', month: 'short', day: 'numeric' }); } catch(e) {}\n    const emoji = statusEmoji[(r.json.status||'').toLowerCase()] || '📅';\n    lines.push(`${emoji} *${fd}* at ${r.json.appointmentTime}`);\n    lines.push(`   Dr. ${r.json.doctorName || 'N/A'} | ${r.json.clinicName || 'Clinic'}`);\n    lines.push(`   Status: ${r.json.status}`);\n    lines.push('');\n  }\n}\n\nif (past.length > 0) {\n  lines.push('*Recent History:*');\n  for (const r of past) {\n    let fd = r.json.appointmentDate;\n    try { fd = new Date(r.json.appointmentDate).toLocaleDateString('en-IN', { month: 'short', day: 'numeric' }); } catch(e) {}\n    const emoji = statusEmoji[(r.json.status||'').toLowerCase()] || '📅';\n    lines.push(`${emoji} ${fd} – Dr. ${r.json.doctorName || 'N/A'} (${r.json.status})`);\n  }\n  lines.push('');\n}\n\nlines.push('━━━━━━━━━━━━━━━━━━');\nlines.push('Reply *confirm*, *reschedule* or *cancel* to manage your appointment.');\n\nreturn [{ json: { phone, myApptMessage: lines.join('\\n') } }];"},"typeVersion":2},{"id":"43a7f4fd-46da-4cde-aa75-6f07167ac5f3","name":"Send a text message","type":"n8n-nodes-wati.wati","position":[976,416],"parameters":{"target":"={{ $('Wati Trigger').item.json.waId }}","messageText":"={{ $('Process Confirmation').item.json.confirmMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"1394c240-f6f6-47cb-99d2-1fc1504c2939","name":"Send a text message1","type":"n8n-nodes-wati.wati","position":[1024,656],"parameters":{"target":"={{ $('Wati Trigger').item.json.waId }}","messageText":"={{ $('Process Cancellation').item.json.cancelMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"04fd6678-77d2-40c9-9e24-b15112120022","name":"Send a text message2","type":"n8n-nodes-wati.wati","position":[1088,1024],"parameters":{"target":"={{ $json.phone }}","messageText":"={{ $('Build Available Slots').item.json.slotsMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"a7036637-cf66-4a16-8975-aa8261d87770","name":"Send a text message3","type":"n8n-nodes-wati.wati","position":[1104,1280],"parameters":{"target":"={{ $('Wati Trigger').item.json.waId }}","messageText":"=hi"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"1489cd18-a11e-4ecc-b79c-a72b5a26d182","name":"Send a text message4","type":"n8n-nodes-wati.wati","position":[848,1680],"parameters":{"target":"={{ $('Wati Trigger').item.json.waId }}","messageText":"={{ $json.myApptMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"561443ba-02e2-4019-9c59-44db9af5ea9b","name":"Wati Trigger","type":"n8n-nodes-wati.watiTrigger","position":[-608,1088],"webhookId":"ceb8d7d4-0ea8-4491-9bec-89f94a3feb35","parameters":{"event":"messageReceived"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1,"alwaysOutputData":true},{"id":"2c1273ed-a893-437c-ad1c-452583ba9849","name":"Send a text message5","type":"n8n-nodes-wati.wati","position":[2608,1056],"parameters":{"target":"917024935915","messageText":"={{ $json.reminderMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1}],"pinData":{"Wati Trigger":[{"id":"699ec6370e106dedc4628caa","data":null,"text":"myappointment","type":"text","waId":"917024935915","owner":false,"created":"2026-02-25T09:51:51.3230313Z","sourceId":null,"ticketId":"699d5bece335b461449f4b91","avatarUrl":null,"eventType":"message","forwarded":false,"listReply":null,"sourceUrl":null,"timestamp":"1772013110","assignedId":null,"senderName":"Deepanshi Singhal","sourceType":7,"buttonReply":null,"operatorName":null,"statusString":"SENT","operatorEmail":null,"conversationId":"699d5becb12153808a3300f0","messageContact":null,"replyContextId":"","whatsappMessageId":"wamid.HBgMOTE3MDI0OTM1OTE1FQIAEhggQUNCQUI4NEY5NEZBMDZENzAwNERFNzdDNTVGQzlDMTAA","frequentlyForwarded":false,"interactiveButtonReply":null}]},"connections":{"Wati Trigger":{"main":[[{"node":"Route Message","type":"main","index":0}]]},"Route Message":{"main":[[{"node":"Google Sheets – Read for Confirm","type":"main","index":0}],[{"node":"Google Sheets – Read for Cancel","type":"main","index":0}],[{"node":"Google Sheets – Read Available Slots","type":"main","index":0}],[{"node":"Google Sheets – Read My Appointment","type":"main","index":0}],[{"node":"Google Sheets – Read Reschedule Session","type":"main","index":0}]]},"Process Cancellation":{"main":[[{"node":"Google Sheets – Update Status Cancelled","type":"main","index":0}]]},"Process Confirmation":{"main":[[{"node":"Google Sheets – Update Status Confirmed","type":"main","index":0}]]},"Build Available Slots":{"main":[[{"node":"Google Sheets – Save Reschedule Session","type":"main","index":0}]]},"Build Reminder Message":{"main":[[{"node":"Send a text message5","type":"main","index":0}]]},"Process Slot Selection":{"main":[[{"node":"Google Sheets – Update Rescheduled","type":"main","index":0}]]},"Build My Appointment Card":{"main":[[{"node":"Send a text message4","type":"main","index":0}]]},"Filter Upcoming Appointments":{"main":[[{"node":"Build Reminder Message","type":"main","index":0}]]},"Schedule Trigger – 9AM Daily":{"main":[[{"node":"Google Sheets – Read Appointments","type":"main","index":0}]]},"Google Sheets – Read for Cancel":{"main":[[{"node":"Process Cancellation","type":"main","index":0}]]},"Google Sheets – Read for Confirm":{"main":[[{"node":"Process Confirmation","type":"main","index":0}]]},"Google Sheets – Read Appointments":{"main":[[{"node":"Filter Upcoming Appointments","type":"main","index":0}]]},"Google Sheets – Update Rescheduled":{"main":[[{"node":"Send a text message3","type":"main","index":0}]]},"Google Sheets – Read My Appointment":{"main":[[{"node":"Build My Appointment Card","type":"main","index":0}]]},"Google Sheets – Read Available Slots":{"main":[[{"node":"Build Available Slots","type":"main","index":0}]]},"Google Sheets – Read Reschedule Session":{"main":[[{"node":"Process Slot Selection","type":"main","index":0}]]},"Google Sheets – Save Reschedule Session":{"main":[[{"node":"Send a text message2","type":"main","index":0}]]},"Google Sheets – Update Status Cancelled":{"main":[[{"node":"Send a text message1","type":"main","index":0}]]},"Google Sheets – Update Status Confirmed":{"main":[[{"node":"Send a text message","type":"main","index":0}]]}}},"lastUpdatedBy":1,"workflowInfo":{"nodeCount":32,"nodeTypes":{"n8n-nodes-base.code":{"count":7},"n8n-nodes-wati.wati":{"count":6},"n8n-nodes-base.switch":{"count":1},"n8n-nodes-base.stickyNote":{"count":6},"n8n-nodes-wati.watiTrigger":{"count":1},"n8n-nodes-base.googleSheets":{"count":10},"n8n-nodes-base.scheduleTrigger":{"count":1}}},"status":"published","readyToDemo":null,"user":{"name":"Jitesh Dugar","username":"jiteshdugar","bio":"AI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.","verified":true,"links":["https://www.linkedin.com/in/jiteshdugar"],"avatar":"https://gravatar.com/avatar/edaa3abb99806b0586dced559d0a5417f24a507e7c4464a63960f0638a4b1b90?r=pg&d=retro&size=200"},"nodes":[{"id":18,"icon":"file:googleSheets.svg","name":"n8n-nodes-base.googleSheets","codex":{"data":{"alias":["CSV","Sheet","Spreadsheet","GS"],"resources":{"generic":[{"url":"https://n8n.io/blog/love-at-first-sight-ricardos-n8n-journey/","icon":"❤️","label":"Love at first sight: Ricardo’s n8n journey"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/","icon":"🧾","label":"Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/creating-triggers-for-n8n-workflows-using-polling/","icon":"⏲","label":"Creating triggers for n8n workflows using polling"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/migrating-community-metrics-to-orbit-using-n8n/","icon":"📈","label":"Migrating Community Metrics to Orbit using n8n"},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"url":"https://n8n.io/blog/how-honest-burgers-use-automation-to-save-100k-per-year/","icon":"🍔","label":"How Honest Burgers Use Automation to Save $100k per year"},{"url":"https://n8n.io/blog/how-a-digital-strategist-uses-n8n-for-online-marketing/","icon":"💻","label":"How a digital strategist uses n8n for online marketing"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/","icon":"📈","label":"How a Membership Development Manager automates his work and investments"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Data & Storage","Productivity"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\",\"output\"]","defaults":{"name":"Google Sheets"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNS42OSAxIDUyIDE3LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0OC4yOTMgNjBIMTIuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDkgNTYuMzEyVjQuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTIuNzA3IDF6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM1LjY5IDEgNTIgMTcuMjI1SDM5LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzkuMjExIDE3LjIyNSA1MiAyMi40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTIwLjEyIDMxLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMS42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzEuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNC42OSAwIDUxIDE2LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0Ny4yOTMgNTlIMTEuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDggNTUuMzEyVjMuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTEuNzA3IDB6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM0LjY5IDAgNTEgMTYuMjI1SDM4LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzguMjExIDE2LjIyNSA1MSAyMS40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE5LjEyIDMwLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMC42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzAuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjwvZz48L3N2Zz4="},"displayName":"Google Sheets","typeVersion":5,"nodeCategories":[{"id":3,"name":"Data & Storage"},{"id":4,"name":"Productivity"}]},{"id":112,"icon":"fa:map-signs","name":"n8n-nodes-base.switch","codex":{"data":{"alias":["Router","If","Path","Filter","Condition","Logic","Branch","Case"],"resources":{"generic":[{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/build-your-own-virtual-assistant-with-n8n-a-step-by-step-guide/","icon":"👦","label":"Build your own virtual assistant with n8n: A step by step guide"},{"url":"https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/","icon":"🏷️","label":"How to automatically manage contributions to open-source projects"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.switch/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"transform\"]","defaults":{"name":"Switch","color":"#506000"},"iconData":{"icon":"map-signs","type":"icon"},"displayName":"Switch","typeVersion":3,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":834,"icon":"file:code.svg","name":"n8n-nodes-base.code","codex":{"data":{"alias":["cpde","Javascript","JS","Python","Script","Custom Code","Function"],"details":"The Code node allows you to execute JavaScript in your workflow.","resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Code"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Code","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"id":839,"icon":"fa:clock","name":"n8n-nodes-base.scheduleTrigger","codex":{"data":{"alias":["Time","Scheduler","Polling","Cron","Interval"],"resources":{"generic":[],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"trigger\",\"schedule\"]","defaults":{"name":"Schedule Trigger","color":"#31C49F"},"iconData":{"icon":"clock","type":"icon"},"displayName":"Schedule Trigger","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]}],"categories":[{"id":40,"name":"Support Chatbot"},{"id":47,"name":"AI Chatbot"}],"image":[]}}