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": "MensalliZap - Anivers\u00e1rio Autom\u00e1tico",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"id": "schedule-trigger",
"name": "Disparo Di\u00e1rio (8h)",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
250,
300
]
},
{
"parameters": {
"method": "GET",
"url": "https://zvlnkkmcytjtridiojxx.supabase.co/rest/v1/vw_aniversariantes_do_dia",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
}
]
},
"options": {}
},
"id": "buscar-aniversariantes",
"name": "Buscar Aniversariantes",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
500,
300
]
},
{
"parameters": {
"jsCode": "// Criar mensagem de anivers\u00e1rio para cada aluno\nconst FALLBACK_ANIVERSARIO = 'Parab\u00e9ns, {{nomeCliente}}! \ud83c\udf82\ud83c\udf89\\n\\nHoje \u00e9 um dia muito especial! A equipe {{nomeEmpresa}} deseja a voc\u00ea um feliz anivers\u00e1rio cheio de sa\u00fade, alegria e conquistas!\\n\\nObrigado por fazer parte da nossa fam\u00edlia! \ud83d\udc9b\\n\\n_{{nomeEmpresa}}_';\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n const data = item.json;\n\n let mensagem = data.template_mensagem;\n if (!mensagem || mensagem.trim() === '') {\n console.log(`${data.nome_cliente}: sem template birthday, usando fallback`);\n mensagem = FALLBACK_ANIVERSARIO;\n }\n\n const variaveis = {\n '{{nomeCliente}}': data.nome_cliente || 'Aluno',\n '{{nomeEmpresa}}': data.nome_empresa || 'Equipe'\n };\n\n Object.entries(variaveis).forEach(([chave, valor]) => {\n mensagem = mensagem.replace(new RegExp(chave, 'g'), valor);\n });\n\n let telefone = String(data.telefone || '').replace(/\\D/g, '');\n if (!telefone.startsWith('55')) telefone = '55' + telefone;\n\n results.push({\n json: {\n ...data,\n mensagem,\n telefone,\n evolution_url: `${data.evolution_api_url}/message/sendText/${data.evolution_instance_name}`,\n tipo_lembrete: 'aniversario'\n }\n });\n}\n\nreturn results;"
},
"id": "criar-msg-aniversario",
"name": "Criar Mensagem",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
750,
300
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (let i = 0; i < items.length; i++) {\n const data = items[i].json;\n if (i > 0) await new Promise(r => setTimeout(r, 1000));\n\n try {\n const resp = await this.helpers.httpRequest({\n method: 'POST',\n url: data.evolution_url,\n headers: { 'Content-Type': 'application/json', 'apikey': data.evolution_api_key },\n body: { number: data.telefone, text: data.mensagem },\n returnFullResponse: true,\n ignoreHttpStatusErrors: true,\n json: true\n });\n\n const body = resp.body;\n const statusCode = resp.statusCode;\n\n if (statusCode >= 200 && statusCode < 300 && body?.key?.id) {\n results.push({ json: { ...data, envio_sucesso: true, response_id: body.key.id, http_status: statusCode, response_api: body } });\n } else {\n let erroCodigo = `http_${statusCode}`;\n let erroMsg = body?.response?.message || body?.message || `HTTP ${statusCode}`;\n if (statusCode === 500) { erroCodigo = 'instance_500'; erroMsg = 'Inst\u00e2ncia retornou 500 (prov\u00e1vel desconex\u00e3o)'; }\n else if (statusCode === 404) { erroCodigo = 'instance_not_found'; erroMsg = 'Inst\u00e2ncia n\u00e3o encontrada na Evolution'; }\n else if (statusCode === 401 || statusCode === 403) { erroCodigo = 'auth_failed'; erroMsg = 'Credencial Evolution inv\u00e1lida'; }\n else if (statusCode === 400) { erroCodigo = 'bad_request'; }\n results.push({ json: { ...data, envio_sucesso: false, erro_mensagem: typeof erroMsg === 'string' ? erroMsg : JSON.stringify(erroMsg), erro_codigo: erroCodigo, http_status: statusCode, response_api: body } });\n }\n } catch (err) {\n results.push({ json: { ...data, envio_sucesso: false, erro_mensagem: err.message || 'Erro de conex\u00e3o', erro_codigo: err.code ? `network_${String(err.code).toLowerCase()}` : 'exception', http_status: null, response_api: { name: err.name, message: err.message, code: err.code } } });\n }\n}\n\nreturn results;"
},
"id": "enviar-aniversario",
"name": "Enviar Anivers\u00e1rio",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1000,
300
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.envio_sucesso }}",
"value2": true
}
]
}
},
"id": "if-sucesso",
"name": "Envio OK?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1500,
300
]
},
{
"parameters": {
"method": "PATCH",
"url": "=https://zvlnkkmcytjtridiojxx.supabase.co/rest/v1/devedores?id=eq.{{ $('Envio OK?').item.json.devedor_id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"enviado_aniversario_em\": \"{{ new Date().toISOString().split('T')[0] }}\"\n}",
"options": {}
},
"id": "marcar-aniversario",
"name": "Marcar Enviado",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1750,
200
]
},
{
"parameters": {
"method": "PATCH",
"url": "=https://zvlnkkmcytjtridiojxx.supabase.co/rest/v1/controle_planos?user_id=eq.{{ $('Envio OK?').item.json.user_id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"usage_count\": {{ ($('Envio OK?').item.json.usage_count || 0) + 1 }},\n \"updated_at\": \"{{ new Date().toISOString() }}\"\n}",
"options": {}
},
"id": "incrementar-usage",
"name": "Incrementar Usage",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2000,
200
]
},
{
"parameters": {
"method": "POST",
"url": "https://zvlnkkmcytjtridiojxx.supabase.co/rest/v1/logs_mensagens",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"{{ $('Envio OK?').item.json.user_id }}\",\n \"devedor_id\": \"{{ $('Envio OK?').item.json.devedor_id }}\",\n \"telefone\": \"{{ $('Envio OK?').item.json.telefone }}\",\n \"mensagem\": {{ JSON.stringify($('Envio OK?').item.json.mensagem) }},\n \"tipo\": \"birthday\",\n \"status\": \"enviado\",\n \"http_status\": {{ JSON.stringify($('Envio OK?').item.json.http_status ?? null) }},\n \"response_api\": {{ JSON.stringify($('Envio OK?').item.json.response_api ?? null) }}\n}",
"options": {}
},
"id": "log-aniversario",
"name": "Log Anivers\u00e1rio",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2250,
200
]
},
{
"parameters": {
"method": "POST",
"url": "https://zvlnkkmcytjtridiojxx.supabase.co/rest/v1/logs_mensagens",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"{{ $('Envio OK?').item.json.user_id }}\",\n \"devedor_id\": \"{{ $('Envio OK?').item.json.devedor_id }}\",\n \"telefone\": \"{{ $('Envio OK?').item.json.telefone }}\",\n \"mensagem\": {{ JSON.stringify($('Envio OK?').item.json.mensagem) }},\n \"tipo\": \"birthday\",\n \"status\": \"falha\",\n \"erro\": {{ JSON.stringify($('Envio OK?').item.json.erro_mensagem || 'Erro desconhecido') }},\n \"erro_codigo\": {{ JSON.stringify($('Envio OK?').item.json.erro_codigo || null) }},\n \"http_status\": {{ JSON.stringify($('Envio OK?').item.json.http_status ?? null) }},\n \"response_api\": {{ JSON.stringify($('Envio OK?').item.json.response_api ?? null) }}\n}",
"options": {}
},
"id": "log-falha",
"name": "Log Falha",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1750,
450
]
}
],
"connections": {
"Disparo Di\u00e1rio (8h)": {
"main": [
[
{
"node": "Buscar Aniversariantes",
"type": "main",
"index": 0
}
]
]
},
"Buscar Aniversariantes": {
"main": [
[
{
"node": "Criar Mensagem",
"type": "main",
"index": 0
}
]
]
},
"Criar Mensagem": {
"main": [
[
{
"node": "Enviar Anivers\u00e1rio",
"type": "main",
"index": 0
}
]
]
},
"Enviar Anivers\u00e1rio": {
"main": [
[
{
"node": "Envio OK?",
"type": "main",
"index": 0
}
]
]
},
"Envio OK?": {
"main": [
[
{
"node": "Marcar Enviado",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Falha",
"type": "main",
"index": 0
}
]
]
},
"Marcar Enviado": {
"main": [
[
{
"node": "Incrementar Usage",
"type": "main",
"index": 0
}
]
]
},
"Incrementar Usage": {
"main": [
[
{
"node": "Log Anivers\u00e1rio",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
MensalliZap - Aniversário Automático. Uses httpRequest. Scheduled trigger; 9 nodes.
Source: https://github.com/Caiolcn/sistema-cobranca/blob/46ea6a3aee3efb5f1043713ca8238bf882ef3bc6/n8n-workflows/agente-aniversario.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.
Template 14310. Uses httpRequest, stopAndError, slack, gmail. Scheduled trigger; 53 nodes.
🧑🏾 Chief of Staff — System Intelligence & Operations. Uses httpRequest, microsoftOutlook. Scheduled trigger; 52 nodes.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 46 nodes.
Reputation Engine — Content Research Agent. Uses httpRequest. Scheduled trigger; 45 nodes.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 44 nodes.