{
  "id": "wVvNaEO8lG0lIMzU",
  "meta": {
    "instanceId": "cb9a1e5321767b6316634728341237e564b2587ab15b74ca0a89eb02a53484d6",
    "templateCredsSetupCompleted": true
  },
  "name": "Automated WhatsApp Welcome Messages for Sales Leads with Google Sheets & Rapiwa",
  "tags": [],
  "nodes": [
    {
      "id": "0550f462-b916-47d3-bebf-b505da01a7fd",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2736,
        -880
      ],
      "parameters": {
        "color": 4,
        "width": 1040,
        "height": 1728,
        "content": "# Automated WhatsApp Welcome Messages for Sales Leads with Google Sheets & Rapiwa\n\n## What does this workflow do?\nThis n8n automation helps you send personalized WhatsApp messages to your leads, directly from a Google Sheet. It checks for new leads, verifies their WhatsApp numbers, sends a welcome message, and updates your sheet—all automatically, every 5 minutes.\n\n---\n\n## How it works (Step by Step)\n1. **Scheduled Runs:**  \n   The workflow runs itself every 5 minutes (you can change this if you want).\n2. **Fetch Leads:**  \n   It looks for new leads in your Google Sheet that are marked for messaging.\n3. **Clean & Validate Numbers:**  \n   Each WhatsApp number is cleaned (removes spaces/symbols) and checked to make sure it’s real and active.\n4. **Send Messages:**  \n   If the number is valid, a personalized WhatsApp message is sent using the Rapiwa API.\n5. **Update Status:**  \n   The Google Sheet is updated to show which messages were sent successfully and which weren’t.\n6. **Safe Batching:**  \n   Only up to 60 leads are processed at a time, with a 5-second pause between each message to avoid being blocked.\n7. **Repeat:**  \n   The cycle repeats, so new leads are always picked up.\n\n---\n\n## What you need\n- **A Google Sheet** set up like [this sample](https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit?usp=sharing)\n- **Google Sheets OAuth2 credentials** connected to n8n\n- **A valid Rapiwa Bearer YOUR_TOKEN_HERE**\n- **WhatsApp Account** (Personal or Business)\n- Your Google Sheet should have these columns:\n  - `WhatsApp No`\n  - `name ` (note: there’s a space at the end—match exactly)\n  - `row_number`\n  - `status`, `check`, `validity`\n\n---\n\n## Example Google Sheet\n\n| name            | number        | email             | time                        | check   | validity   | status    |\n|-----------------|--------------|-------------------|-----------------------------|---------|------------|-----------|\n| Shakil Ahammed  | 8801322827753| admin@gmail.com   | September 14th 2025, 10:34  | checked | verified   | sent      |\n| Shakil Ahammed  | 8801322827754| admin@gmail.com   | September 14th 2025, 10:34  | checked | unverified | not sent  |\n\n> **Note:** The `name` column must have a space at the end: `name `\n\n---\n\n## Tips for Best Results\n- Keep your Google Sheet tidy and use data validation if possible.\n- Always use international phone number format.\n- If you get blocked by Rapiwa, try increasing the wait time or lowering the batch size.\n- Make sure you have a `row_number` column (can be auto-generated).\n\n---\n\n## Want to customize?\n- Log errors to a separate sheet\n- Get email notifications for failed messages\n- Send PDFs or images via Rapiwa\n- Personalize messages with more fields\n\n---\n\n## Why use this?\nThis workflow is perfect for automating lead engagement, order confirmations, or onboarding messages. It saves you time and effort by handling WhatsApp messaging for you, using your Google Sheet as the source of truth.\n\n> **Built for non-official WhatsApp API workflows using n8n and Rapiwa.**"
      },
      "typeVersion": 1
    },
    {
      "id": "0841f0a0-7042-4049-8642-6d40987fc607",
      "name": "Fetch All Pending Queries for Messaging1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1072,
        -496
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "check"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit?usp=drivesdk",
          "cachedResultName": "Sales - Send welcome message"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "googleSheetsOAuth2Api Credential"
        }
      },
      "notesInFlow": false,
      "retryOnFail": false,
      "typeVersion": 4.6
    },
    {
      "id": "27263025-0d11-4e6b-bf84-df8e3269cd24",
      "name": "Limit1",
      "type": "n8n-nodes-base.limit",
      "position": [
        -656,
        -496
      ],
      "parameters": {
        "maxItems": 60
      },
      "typeVersion": 1
    },
    {
      "id": "ed57db8c-6127-454f-b7a1-b65a77877e7b",
      "name": "Clean WhatsApp Number1",
      "type": "n8n-nodes-base.code",
      "position": [
        16,
        -480
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst updatedItems = items.map((item) => {\n  let waNo = item?.json[\"WhatsApp No\"];\n\n  // Convert to string safely\n  let waNoStr = \"\";\n  if (typeof waNo === 'string') {\n    waNoStr = waNo;\n  } else if (waNo !== undefined && waNo !== null) {\n    waNoStr = String(waNo);\n  }\n\n  // Remove all non-digit characters\n  const cleanedNumber = waNoStr.replace(/\\D/g, \"\");\n\n  // Assign cleaned number as a string\n  item.json[\"WhatsApp No\"] = cleanedNumber;\n\n  return item;\n});\n\nreturn updatedItems;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7e100ddc-107e-4059-90cb-b4cef3d5c3a7",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -416,
        -496
      ],
      "parameters": {
        "options": {}
      },
      "executeOnce": false,
      "typeVersion": 3
    },
    {
      "id": "da9deff5-b797-4997-a2e2-5923f09f7c18",
      "name": "Send Message Using Rapiwa1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        816,
        -128
      ],
      "parameters": {
        "url": "=https://app.rapiwa.com/api/send-message",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "number",
              "value": "={{ $json.data.phone }}"
            },
            {
              "name": "message_type",
              "value": "text"
            },
            {
              "name": "message",
              "value": "=Hi *{{ $('Clean WhatsApp Number1').item.json['name '] }}*,\nThanks for purchasing from *Spagreen Creative*. Your product purchase has been confirmed.\nWe truly appreciate your trust in our products. If you have any questions, feel free to message us here anytime!\n– Team *Spagreen Creative*"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "credential-id",
          "name": "httpBearerAuth Credential"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ae5bfcf0-f1c5-41a5-ad48-2f0cc94faa3c",
      "name": "Update rows: not sent & unverified1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        816,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "check": "checked",
            "status": "not sent",
            "validity": "unverified",
            "row_number": "={{ $('Loop Over Items').item.json.row_number }}"
          },
          "schema": [
            {
              "id": "name ",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "name ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "check",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "check",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "validity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "validity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit?usp=drivesdk",
          "cachedResultName": "Sales - Send welcome message"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "googleSheetsOAuth2Api Credential"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "fc1b5295-dda0-43ee-a275-32f55b969cb4",
      "name": "Update rows: sent & verified1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1040,
        -128
      ],
      "parameters": {
        "columns": {
          "value": {
            "check": "checked",
            "status": "sent",
            "validity": "verified",
            "row_number": "={{ $('Loop Over Items').item.json.row_number }}"
          },
          "schema": [
            {
              "id": "name ",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "name ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "check",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "check",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "validity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "validity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1amkVSIXrhOkf86YDYaddOcAamhUC4DlvFiSg3cpAH78/edit?usp=drivesdk",
          "cachedResultName": "Sales - Send welcome message"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "googleSheetsOAuth2Api Credential"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "524c6411-7826-4ef0-a723-e6fa741758b9",
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "position": [
        1040,
        80
      ],
      "webhookId": "6c474e54-eb3c-4fcd-b455-948322cd0121",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "1f9f9e50-4934-4184-b4dd-b4aa3d2351ac",
      "name": "Check valid whatsapp number Using Rapiwa1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        224,
        -480
      ],
      "parameters": {
        "url": "=https://app.rapiwa.com/api/verify-whatsapp",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "number",
              "value": "={{ String($json.number) }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "credential-id",
          "name": "httpBearerAuth Credential"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "31c3193f-ac56-4ae8-8221-06ef827f00ee",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        -896
      ],
      "parameters": {
        "width": 320,
        "height": 720,
        "content": "## Workflow Schedule\nThis workflow runs automatically every 5 minutes. You can adjust the interval if you want messages to go out more or less frequently. This ensures your leads are always contacted on time, without any manual effort."
      },
      "typeVersion": 1
    },
    {
      "id": "f1ed589d-493c-4a62-9fb3-5bbf0f83b0a5",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1248,
        -896
      ],
      "parameters": {
        "color": 2,
        "width": 448,
        "height": 944,
        "content": "## Google Sheets Connection\nThis step fetches all leads from your Google Sheet that are marked for messaging (where the `check` column is filled). Make sure your Document ID and Sheet GID are correct. Only the leads you want to contact are selected, giving you full control.\n\n- **Node:** Fetch All Pending Queries for Messaging\n- Reads rows from your Google Sheet where the `check` column is filled.\n- Make sure the correct Document ID and Sheet GID are set.\n- Only leads marked for messaging are fetched."
      },
      "typeVersion": 1
    },
    {
      "id": "83a91565-e5b4-4551-a8b7-6407ce030c6b",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        -896
      ],
      "parameters": {
        "color": 6,
        "width": 608,
        "height": 1232,
        "content": "## Limit and Process Leads\nTo keep things running smoothly, the workflow processes up to 60 leads at a time. You can change this limit as needed. Each lead is handled one by one, so every contact gets the right message and your system stays fast.\n\n- **Node:** Limit\n  - Only processes up to 60 leads per cycle to avoid overloading or hitting API limits.\n  - You can adjust this number as needed.\n- **Node:** Loop Over Items1\n  - Goes through each lead one by one for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "5f158c59-9cb4-4c43-9705-8cb6843baef8",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        -896
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 1232,
        "content": "## Clean and Verify WhatsApp Numbers\nBefore sending messages, each WhatsApp number is cleaned (removing spaces and symbols) and checked to make sure it’s a real, active WhatsApp account. Only valid numbers will get a message, so you don’t waste time or credits.\n\n- **Node:** Clean WhatsApp Number\n  - Removes any spaces or symbols from phone numbers so they work with the API.\n- **Node:** Check valid whatsapp number Using Rapiwa\n  - Checks if the WhatsApp number is real and can receive messages.\n  - Only valid numbers will get a message."
      },
      "typeVersion": 1
    },
    {
      "id": "30aea538-f33c-4e6e-ae4a-8295cc455f0f",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        -896
      ],
      "parameters": {
        "color": 4,
        "width": 848,
        "height": 1232,
        "content": "## Message Sending & Status Update\nIf a WhatsApp number is valid, the workflow sends a personalized message and updates the sheet to show it was sent. If not, it marks the row as not sent and unverified. Each message is sent with a 5-second pause to avoid being blocked. The Google Sheet is always updated, so you know which leads were contacted.\n\n- **Node:** If\n  - Checks if the WhatsApp number is valid.\n  - If valid: sends the message.\n  - If not valid: marks the row as \"not sent\" and \"unverified\".\n- **Node:** Send Message Using Rapiwa\n  - Sends a personalized WhatsApp message using the name from your sheet.\n- **Node:** Update rows: sent & verified\n  - Marks successful messages as \"sent\" and \"verified\".\n- **Node:** Update rows: not sent & unverified\n  - Marks failed messages as \"not sent\" and \"unverified\".\n- **Node:** Wait\n  - Waits 5 seconds between each message to avoid being blocked by WhatsApp or the API."
      },
      "typeVersion": 1
    },
    {
      "id": "20ec8ec0-ef20-40fe-9f97-8f11c201eb71",
      "name": "Trigger Every 5 Minute1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1504,
        -496
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "769eb9a9-5afb-42f3-8b79-26dbb824902d",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        560,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3ab8725a-9268-45fd-b91c-0e055fe6fa7c",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.exists }}",
              "rightValue": "=\"true\""
            }
          ]
        }
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "40f6da2f-5153-49a9-b19a-c0365573c1ef",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Send Message Using Rapiwa1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update rows: not sent & unverified1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit1": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Clean WhatsApp Number1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean WhatsApp Number1": {
      "main": [
        [
          {
            "node": "Check valid whatsapp number Using Rapiwa1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Every 5 Minute1": {
      "main": [
        [
          {
            "node": "Fetch All Pending Queries for Messaging1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Message Using Rapiwa1": {
      "main": [
        [
          {
            "node": "Update rows: sent & verified1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update rows: sent & verified1": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update rows: not sent & unverified1": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch All Pending Queries for Messaging1": {
      "main": [
        [
          {
            "node": "Limit1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check valid whatsapp number Using Rapiwa1": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}