{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "587768b6-db4d-4cb8-91f9-defc74f86a98",
      "name": "\ud83d\udccb Flow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1664,
        -464
      ],
      "parameters": {
        "width": 660,
        "height": 802,
        "content": "## \ud83c\udfe5 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 \u2192 bot shows available slots \u2192 patient picks one \u2192 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 \u2013 Scheduled Reminders",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1600,
        896
      ],
      "parameters": {
        "color": 7,
        "width": 1264,
        "height": 386,
        "content": "### 1\ufe0f\u20e3 Scheduled Reminder Dispatch\n**Schedule Trigger** fires every morning at 9 AM.\n**Sheets \u2013 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 \u2013 Inbound Routing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        736
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 722,
        "content": "### 2\ufe0f\u20e3 Inbound Reply Routing\n**WATI Trigger** receives patient replies.\n**Route Message Switch** detects the reply keyword:\n- `confirm` \u2192 mark confirmed in Sheets + send confirmation\n- `cancel` \u2192 mark cancelled + notify admin\n- `reschedule` \u2192 show available slots\n- `myappointment` \u2192 show current booking details\n- `slot <number>` \u2192 book the selected slot\n- anything else \u2192 help message"
      },
      "typeVersion": 1
    },
    {
      "id": "cc1be22d-b584-4126-add9-8e7d74486051",
      "name": "Sticky \u2013 Confirm & Cancel",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        256
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 578,
        "content": "### 3\ufe0f\u20e3 Confirm & Cancel\n**Confirm Flow:** Reads patient's appointment \u2192 updates status to Confirmed in Sheets \u2192 updates Google Calendar event \u2192 sends warm confirmation message.\n**Cancel Flow:** Updates status to Cancelled \u2192 removes/updates Google Calendar event \u2192 notifies admin via WATI \u2192 sends cancellation confirmation to patient."
      },
      "typeVersion": 1
    },
    {
      "id": "f6b88221-1a95-47fc-bb8a-0aedcf2db192",
      "name": "Sticky \u2013 Reschedule",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        880
      ],
      "parameters": {
        "color": 7,
        "width": 1036,
        "height": 610,
        "content": "### 4\ufe0f\u20e3 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 \u2013 Status & Admin",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        1536
      ],
      "parameters": {
        "color": 7,
        "width": 852,
        "height": 340,
        "content": "### 5\ufe0f\u20e3 My Appointment & Admin Notify\n**My Appointment Flow:** Reads Sheets for this patient's phone \u2192 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 \u2013 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 \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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 \u2013 Read Appointments').first().json.patientName|| 'Patient';\nconst phone =  $('Google Sheets \u2013 Read Appointments').first().json.phone|| '';\nconst doctorName = $('Google Sheets \u2013 Read Appointments').first().json.doctorName || 'your doctor';\nconst appointmentDate = $('Google Sheets \u2013 Read Appointments').first().json.appointmentDate || '';\nconst appointmentTime = $('Google Sheets \u2013 Read Appointments').first().json.appointmentTime || '';\nconst clinicName = $('Google Sheets \u2013 Read Appointments').first().json.clinicName || 'our clinic';\nconst appointmentId =  $('Google Sheets \u2013 Read Appointments').first().json.appointmentId|| appt.rowIndex || '';\nconst speciality = $('Google Sheets \u2013 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 ? '\ud83d\udd34 *TODAY*' : '\ud83d\udcc5 *TOMORROW*';\n\nconst lines = [\n  `\ud83d\udc4b Hello *${patientName}!*`,\n  '',\n  `\u23f0 *Appointment Reminder* ${urgency}`,\n  '',\n  `\ud83c\udfe5 *Clinic:* ${clinicName}`,\n  `\ud83d\udc68\u200d\u2695\ufe0f *Doctor:* ${doctorName}${speciality ? ` (${speciality})` : ''}`,\n  `\ud83d\udcc5 *Date:* ${formattedDate}`,\n  `\ud83d\udd50 *Time:* ${appointmentTime}`,\n  '',\n  '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501',\n  'Please reply with one of:',\n  '',\n  '\u2705 *confirm* \u2013 I will be there',\n  '\ud83d\udd01 *reschedule* \u2013 I need another time',\n  '\u274c *cancel* \u2013 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 \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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: `\u26a0\ufe0f *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  `\u2705 *Appointment Confirmed!*`,\n  '',\n  `Thank you, *${patientName}!* We have noted your confirmation.`,\n  '',\n  `\ud83c\udfe5 *Clinic:* ${appt.clinicName || 'Our Clinic'}`,\n  `\ud83d\udc68\u200d\u2695\ufe0f *Doctor:* ${appt.doctorName || 'Your Doctor'}`,\n  `\ud83d\udcc5 *Date:* ${formattedDate}`,\n  `\ud83d\udd50 *Time:* ${appt.appointmentTime}`,\n  '',\n  '\ud83d\udccd Please arrive 10 minutes early.',\n  '\ud83d\udcc4 Bring any previous reports or prescriptions.',\n  '',\n  'See you soon! \ud83d\ude0a'\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 \u2013 Update Status Confirmed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        768,
        416
      ],
      "parameters": {
        "columns": {
          "value": {
            "phone": "={{ $('Google Sheets \u2013 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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "c47004c0-95f6-455c-a443-5fc3083a5f4f",
      "name": "Google Sheets \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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: `\u26a0\ufe0f *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  `\u274c *Appointment Cancelled*`,\n  '',\n  `We have cancelled your appointment, *${patientName}.*`,\n  '',\n  `\ud83d\uddd1\ufe0f *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! \ud83d\ude4f'\n];\n\nconst adminLines = [\n  `\ud83d\udea8 *Appointment Cancelled*`,\n  '',\n  `\ud83d\udc64 *Patient:* ${patientName}`,\n  `\ud83d\udcde *Phone:* ${phone}`,\n  `\ud83d\udc68\u200d\u2695\ufe0f *Doctor:* ${appt.doctorName || 'N/A'}`,\n  `\ud83d\udcc5 *Date:* ${formattedDate}`,\n  `\ud83d\udd50 *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 \u2013 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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "c4af005b-b3c6-403c-a615-9374cac32c95",
      "name": "Google Sheets \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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: `\u26a0\ufe0f *No available slots right now.*\\n\\nPlease call us directly to reschedule.\\n\ud83d\udcde Contact: YOUR_CLINIC_PHONE`,\n    slots: []\n  }}];\n}\n\nconst lines = [\n  `\ud83d\udd01 *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}.* \ud83d\udcc5 ${formattedDate} at \ud83d\udd50 ${s.time} \u2014 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 \u2013 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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "d0c8c7c1-a871-4553-a6f5-d312617962b5",
      "name": "Google Sheets \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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: `\u26a0\ufe0f 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: `\u26a0\ufe0f 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: `\u26a0\ufe0f 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  `\u2705 *Appointment Rescheduled!*`,\n  '',\n  `Great choice, *${patientName}!* Your appointment has been updated.`,\n  '',\n  `\ud83d\udc68\u200d\u2695\ufe0f *Doctor:* Dr. ${selected.doctorName || 'Available'}`,\n  `\ud83d\udcc5 *New Date:* ${formattedDate}`,\n  `\ud83d\udd50 *New Time:* ${selected.time}`,\n  '',\n  '\ud83d\udccd Please arrive 10 minutes early.',\n  'Reply *myappointment* to verify your booking.',\n  '',\n  'See you soon! \ud83d\ude0a'\n];\n\nconst adminLines = [\n  `\ud83d\udd01 *Appointment Rescheduled*`,\n  `\ud83d\udc64 *Patient:* ${patientName}`,\n  `\ud83d\udcde *Phone:* ${phone}`,\n  `\ud83d\udcc5 *New Date:* ${formattedDate}`,\n  `\ud83d\udd50 *New Time:* ${selected.time}`,\n  `\ud83d\udc68\u200d\u2695\ufe0f *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 \u2013 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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "89deab9b-54fa-4723-a57d-6fdfed6db894",
      "name": "Google Sheets \u2013 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": {
          "name": "<your credential>"
        }
      },
      "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: `\ud83d\udccb *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 = [`\ud83d\udccb *My Appointments*`, `\ud83d\udc64 *${patientName}*`, ''];\n\nconst statusEmoji = { confirmed: '\u2705', pending: '\u23f3', rescheduled: '\ud83d\udd01', cancelled: '\u274c', completed: '\ud83c\udfc1' };\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()] || '\ud83d\udcc5';\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()] || '\ud83d\udcc5';\n    lines.push(`${emoji} ${fd} \u2013 Dr. ${r.json.doctorName || 'N/A'} (${r.json.status})`);\n  }\n  lines.push('');\n}\n\nlines.push('\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501');\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": {
          "name": "<your credential>"
        }
      },
      "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": {
          "name": "<your credential>"
        }
      },
      "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": {
          "name": "<your credential>"
        }
      },
      "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": {
          "name": "<your credential>"
        }
      },
      "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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "561443ba-02e2-4019-9c59-44db9af5ea9b",
      "name": "Wati Trigger",
      "type": "n8n-nodes-wati.watiTrigger",
      "position": [
        -608,
        1088
      ],
      "parameters": {
        "event": "messageReceived"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "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": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Wati Trigger": {
      "main": [
        [
          {
            "node": "Route Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route Message": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Read for Confirm",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read for Cancel",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read Available Slots",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read My Appointment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read Reschedule Session",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Cancellation": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Update Status Cancelled",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Confirmation": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Update Status Confirmed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Available Slots": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 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 \u2013 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 \u2013 9AM Daily": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Read Appointments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read for Cancel": {
      "main": [
        [
          {
            "node": "Process Cancellation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read for Confirm": {
      "main": [
        [
          {
            "node": "Process Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read Appointments": {
      "main": [
        [
          {
            "node": "Filter Upcoming Appointments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Update Rescheduled": {
      "main": [
        [
          {
            "node": "Send a text message3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read My Appointment": {
      "main": [
        [
          {
            "node": "Build My Appointment Card",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read Available Slots": {
      "main": [
        [
          {
            "node": "Build Available Slots",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read Reschedule Session": {
      "main": [
        [
          {
            "node": "Process Slot Selection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Save Reschedule Session": {
      "main": [
        [
          {
            "node": "Send a text message2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Update Status Cancelled": {
      "main": [
        [
          {
            "node": "Send a text message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Update Status Confirmed": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}