{
  "id": "PB3jK3Vbq9HQ8lgu",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Send appointment reminders from Google Sheets to WhatsApp",
  "tags": [],
  "nodes": [
    {
      "id": "689933aa-a39e-4dc3-9231-9b95b57685a9",
      "name": "Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -48
      ],
      "parameters": {
        "color": 4,
        "width": 620,
        "height": 968,
        "content": "## \ud83d\udc87 Send Appointment Reminders from Google Sheets to WhatsApp\n\n## Who's it for\nSalon owners and small service businesses who track bookings in Google Sheets and want to automatically remind clients about upcoming appointments, without manually texting each one.\n\n## How it works\nOnce a day, the workflow checks your Google Sheet for appointments scheduled tomorrow. For each unreminded booking, it sends a WhatsApp message to the client with their appointment details, then marks the row as reminded so it's never sent twice.\n\n## How to set up\n1. Connect your Google Sheets credentials and point the workflow at your booking sheet.\n2. Connect your WhatsApp Business Cloud credentials.\n3. Make sure your sheet has these columns: row_id, client_name, phone_number, service, appointment_time, appointment_date, reminder_sent.\n4. Open the Set Configuration node and enter your Sheet ID, tab name, and WhatsApp phone number ID.\n5. Set your preferred run time in the Schedule Trigger.\n6. Activate the workflow.\n\n## Requirements\n- Google Sheets account\n- WhatsApp Business Cloud API access\n\n## How to customize\nEdit the WhatsApp message template in the Send WhatsApp Reminder node to match your salon's tone. Add a second reminder (e.g. 2 hours before) by duplicating the Schedule Trigger with a different time window."
      },
      "typeVersion": 1
    },
    {
      "id": "b73c245d-0f41-49f9-b658-e1482cee646f",
      "name": "Trigger Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 332,
        "height": 196,
        "content": "## 1\ufe0f\u20e3 Trigger\nRuns once daily. Adjust the time in the node's trigger settings to match when you want reminders sent (e.g. every morning at 9 AM)."
      },
      "typeVersion": 1
    },
    {
      "id": "3e56ce9c-c1c3-4674-b288-548de41ad79a",
      "name": "Every Day at 9 AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        640,
        400
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "274a8500-acb7-49e8-91d5-6e0a6ee94955",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        848,
        400
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-1",
              "name": "sheet_id",
              "type": "string",
              "value": "REPLACE_WITH_GOOGLE_SHEET_ID"
            },
            {
              "id": "cfg-2",
              "name": "sheet_name",
              "type": "string",
              "value": "Appointments"
            },
            {
              "id": "cfg-3",
              "name": "whatsapp_phone_number_id",
              "type": "string",
              "value": "REPLACE_WITH_WHATSAPP_PHONE_NUMBER_ID"
            },
            {
              "id": "cfg-4",
              "name": "tomorrow_date",
              "type": "string",
              "value": "={{ $now.plus({ days: 1 }).toFormat('yyyy-MM-dd') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c15c1820-689c-4198-a4cf-874c555eded9",
      "name": "Sheets Read Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 184,
        "content": "## 2\ufe0f\u20e3 Read Bookings\nReads every row from your Appointments sheet. Required columns: row_id, client_name, phone_number, service, appointment_time, appointment_date, reminder_sent."
      },
      "typeVersion": 1
    },
    {
      "id": "51b0dca9-19b1-4235-8fc8-d911006a14bf",
      "name": "Read Appointments Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1184,
        400
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Set Configuration').item.json.sheet_name }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Configuration').item.json.sheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e92af89c-c7aa-45cb-a4ca-7227ec94a132",
      "name": "Filter Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 184,
        "content": "## 3\ufe0f\u20e3 Filter\nKeeps only rows where appointment_date is tomorrow AND reminder_sent is not already true. This is what stops clients getting texted twice on repeat runs."
      },
      "typeVersion": 1
    },
    {
      "id": "1c8547e1-f803-4299-ab61-bc7a89e76f84",
      "name": "Filter Unreminded Tomorrow",
      "type": "n8n-nodes-base.filter",
      "position": [
        1584,
        400
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "454cc596-65f8-45c7-8f65-d2f6a89f0d6a",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.appointment_date }}",
              "rightValue": "={{ $('Set Configuration').item.json.tomorrow_date }}"
            },
            {
              "id": "33b5150a-a6b5-4f2e-b7c9-6640189632f9",
              "operator": {
                "type": "boolean",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.reminder_sent }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "93762e2d-9749-4bf8-a2a1-1d4664014f1c",
      "name": "Send Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1872,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 332,
        "height": 180,
        "content": "## 4\ufe0f\u20e3 Send Reminder\nCustomize this message template to match your salon's tone. One WhatsApp message is sent per remaining row."
      },
      "typeVersion": 1
    },
    {
      "id": "8180e4e5-0f6f-4667-a83d-818631abf533",
      "name": "Send WhatsApp Reminder",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        1968,
        400
      ],
      "parameters": {
        "textBody": "=Hi {{ $json.client_name }}! Just a reminder about your {{ $json.service }} appointment tomorrow at {{ $json.appointment_time }}. See you then! Reply here if you need to reschedule.",
        "operation": "send",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $json.phone_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2f3b1441-fd49-46d4-af70-ee53a5f64202",
      "name": "Update Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2272,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 348,
        "height": 184,
        "content": "## 5\ufe0f\u20e3 Mark as Reminded\nUpdates the row so it isn't texted again tomorrow. Matches on row_id, so make sure every row has a unique value in that column."
      },
      "typeVersion": 1
    },
    {
      "id": "3e267a20-523e-4bc5-a9b9-60b0e5e9faca",
      "name": "Update Sheet - Mark Reminded",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2320,
        400
      ],
      "parameters": {
        "columns": {
          "value": {
            "row_id": "={{ $json.row_id }}",
            "reminder_sent": true
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_id"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Set Configuration').item.json.sheet_name }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Configuration').item.json.sheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "ffe0b13e-9742-4890-9230-07844ab6f1f1",
  "nodeGroups": [],
  "connections": {
    "Every Day at 9 AM": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Read Appointments Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send WhatsApp Reminder": {
      "main": [
        [
          {
            "node": "Update Sheet - Mark Reminded",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Appointments Sheet": {
      "main": [
        [
          {
            "node": "Filter Unreminded Tomorrow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unreminded Tomorrow": {
      "main": [
        [
          {
            "node": "Send WhatsApp Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}