This workflow follows the Google Sheets → HTTP Request 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 →
{
"name": "Fluxo A - Opt-in (Luz da Lua)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 13 * * 1-5"
}
]
}
},
"id": "a1",
"name": "Schedule 10h BRT (dias \u00fateis)",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
240,
300
],
"notes": "Cron 0 13 * * 1-5 = 10h em America/Sao_Paulo se o n8n estiver em UTC. Ajuste se a env GENERIC_TIMEZONE=America/Sao_Paulo estiver setada (use 0 10 * * 1-5)."
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "PLACEHOLDER_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "PLACEHOLDER_SHEET_NAME",
"mode": "name"
},
"options": {}
},
"id": "a2",
"name": "Sheets - Get rows",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
460,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "f1",
"leftValue": "={{ $json.opt_in }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "empty",
"singleValue": true
}
},
{
"id": "f2",
"leftValue": "={{ $json.status_contato }}",
"rightValue": "sem_consentimento",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a3",
"name": "Filter - sem_consentimento",
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
680,
300
]
},
{
"parameters": {
"maxItems": 20
},
"id": "a4",
"name": "Limit (warm-up: 20/dia)",
"type": "n8n-nodes-base.limit",
"typeVersion": 1,
"position": [
900,
300
],
"notes": "Ajuste segundo o cronograma de warm-up (07-warmup-e-qualidade.md)."
},
{
"parameters": {
"batchSize": 1,
"options": {}
},
"id": "a5",
"name": "SplitInBatches",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
1120,
300
]
},
{
"parameters": {
"method": "POST",
"url": "=https://graph.facebook.com/v21.0/{{$env.WHATSAPP_PHONE_NUMBER_ID}}/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"messaging_product\": \"whatsapp\",\n \"to\": \"{{ $json.telefone }}\",\n \"type\": \"template\",\n \"template\": {\n \"name\": \"solicitar_consentimento\",\n \"language\": { \"code\": \"pt_BR\" },\n \"components\": [\n {\n \"type\": \"body\",\n \"parameters\": [\n { \"type\": \"text\", \"text\": \"{{ $json.nome }}\" }\n ]\n }\n ]\n }\n}",
"options": {
"response": {
"response": {
"fullResponse": false,
"neverError": true
}
}
}
},
"id": "a6",
"name": "WhatsApp - Send template",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput",
"notes": "Header Authorization: Bearer <ACCESS_TOKEN> via credencial Header Auth (Name=Authorization, Value=Bearer SEU_TOKEN)."
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "ok",
"leftValue": "={{ $json.messages?.[0]?.id }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "ok"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "inv",
"leftValue": "={{ $json.error?.code }}",
"rightValue": "131026",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "numero_invalido"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "tp",
"leftValue": "={{ $json.error?.code }}",
"rightValue": "132000",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "template_paused"
}
]
},
"options": {
"fallbackOutput": "extra",
"renameFallbackOutput": "falha"
}
},
"id": "a7",
"name": "Switch - resultado API",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
1560,
300
]
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "PLACEHOLDER_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "PLACEHOLDER_SHEET_NAME",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"matchingColumns": [
"telefone"
],
"value": {
"telefone": "={{ $('SplitInBatches').item.json.telefone }}",
"status_contato": "aguardando_resposta_optin",
"data_ultimo_envio": "={{ $now.toISO() }}",
"versao_template_optin": "solicitar_consentimento_v1",
"tentativas_envio": 0,
"ultimo_erro": ""
}
},
"options": {}
},
"id": "a8",
"name": "Sheets - Update OK",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1820,
140
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "PLACEHOLDER_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "PLACEHOLDER_SHEET_NAME",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"matchingColumns": [
"telefone"
],
"value": {
"telefone": "={{ $('SplitInBatches').item.json.telefone }}",
"status_contato": "numero_invalido",
"ultimo_erro": "131026 - not a WhatsApp user"
}
},
"options": {}
},
"id": "a9",
"name": "Sheets - numero_invalido",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1820,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"errorMessage": "Template solicitar_consentimento foi pausado pela Meta. Verifique no WhatsApp Manager."
},
"id": "a10",
"name": "Stop - template_paused",
"type": "n8n-nodes-base.stopAndError",
"typeVersion": 1,
"position": [
1820,
460
]
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "PLACEHOLDER_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "PLACEHOLDER_SHEET_NAME",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"matchingColumns": [
"telefone"
],
"value": {
"telefone": "={{ $('SplitInBatches').item.json.telefone }}",
"tentativas_envio": "={{ ($('SplitInBatches').item.json.tentativas_envio || 0) + 1 }}",
"ultimo_erro": "={{ ($json.error?.code || 'unknown') + ' - ' + ($json.error?.message || JSON.stringify($json)) }}",
"status_contato": "={{ (($('SplitInBatches').item.json.tentativas_envio || 0) + 1) >= 3 ? 'falha_envio' : $('SplitInBatches').item.json.status_contato }}"
}
},
"options": {}
},
"id": "a11",
"name": "Sheets - Falha gen\u00e9rica",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1820,
620
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"amount": "={{ Math.floor(Math.random() * 40) + 20 }}",
"unit": "seconds"
},
"id": "a12",
"name": "Wait 20-60s (humanizar)",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
2060,
300
]
}
],
"connections": {
"Schedule 10h BRT (dias \u00fateis)": {
"main": [
[
{
"node": "Sheets - Get rows",
"type": "main",
"index": 0
}
]
]
},
"Sheets - Get rows": {
"main": [
[
{
"node": "Filter - sem_consentimento",
"type": "main",
"index": 0
}
]
]
},
"Filter - sem_consentimento": {
"main": [
[
{
"node": "Limit (warm-up: 20/dia)",
"type": "main",
"index": 0
}
]
]
},
"Limit (warm-up: 20/dia)": {
"main": [
[
{
"node": "SplitInBatches",
"type": "main",
"index": 0
}
]
]
},
"SplitInBatches": {
"main": [
[
{
"node": "WhatsApp - Send template",
"type": "main",
"index": 0
}
]
]
},
"WhatsApp - Send template": {
"main": [
[
{
"node": "Switch - resultado API",
"type": "main",
"index": 0
}
]
]
},
"Switch - resultado API": {
"main": [
[
{
"node": "Sheets - Update OK",
"type": "main",
"index": 0
}
],
[
{
"node": "Sheets - numero_invalido",
"type": "main",
"index": 0
}
],
[
{
"node": "Stop - template_paused",
"type": "main",
"index": 0
}
],
[
{
"node": "Sheets - Falha gen\u00e9rica",
"type": "main",
"index": 0
}
]
]
},
"Sheets - Update OK": {
"main": [
[
{
"node": "Wait 20-60s (humanizar)",
"type": "main",
"index": 0
}
]
]
},
"Sheets - numero_invalido": {
"main": [
[
{
"node": "Wait 20-60s (humanizar)",
"type": "main",
"index": 0
}
]
]
},
"Sheets - Falha gen\u00e9rica": {
"main": [
[
{
"node": "Wait 20-60s (humanizar)",
"type": "main",
"index": 0
}
]
]
},
"Wait 20-60s (humanizar)": {
"main": [
[
{
"node": "SplitInBatches",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
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.
googleSheetsOAuth2ApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Fluxo A - Opt-in (Luz da Lua). Uses googleSheets, httpRequest, stopAndError. Scheduled trigger; 12 nodes.
Source: https://github.com/rodrigogr/shared-projects/blob/3a68abe13ba87467d3fc5fa0e72f91a2686d4bd3/whatsapp-mvp/n8n-workflows/fluxo-a-opt-in.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
YogiAI. Uses googleSheets, googleSheetsTool, httpRequest, stopAndError. Scheduled trigger; 61 nodes.
Anyone curating before/after text examples in a spreadsheet and wanting a push-button path to a fine-tuned GPT model—without touching curl. Works with Google Sheets or Airtable.
This workflow automates video distribution to 9 social platforms simultaneously using Blotato's API. It includes both a scheduled publisher (checks Google Sheets for videos marked "Ready") and a subwo
This workflow monitors Google Calendar for events indicating that a customer will visit the company today or the next day, retrieves the required details, and sends reminder notifications to the relev
ofn hook v0.24.0 beta. Uses start, httpRequest, functionItem, itemLists. Scheduled trigger; 42 nodes.