AutomationFlowsSlack & Telegram › Send Daily Appointment Reminders From Google Sheets to Whatsapp

Send Daily Appointment Reminders From Google Sheets to Whatsapp

ByKanishka Shrivastava @kanishka-shrivastava on n8n.io

This workflow runs daily to read appointment bookings from Google Sheets, filter for tomorrow’s appointments that have not been reminded yet, send each client a WhatsApp reminder message, and then update the sheet to mark the reminder as sent. Runs every day at 9 AM on a…

Cron / scheduled trigger★★★★☆ complexity12 nodesGoogle SheetsWhatsApp
Slack & Telegram Trigger: Cron / scheduled Nodes: 12 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #17000 — we link there as the canonical source.

This workflow follows the Google Sheets → WhatsApp recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "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
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs daily to read appointment bookings from Google Sheets, filter for tomorrow’s appointments that have not been reminded yet, send each client a WhatsApp reminder message, and then update the sheet to mark the reminder as sent. Runs every day at 9 AM on a…

Source: https://n8n.io/workflows/17000/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

This workflow automatically sends timely medication reminders to patients after a prescription is marked as sent in the system. It reads the medication schedule from prescription data, schedules remin

Google Sheets, WhatsApp, Google Sheets Trigger +1
Slack & Telegram

This workflow runs every hour to read abandoned cart rows from Google Sheets, sends a WhatsApp reminder (with a discount for high-value carts), and then updates the sheet to log the follow-up count an

Google Sheets, WhatsApp
Slack & Telegram

Auto Hunt. Uses httpRequest, googleSheets, rssFeedRead, telegram. Scheduled trigger; 78 nodes.

HTTP Request, Google Sheets, RSS Feed Read +1
Slack & Telegram

Auto-Hunt. Uses httpRequest, googleSheets, rssFeedRead, telegram. Scheduled trigger; 78 nodes.

HTTP Request, Google Sheets, RSS Feed Read +1
Slack & Telegram

This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS

HTTP Request, Shopify, SendGrid +5