GitHub n8n
Você quer receber um evento via API (Webhook), enviar uma mensagem no WhatsApp via Notifish e registrar o resultado (sucesso/erro) em log.
Esse fluxo é útil para:
POST https://meu-dominio.notifish.com/api/v2/{INSTANCE_UUID}/whatsapp/message/groupsAuthorization: Bearer ...Aqui vou usar a opção A (mais “produção”).
Você vai expor um endpoint no n8n, por exemplo:
POST https://SEU_N8N/webhook/notify
Payload recomendado (simples e suficiente):
{
"title": "API 5xx alto",
"message": "Erros 5xx acima do normal em /api/orders",
"url": "https://seu-dashboard",
"identifier": "prod:api:5xx",
"delayMessage": 0
}
Repare que já mandamos identifier. Isso permite deduplicar e evitar spam.
Se você tiver Redis (muito comum), dá para usar um passo “check” antes do envio.
dedupe:{identifier}Se você não tiver Redis, dá para deduplicar com “Data Store” do n8n ou com um endpoint seu.
Vou te passar o fluxo com Data Store do n8n (não depende de infra extra).
O Notifish recebe:
{
"message": "...",
"identifier": "...",
"link": true,
"typing": "composing",
"delayMessage": 1200
}
A gente vai montar isso no n8n.
Depois do envio (sucesso ou falha), registramos em um endpoint de log. Exemplo:
POST https://seu-sistema.com/api/logs/notifish
Log recomendado:
{
"identifier": "prod:api:5xx",
"status": "success",
"http_status": 200,
"provider": "notifish",
"payload": { ... },
"response": { ... },
"created_at": "2026-01-22T00:00:00-03:00"
}
Cria um formato consistente e monta a mensagem final do WhatsApp:
Busca identifier na datastore (dedupe).
Se já existe registro recente, responde 200 “ignored” e não envia.
POST no endpoint do Notifish com Bearer Token.
Salva identifier com TTL (ex.: 300s) para dedupe.
Envia log para seu endpoint.
Se Notifish falhar, manda log com status error.
Abaixo um workflow base. Você só precisa trocar:
NOTIFISH_INSTANCE_UUIDNOTIFISH_TOKENLOG_ENDPOINT_URLImport: n8n → Workflows → Import from file/clipboard
{
"name": "API → Notifish WhatsApp → Log (com dedupe)",
"nodes": [
{
"parameters": {
"path": "notify",
"httpMethod": "POST",
"responseMode": "lastNode",
"options": {}
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [260, 300]
},
{
"parameters": {
"functionCode": "const body = $json;\n\nconst title = body.title || 'Notificação';\nconst msg = body.message || '';\nconst url = body.url || '';\n\nconst identifier = body.identifier || `generic:${Date.now()}`;\nconst delayMessage = body.delayMessage ?? 0;\n\nconst whatsappMessage = `*${title}*\\n\\n${msg}${url ? `\\n\\n${url}` : ''}`;\n\nreturn [{\n identifier,\n delayMessage,\n notifishPayload: {\n message: whatsappMessage,\n identifier,\n link: true,\n typing: 'composing',\n delayMessage\n },\n original: body\n}];"
},
"name": "Normalize",
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [520, 300]
},
{
"parameters": {
"operation": "get",
"key": "={{$json.identifier}}"
},
"name": "Dedupe Get",
"type": "n8n-nodes-base.dataStore",
"typeVersion": 1,
"position": [760, 300]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json.value !== undefined && $json.value !== null}}",
"value2": true
}
]
}
},
"name": "Já enviou?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [980, 300]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\"status\":\"ignored\",\"reason\":\"dedupe\",\"identifier\":\"{{$json.identifier}}\"}",
"options": {}
},
"name": "Return Ignored",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [1210, 200]
},
{
"parameters": {
"url": "https://meu-dominio.notifish.com/api/v2/NOTIFISH_INSTANCE_UUID/whatsapp/message/groups",
"method": "POST",
"authentication": "none",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer NOTIFISH_TOKEN"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Accept",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "json",
"jsonBody": "={{$json.notifishPayload}}",
"options": {
"timeout": 8000
}
},
"name": "Send Notifish",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [1210, 380]
},
{
"parameters": {
"operation": "set",
"key": "={{$json.identifier}}",
"value": "={{JSON.stringify({sentAt: new Date().toISOString()})}}"
},
"name": "Dedupe Set",
"type": "n8n-nodes-base.dataStore",
"typeVersion": 1,
"position": [1450, 380]
},
{
"parameters": {
"url": "LOG_ENDPOINT_URL",
"method": "POST",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "json",
"jsonBody": "={{ {\n identifier: $json.identifier,\n status: 'success',\n provider: 'notifish',\n response: $json,\n created_at: new Date().toISOString()\n} }}"
},
"name": "Log Success",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [1690, 380]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\"status\":\"sent\",\"identifier\":\"{{$json.identifier}}\"}",
"options": {}
},
"name": "Return OK",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [1910, 380]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Normalize",
"type": "main",
"index": 0
}
]
]
},
"Normalize": {
"main": [
[
{
"node": "Dedupe Get",
"type": "main",
"index": 0
}
]
]
},
"Dedupe Get": {
"main": [
[
{
"node": "Já enviou?",
"type": "main",
"index": 0
}
]
]
},
"Já enviou?": {
"main": [
[
{
"node": "Return Ignored",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Notifish",
"type": "main",
"index": 0
}
]
]
},
"Send Notifish": {
"main": [
[
{
"node": "Dedupe Set",
"type": "main",
"index": 0
}
]
]
},
"Dedupe Set": {
"main": [
[
{
"node": "Log Success",
"type": "main",
"index": 0
}
]
]
},
"Log Success": {
"main": [
[
{
"node": "Return OK",
"type": "main",
"index": 0
}
]
]
}
},
"active": false
}
Ele salva “para sempre” se você não limpar. Em produção, o ideal é:
Se você quiser, eu te mando a versão com Redis (TTL real).
Se você não tiver endpoint pronto, você pode logar em:
ou até em um arquivo via API sua
PostgreSQL/MySQL via node de banco
Google Sheets (rápido)
WhatsApp é um canal excelente para alerta porque ele tem uma característica que e-mail e…
Durante alguns anos, o AMP foi tratado como solução quase obrigatória para quem queria desempenho…
Performance, acessibilidade e boas práticas deixaram de ser “detalhes técnicos” e passaram a impactar diretamente…
Automação deixou de ser algo exclusivo de grandes sistemas. Hoje, boa parte das aplicações depende…
Durante muito tempo, o WhatsApp foi visto apenas como um canal de comunicação direta: mensagens,…
Depois de instalar a Evolution API (via Orion), muita gente trava no mesmo ponto: “ok,…