AutomationFlowsData & Sheets › Google Sheets Send SMS with Twilio - Bulk SMS Automation Simplified!

Google Sheets Send SMS with Twilio - Bulk SMS Automation Simplified!

ByMilan Vasarhelyi - SmoothWork @vasarmilan on n8n.io

[](https://youtu.be/6QKbzoWMaXE)

Event trigger★★★★☆ complexity13 nodesGoogle Sheets TriggerTwilioGoogle Sheets
Data & Sheets Trigger: Event Nodes: 13 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Sheets → Googlesheetstrigger 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "57c3d2f1-a6bf-489b-8d89-e22e2c331060",
      "name": "Monitor Google Sheet for SMS Queue",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -16,
        784
      ],
      "parameters": {
        "options": {
          "columnsToWatch": [
            "Status"
          ]
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1DGhQ2YLeQ5boLYPMK4nUF8SIOJmDDqvtyleSz5IpJEc/edit?gid=0#gid=0"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1DGhQ2YLeQ5boLYPMK4nUF8SIOJmDDqvtyleSz5IpJEc/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "46ad543f-8988-4258-9a9d-f824461e5862",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        784
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e60a21c7-574a-4579-9e7f-57cf6b9f50c9",
              "name": "sheet_url",
              "type": "string",
              "value": "https://docs.google.com/spreadsheets/d/1DGhQ2YLeQ5boLYPMK4nUF8SIOJmDDqvtyleSz5IpJEc/edit?gid=0#gid=0"
            },
            {
              "id": "e39b8ae5-c53a-4186-9ec5-6c352cd1d7e4",
              "name": "from_number",
              "type": "string",
              "value": "+1234567890"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "122f32a2-c87e-419f-b168-fabe5ed9a111",
      "name": "Merge Config with Row Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        736,
        560
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "e2135c65-c83a-487a-9fab-6760711001f1",
      "name": "Prepare SMS Content",
      "type": "n8n-nodes-base.set",
      "position": [
        928,
        560
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "463668f7-11f7-48d2-91c3-635a78637c7f",
              "name": "Message",
              "type": "string",
              "value": "={{ $json['Message Template']\n  .replace(/\\[First Name\\]/g, $json['First Name'])\n  .replace(/\\[Last Name\\]/g, $json['Last Name'])\n}}"
            },
            {
              "id": "3ddbf667-aa74-4ddb-b12e-6bf1294fdaa3",
              "name": "To",
              "type": "string",
              "value": "={{ $json.Phone }}"
            },
            {
              "id": "609250bc-7ae0-4213-9611-a60b3ac63eaa",
              "name": "From",
              "type": "string",
              "value": "={{ $json.from_number }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "604eeeb8-57c7-452e-b9ba-a69609fb0869",
      "name": "Check if Ready to Send",
      "type": "n8n-nodes-base.if",
      "position": [
        384,
        784
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "223f9988-650a-4fcc-9a65-2f240c4b3dce",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "To send"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "61cf54a2-dafe-48f2-812e-68edc1207c63",
      "name": "Send SMS via Twilio",
      "type": "n8n-nodes-base.twilio",
      "onError": "continueRegularOutput",
      "position": [
        1136,
        560
      ],
      "parameters": {
        "to": "={{ $json.To }}",
        "from": "={{ $json.From }}",
        "message": "={{ $json.Message }}",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3a112254-bd07-4b7c-9cd4-b2950548fbff",
      "name": "Update Status to Sending",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        592,
        768
      ],
      "parameters": {
        "columns": {
          "value": {
            "ID": "={{ $json.ID }}",
            "Status": "Sending..."
          },
          "schema": [
            {
              "id": "ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Message Template",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Message Template",
              "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": [
            "ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.sheet_url }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.sheet_url }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "3497b801-644b-4e83-9638-e674090a4871",
      "name": "Check Send Result",
      "type": "n8n-nodes-base.if",
      "position": [
        1344,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3f814939-8cea-4114-aed8-9f4202c7eb80",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ !$json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d5252d5b-7064-42e5-9167-a9e544e7eaa8",
      "name": "Mark as Success",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1584,
        464
      ],
      "parameters": {
        "columns": {
          "value": {
            "ID": "={{ $('Update Status to Sending').item.json.ID }}",
            "Status": "Success"
          },
          "schema": [
            {
              "id": "ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Message Template",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Message Template",
              "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": [
            "ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Config').first().json.sheet_url }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Config').first().json.sheet_url }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "b9b09def-5a49-49f3-b754-fcd7fb2bc521",
      "name": "Mark as Error",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1584,
        672
      ],
      "parameters": {
        "columns": {
          "value": {
            "ID": "={{ $('Update Status to Sending').item.json.ID }}",
            "Status": "Error"
          },
          "schema": [
            {
              "id": "ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Message Template",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Message Template",
              "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": [
            "ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Config').first().json.sheet_url }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Config').first().json.sheet_url }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "3ae7f2e6-2907-4ccf-9c65-3f74ff79bbac",
      "name": "Configuration Helper",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        592
      ],
      "parameters": {
        "width": 272,
        "content": "## Configure here \ud83d\udc47\ud83d\udc47\nSet your Google Sheet URL and Twilio phone number in the Config node below"
      },
      "typeVersion": 1
    },
    {
      "id": "contact-note-1759930148725",
      "name": "Creator Contact Info",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -716,
        -71
      ],
      "parameters": {
        "color": 5,
        "width": 600,
        "height": 440,
        "content": "# Contact Us:\n## Milan @ SmoothWork - [Book a Free Consulting Call](https://smoothwork.ai/book-a-call/)\n![Milan](https://gravatar.com/avatar/95700d17ba300a9f14c1b8cacf933df7720027b3adda9cbe6183d89142925422?r=pg&d=retro&size=100)\n\n\n### We help businesses eliminate busywork by building compact business tools tailored to your process.\n### Contact us for customizing this, or building similar automations.\n\n\ud83d\udce7 hello@smoothwork.ai\n\u25b6\ufe0f [Check us on YouTube](https://www.youtube.com/@vasarmilan)\n\ud83d\udcde [Book a Free Consulting Call](https://smoothwork.ai/book-a-call/)\n\ud83d\udcbc [Add me on Linkedin](https://www.linkedin.com/in/mil%C3%A1n-v%C3%A1s%C3%A1rhelyi-3a9985123/)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "doc-note-1759930148725",
      "name": "Workflow Description",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -716,
        369
      ],
      "parameters": {
        "width": 600,
        "height": 950,
        "content": "## Workflow Overview\n\nThis workflow automates sending personalized SMS messages directly from a Google Sheet. Simply update a row's status to \"To send\" and the workflow will automatically send the text message via Twilio, then update the status to \"Success\" or \"Error\" based on the delivery result. Perfect for event reminders, bulk notifications, or any scenario where you need to send customized messages to multiple recipients.\n\n### First Setup\n\n1. **Copy the Google Sheet Template**: Make a copy of the [template spreadsheet](https://docs.google.com/spreadsheets/d/1DGhQ2YLeQ5boLYPMK4nUF8SIOJmDDqvtyleSz5IpJEc/edit?usp=sharing) via *File \u2192 Make a copy*. You must use your own copy so the workflow can update the status.\n\n2. **Connect Google Sheets**: Add your Google Sheets credentials to the 'Monitor Google Sheet for SMS Queue' trigger node.\n\n3. **Set up Twilio**: Sign up for a [free Twilio account](https://www.twilio.com/try-twilio) (trial works fine for testing). Get your Account SID, Auth Token, and Twilio phone number from the dashboard, then add these credentials to the 'Send SMS via Twilio' node.\n\n### Configuration\n\nIn the **Config** node, update:\n- `sheet_url`: Your copied Google Sheet URL\n- `from_number`: Your Twilio phone number\n\nThe workflow monitors the 'Status' column every minute. Message templates support `[First Name]` and `[Last Name]` placeholders for personalization."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Config": {
      "main": [
        [
          {
            "node": "Check if Ready to Send",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Send Result": {
      "main": [
        [
          {
            "node": "Mark as Success",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark as Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare SMS Content": {
      "main": [
        [
          {
            "node": "Send SMS via Twilio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send SMS via Twilio": {
      "main": [
        [
          {
            "node": "Check Send Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Ready to Send": {
      "main": [
        [
          {
            "node": "Update Status to Sending",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Config with Row Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Status to Sending": {
      "main": [
        [
          {
            "node": "Merge Config with Row Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Config with Row Data": {
      "main": [
        [
          {
            "node": "Prepare SMS Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monitor Google Sheet for SMS Queue": {
      "main": [
        [
          {
            "node": "Config",
            "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

[](https://youtu.be/6QKbzoWMaXE)

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.

HTTP Request, Gmail, Twilio +3
Data & Sheets

Stickynote Workflow. Uses googleTranslate, googleSheetsTrigger, googleDrive, httpRequest. Event-driven trigger; 22 nodes.

Google Translate, Google Sheets Trigger, Google Drive +2
Data & Sheets

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Google Sheets Trigger, N8N Nodes Sinergiacrm, Google Sheets
Data & Sheets

This powerful no-code workflow automates plagiarism detection using Plagiarism Checker AI Powered. Users submit text through Google Sheets. The system checks for duplication using the API, sends a det

Google Sheets Trigger, HTTP Request, Email Send +1
Data & Sheets

📋 Customer submits your Typeform → instant personalised welcome SMS fires via Twilio 📊 Submission logged to Google Sheets with name, phone, timestamp, and nudge tracking 💬 Twilio listens 24/7 for repl

Typeform Trigger, Twilio, Google Sheets +1