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": "AutoAtende \u2014 Relat\u00f3rio Semanal Autom\u00e1tico",
"nodes": [
{
"id": "node-cron",
"name": "Cron \u2014 Segunda-feira 8h",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "node-ler-leads",
"name": "Sheets \u2014 Ler Leads da Semana",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
500,
300
],
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "={{ $vars.SHEETS_ID_CLIENTE }}",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"options": {
"returnFirstMatch": false
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"id": "node-calcular-metricas",
"name": "Calcular M\u00e9tricas da Semana",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
750,
300
],
"parameters": {
"jsCode": "const leads = $input.all().map(i => i.json);\n\n// Data de 7 dias atr\u00e1s\nconst agora = new Date();\nconst seteDiasAtras = new Date();\nseteDiasAtras.setDate(agora.getDate() - 7);\n\n// Filtrar apenas leads da \u00faltima semana\nconst leadsSemana = leads.filter(l => {\n if (!l['Data/Hora']) return false;\n // Tenta parsear a data no formato pt-BR: DD/MM/YYYY HH:mm\n const partes = l['Data/Hora'].split(' ');\n const dataParts = (partes[0] || '').split('/');\n if (dataParts.length < 3) return false;\n const dataLead = new Date(dataParts[2], dataParts[1]-1, dataParts[0]);\n return dataLead >= seteDiasAtras;\n});\n\nconst total = leadsSemana.length;\nconst qualificados = leadsSemana.filter(l => l.Status && l.Status !== 'Novo').length;\nconst transferidos = leadsSemana.filter(l => l.Status === 'Transferido').length;\nconst fechados = leadsSemana.filter(l => l.Status === 'Fechado').length;\nconst perdidos = leadsSemana.filter(l => l.Status === 'Perdido').length;\n\nconst taxaConversao = total > 0 ? ((fechados / total) * 100).toFixed(1) : 0;\nconst taxaQualif = total > 0 ? ((qualificados / total) * 100).toFixed(1) : 0;\n\n// Contar leads por dia da semana\nconst diasSemana = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'S\u00e1b'];\nconst porDia = {};\ndiasSemana.forEach(d => porDia[d] = 0);\n\nleadsSemana.forEach(l => {\n if (!l['Data/Hora']) return;\n const partes = l['Data/Hora'].split(' ');\n const dataParts = (partes[0] || '').split('/');\n if (dataParts.length < 3) return;\n const dataLead = new Date(dataParts[2], dataParts[1]-1, dataParts[0]);\n const dia = diasSemana[dataLead.getDay()];\n porDia[dia] = (porDia[dia] || 0) + 1;\n});\n\nconst diaTop = Object.entries(porDia).sort((a,b) => b[1]-a[1])[0];\n\nconst dataInicio = seteDiasAtras.toLocaleDateString('pt-BR');\nconst dataFim = agora.toLocaleDateString('pt-BR');\n\nreturn [{\n json: {\n total, qualificados, transferidos, fechados, perdidos,\n taxaConversao, taxaQualif,\n porDia,\n diaTop: diaTop ? `${diaTop[0]} (${diaTop[1]} leads)` : 'N/A',\n periodo: `${dataInicio} a ${dataFim}`\n }\n}];"
}
},
{
"id": "node-montar-relatorio",
"name": "Montar Mensagem do Relat\u00f3rio",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1000,
300
],
"parameters": {
"jsCode": "const m = $input.first().json;\n\nconst barras = Object.entries(m.porDia)\n .map(([dia, qtd]) => `${dia}: ${'\u2588'.repeat(qtd)}${'\u2591'.repeat(Math.max(0, 5-qtd))} (${qtd})`)\n .join('\\n');\n\nconst mensagem = `\ud83d\udcca *Relat\u00f3rio Semanal \u2014 AutoAtende*\n` +\n `Per\u00edodo: ${m.periodo}\\n\\n` +\n `\ud83d\udce5 Leads recebidos: *${m.total}*\\n` +\n `\u2705 Qualificados: *${m.qualificados}* (${m.taxaQualif}%)\\n` +\n `\ud83d\udcac Transferidos para humano: *${m.transferidos}*\\n` +\n `\ud83e\udd1d Fechados: *${m.fechados}*\\n` +\n `\ud83c\udfaf Taxa de convers\u00e3o: *${m.taxaConversao}%*\\n\\n` +\n `\ud83d\udcc5 Leads por dia:\\n${barras}\\n\\n` +\n `\ud83d\udcc8 Dia mais movimentado: ${m.diaTop}\\n\\n` +\n `_Relat\u00f3rio gerado automaticamente pelo AutoAtende_ \ud83e\udd16`;\n\nreturn [{ json: { mensagem } }];"
}
},
{
"id": "node-enviar-relatorio",
"name": "Evolution \u2014 Enviar Relat\u00f3rio",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1250,
300
],
"parameters": {
"method": "POST",
"url": "={{ $vars.EVOLUTION_URL }}/message/sendText/{{ $vars.INSTANCE_NAME }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{ $vars.EVOLUTION_API_KEY }}"
}
]
},
"sendBody": true,
"contentType": "json",
"body": "={\n \"number\": \"{{ $vars.TELEFONE_DONO }}\",\n \"text\": \"{{ $json.mensagem }}\"\n}"
}
},
{
"id": "node-log-envio",
"name": "Log \u2014 Relat\u00f3rio Enviado",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
1500,
300
],
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "={{ $vars.SHEETS_ID_CLIENTE }}",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Relat\u00f3rios",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Data": "={{ new Date().toLocaleString('pt-BR', {timeZone:'America/Sao_Paulo'}) }}",
"Total Leads": "={{ $('Calcular M\u00e9tricas da Semana').first().json.total }}",
"Qualificados": "={{ $('Calcular M\u00e9tricas da Semana').first().json.qualificados }}",
"Fechados": "={{ $('Calcular M\u00e9tricas da Semana').first().json.fechados }}",
"Convers\u00e3o %": "={{ $('Calcular M\u00e9tricas da Semana').first().json.taxaConversao }}"
}
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Cron \u2014 Segunda-feira 8h": {
"main": [
[
{
"node": "Sheets \u2014 Ler Leads da Semana",
"type": "main",
"index": 0
}
]
]
},
"Sheets \u2014 Ler Leads da Semana": {
"main": [
[
{
"node": "Calcular M\u00e9tricas da Semana",
"type": "main",
"index": 0
}
]
]
},
"Calcular M\u00e9tricas da Semana": {
"main": [
[
{
"node": "Montar Mensagem do Relat\u00f3rio",
"type": "main",
"index": 0
}
]
]
},
"Montar Mensagem do Relat\u00f3rio": {
"main": [
[
{
"node": "Evolution \u2014 Enviar Relat\u00f3rio",
"type": "main",
"index": 0
}
]
]
},
"Evolution \u2014 Enviar Relat\u00f3rio": {
"main": [
[
{
"node": "Log \u2014 Relat\u00f3rio Enviado",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"tags": [
{
"name": "autoatende"
},
{
"name": "relatorio"
}
]
}
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.
googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AutoAtende — Relatório Semanal Automático. Uses googleSheets, httpRequest. Scheduled trigger; 6 nodes.
Source: https://github.com/HeitorRafael/Auto-Zap/blob/184de9f2ddcc90f94cf5f89d85774f9e3687dcc7/n8n-workflows/daily-report.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.
Complaint Triage Orchestrator (S2.3). Uses httpRequest, googleSheets. Scheduled trigger; 65 nodes.
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
YogiAI. Uses googleSheets, googleSheetsTool, httpRequest, stopAndError. Scheduled trigger; 61 nodes.
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.