AutomationFlowsSlack & Telegram › Meta Whatsapp Cloud API - Webhook Fan-out (duplicate)

Meta Whatsapp Cloud API - Webhook Fan-out (duplicate)

Meta WhatsApp Cloud API - Webhook Fan-out (Duplicate). Uses httpRequest. Webhook trigger; 16 nodes.

Webhook trigger★★★★☆ complexity16 nodesHTTP Request
Slack & Telegram Trigger: Webhook Nodes: 16 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "id": "bsTKD9MFb3sX0bnU",
  "name": "Meta WhatsApp Cloud API - Webhook Fan-out (Duplicate)",
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "id": "2610b067-dfa9-4a4c-9365-858f5f31c046",
      "name": "Webhook - Verify (GET)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -800,
        -300
      ],
      "parameters": {
        "httpMethod": "GET",
        "path": "meta-wa-fanout",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "b35624d0-2d74-4bc5-8fa1-19ee8f47cf34",
      "name": "Set - Verify Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -680,
        -300
      ],
      "parameters": {
        "mode": "manual",
        "includeOtherFields": true,
        "assignments": {
          "assignments": [
            {
              "id": "assign-verify-token",
              "name": "verify_token",
              "value": "CHANGE_ME_VERIFY_TOKEN",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "56cad50f-443f-4cb6-9f15-f5c9140664f6",
      "name": "IF - Verify Token Valid",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -560,
        -300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-mode",
              "leftValue": "={{ $json.query['hub.mode'] }}",
              "rightValue": "subscribe",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "cond-token",
              "leftValue": "={{ $json.query['hub.verify_token'] }}",
              "rightValue": "={{ $json.verify_token }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "468ef2b9-e28b-4002-93e9-c2fbadf6db8d",
      "name": "Respond - Challenge (200)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -320,
        -380
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query['hub.challenge'] }}",
        "options": {
          "responseCode": 200
        }
      }
    },
    {
      "id": "89bac256-87d5-43e4-865b-13c006eaa2b4",
      "name": "Respond - Verify Failed (403)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -320,
        -220
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "Forbidden",
        "options": {
          "responseCode": 403
        }
      }
    },
    {
      "id": "313b9719-f159-4d1d-bee8-f923122e49b1",
      "name": "Webhook - Events (POST)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -800,
        200
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "meta-wa-fanout",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      }
    },
    {
      "id": "4b6bc82c-8bc8-4ac7-9996-127906a90ede",
      "name": "Set - Signature Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -680,
        200
      ],
      "parameters": {
        "mode": "manual",
        "includeOtherFields": true,
        "assignments": {
          "assignments": [
            {
              "id": "assign-app-secret",
              "name": "app_secret",
              "value": "CHANGE_ME_APP_SECRET",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "df1e2f70-ffbe-4721-aaca-3158279eed06",
      "name": "Code - Validate Signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -560,
        200
      ],
      "parameters": {
        "jsCode": "const crypto = require('crypto');\nconst input = $input.first();\nconst item = input.json;\nconst binary = input.binary && input.binary.data;\nconst rawBody = binary ? Buffer.from(binary.data, 'base64').toString('utf8') : JSON.stringify(item.body || {});\nconst secret = item.app_secret;\nconst headerSig = (item.headers && item.headers['x-hub-signature-256']) || '';\nconst expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');\nconst a = Buffer.from(headerSig);\nconst b = Buffer.from(expected);\nconst valid = a.length === b.length && crypto.timingSafeEqual(a, b);\n\nreturn [{ json: { valid, rawBody, sourceHeaders: item.headers || {} } }];"
      }
    },
    {
      "id": "7e64666e-2951-4358-9738-1208554799ee",
      "name": "IF - Signature Valid",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -320,
        200
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-valid",
              "leftValue": "={{ $json.valid }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "dc120c80-d9fb-4042-8979-8d5b8bd74348",
      "name": "Respond - Ack Meta (200)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -80,
        100
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "EVENT_RECEIVED",
        "options": {
          "responseCode": 200
        }
      }
    },
    {
      "id": "8a895970-f392-4cad-87c0-a1f798c749e0",
      "name": "Respond - Invalid Signature (401)",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -80,
        320
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "Invalid signature",
        "options": {
          "responseCode": 401
        }
      }
    },
    {
      "id": "b9e2473f-cf2c-424f-8b97-342598a06db4",
      "name": "Code - Destinations Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        160,
        100
      ],
      "parameters": {
        "jsCode": "const prev = $input.first().json; // { valid, rawBody, sourceHeaders }\n\n// Edit this array to add/remove/enable destinations.\nconst destinations = [\n  {\n    name: 'chatwoot',\n    url: 'https://YOUR-CHATWOOT-DOMAIN/webhooks/whatsapp/YOUR_PHONE_NUMBER_ID',\n    method: 'POST',\n    headers: {},\n    enabled: false\n  },\n  {\n    name: 'zap-crm-br',\n    url: 'https://YOUR-ZAPCRM-DOMAIN/api/whatsapp/webhook',\n    method: 'POST',\n    headers: {},\n    enabled: false\n  },\n  {\n    name: 'evolution-api',\n    url: 'https://YOUR-EVOLUTION-DOMAIN/webhook/meta/incoming',\n    method: 'POST',\n    headers: {},\n    enabled: false\n  }\n];\n\nreturn [{ json: { destinations, rawBody: prev.rawBody, sourceHeaders: prev.sourceHeaders } }];"
      }
    },
    {
      "id": "0cbf2a30-82c7-416a-962e-fd949cb2124c",
      "name": "Split Out - Per Destination",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        400,
        100
      ],
      "parameters": {
        "fieldToSplitOut": "destinations",
        "include": "allOtherFields",
        "options": {}
      }
    },
    {
      "id": "dbe51bb8-d98a-436a-af65-bf28fae9708e",
      "name": "Filter - Enabled Only",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        640,
        100
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-enabled",
              "leftValue": "={{ $json.destinations.enabled }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "8750825a-db6e-45d9-96a3-eb16d47a5f4f",
      "name": "HTTP Request - Forward Raw Body",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        100
      ],
      "onError": "continueRegularOutput",
      "retryOnFail": true,
      "maxTries": 2,
      "waitBetweenTries": 1000,
      "parameters": {
        "method": "={{ $json.destinations.method || 'POST' }}",
        "url": "={{ $json.destinations.url }}",
        "sendHeaders": true,
        "specifyHeaders": "json",
        "jsonHeaders": "={{ JSON.stringify(Object.assign({ 'Content-Type': ($json.sourceHeaders && $json.sourceHeaders['content-type']) || 'application/json', 'X-Hub-Signature-256': ($json.sourceHeaders && $json.sourceHeaders['x-hub-signature-256']) || '' }, $json.destinations.headers || {})) }}",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "={{ ($json.sourceHeaders && $json.sourceHeaders['content-type']) || 'application/json' }}",
        "body": "={{ $json.rawBody }}",
        "options": {
          "timeout": 10000
        }
      }
    },
    {
      "id": "7f18fe61-7cc7-4fa5-976f-ce89df4fff18",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -800,
        -560
      ],
      "parameters": {
        "content": "## Meta WhatsApp Cloud API \u2014 Webhook Fan-out\n\nRegister this Callback URL in Meta App Dashboard > WhatsApp > Configuration:\n`https://<YOUR-N8N-HOST>/webhook/meta-wa-fanout`\n\nSecrets: fill in 'Set - Verify Config' (verify_token) and 'Set - Signature Config' (app_secret) with real values \u2014 do not commit real values back to a public repo copy.\nDestinations: edit the 'Code - Destinations Config' node to add/enable your destinations. Ships with placeholders for Chatwoot, Zap CRM BR (https://github.com/brunopelatieri/zap-crm-br), and Evolution API \u2014 all three can run in parallel.\nSee SPEC.md and README.md in the repo for full details.\n\n\u26a0\ufe0f Avoid editing/saving this workflow from the n8n web editor UI when possible \u2014 several node options in this n8n version only take effect when set at very specific parameter paths (documented in SPEC.md \u00a713); a UI re-save has been observed to alter them. Prefer redeploying via MCP tooling for structural changes.",
        "height": 300,
        "width": 900,
        "color": 5
      }
    }
  ],
  "connections": {
    "Webhook - Verify (GET)": {
      "main": [
        [
          {
            "node": "Set - Verify Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set - Verify Config": {
      "main": [
        [
          {
            "node": "IF - Verify Token Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Verify Token Valid": {
      "main": [
        [
          {
            "node": "Respond - Challenge (200)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Verify Failed (403)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Events (POST)": {
      "main": [
        [
          {
            "node": "Set - Signature Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set - Signature Config": {
      "main": [
        [
          {
            "node": "Code - Validate Signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Validate Signature": {
      "main": [
        [
          {
            "node": "IF - Signature Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Signature Valid": {
      "main": [
        [
          {
            "node": "Respond - Ack Meta (200)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Invalid Signature (401)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respond - Ack Meta (200)": {
      "main": [
        [
          {
            "node": "Code - Destinations Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Destinations Config": {
      "main": [
        [
          {
            "node": "Split Out - Per Destination",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out - Per Destination": {
      "main": [
        [
          {
            "node": "Filter - Enabled Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter - Enabled Only": {
      "main": [
        [
          {
            "node": "HTTP Request - Forward Raw Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {},
  "staticData": null,
  "meta": null,
  "versionId": "d3a50b35-3896-4f87-bfd5-b7b8d06b943d",
  "tags": [
    {
      "id": "2Lx5qjEW55TRFEBD",
      "name": "Cloud API Meta"
    }
  ]
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Meta WhatsApp Cloud API - Webhook Fan-out (Duplicate). Uses httpRequest. Webhook trigger; 16 nodes.

Source: https://github.com/brunopelatieri/n8n-meta-whatsapp-webhook-duplicate/blob/main/workflow.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

Flujowhatsapp. Uses @aldinokemal2104/n8n-nodes-gowa, postgres, httpRequest. Webhook trigger; 65 nodes.

@Aldinokemal2104/N8N Nodes Gowa, Postgres, HTTP Request
Slack & Telegram

HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant

HTTP Request, Slack
Slack & Telegram

This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS

HTTP Request, Shopify, SendGrid +5
Slack & Telegram

WF_UNIFIED_LEGAL_AUTOMATION. Uses googleSheets, httpRequest, telegram, telegramTrigger. Webhook trigger; 53 nodes.

Google Sheets, HTTP Request, Telegram +1
Slack & Telegram

Backbrief: transcripts (Zoom webhook -> Slack + vault). Uses httpRequest, slack. Webhook trigger; 52 nodes.

HTTP Request, Slack