CORTEXFLOW · FREE FOREVER

Chatbots

Fix n8n WhatsApp Trigger Not Firing in Production (5 Fixes That Actually Register the Webhook)

Fix n8n WhatsApp Trigger Not Firing in Production (5 Fixes That Actually Register the Webhook)
FIG. 01 — Fix n8n WhatsApp Trigger Not Firing in Production (5 Fixes That Actually Register the Webhook)SCALE 16:9

Your n8n workflow is Active. The WhatsApp Trigger node is configured, credentials validate, Meta’s webhook verification passed with a green check. You send a message from your phone to the business number — and nothing happens. No execution, not even a failed one. The workflow simply does not fire.

This is the most reported WhatsApp problem on the n8n forum, and the confusing part is that everything looks wired up. The truth is that getting a WhatsApp message into n8n requires three independent registrations to agree with each other: n8n’s own webhook address, Meta’s callback configuration, and the app’s subscription to your WhatsApp Business Account (WABA). A gap in any one of them causes silent drops.

By the end of this article, you will have: the five exact fixes in the order you should try them — which takes under 10 minutes to work through — plus a verification routine that proves Meta’s servers can actually reach your workflow before you burn another afternoon guessing.

Prerequisites

  • An n8n instance (self-hosted 2.30.8+ or n8n Cloud) with a WhatsApp Business credential (App ID + App Secret from your Meta developer app)
  • A Meta developer app with the WhatsApp product added, and a WhatsApp Business Account (test number works for diagnosis)
  • Your n8n instance reachable over HTTPS from the public internet (tunnel or reverse proxy — see below)
  • The reference threads: WhatsApp Trigger not firing and webhook subscription conflict on community.n8n.io

Terminology used in this article:

  • WABA: WhatsApp Business Account — the Meta-side account that owns your business phone number. One WABA can have only one subscribed webhook app at a time.
  • Test URL vs production URL: every n8n trigger node has two webhook addresses. The test URL (/webhook-test/...) only listens for 120 seconds after you click “Listen for test event”. The production URL (/webhook/...) only receives traffic while the workflow is Active (published).
  • subscribed_apps: Meta’s endpoint (GET|POST /{WABA_ID}/subscribed_apps) that controls which Meta app receives events for a WABA. If no app is subscribed, Meta sends no webhooks at all — silently.
  • Verify token: the secret Meta echoes back during webhook verification. For the WhatsApp Trigger, n8n generates this from the trigger node’s own ID — you must not type your own token on Meta’s side.

Root cause: three registrations, one silent failure

Draw the path a message must travel:

  1. Someone messages your business number → Meta’s servers look up which app is subscribed to that WABA (subscribed_apps).
  2. Meta POSTs to the callback URL it registered during verification.
  3. That URL must match the production webhook URL of your Active workflow.

Break any link and the message dies with no error on your side. The forum evidence clusters into five distinct breaks, each with its own fix.

Isometric webhook registration switchboard machine: Meta's Cloud API line plugs into a panel with two jacks, TEST and PRODUCTION, and a SUBSCRIBE lever must be pressed down (POST /WABA_ID/subscribed_apps) before message cartridges can roll through the open gate into n8n
Fig 1 — The webhook registration switchboard. Meta's Cloud API line must be patched into the PRODUCTION jack (the Active workflow's /webhook/ URL) and the SUBSCRIBE lever must be down (POST /{WABA_ID}/subscribed_apps) before message cartridges can roll through the gate into n8n. The TEST jack only listens for 120 seconds.

Step 1 - Publish the workflow and stop listening on the test URL

This is the fix that resolves the majority of reports. The WhatsApp Trigger registers one callback URL with Meta. If you built the workflow with “Execute step” and the listener, Meta may know the test URL — which goes deaf 120 seconds after you stop listening — while your real traffic arrives at the production URL that nothing registered.

Short paragraph on why: production traffic is served from the published snapshot of the workflow, a separate copy from the draft you edit on the canvas. Manual executions run the draft. The test URL exists only for the editor session.

  1. In the n8n editor, click the workflow’s Active toggle so it is on (published). The toggle must stay on — Meta’s verification during activation registers the subscription.
  2. Stop clicking “Execute step” / “Listen for test event” on the trigger. Watch the Executions tab in the left sidebar instead — production runs appear there, never on the canvas.
  3. Send a test message from the phone associated with your WABA test number. A production execution should appear within seconds.

You should see: a new entry in Executions with the incoming message payload. If you see no execution at all, the problem is upstream of n8n — continue to Step 2.

Warning: deleting the trigger node or toggling Active off and on later re-registers the webhook. Do that deliberately (it is Step 5’s tool), not by accident while debugging.

Step 2 - Pin N8N_WEBHOOK_URL to your public HTTPS address

If Meta rejected verification with a generic “Bad request — please check your parameters / Invalid parameter” and no field was named, Meta is rejecting the callback URL n8n handed it — almost always because it is not a public HTTPS URL.

Why: unless overridden, n8n builds its webhook URL from N8N_PROTOCOL, N8N_HOST and N8N_PORT. On Docker (especially Docker Desktop) this comes out as http://localhost:5678/ — unreachable from Meta’s servers and rejected by Meta for lacking HTTPS. (This exact localhost trap also breaks plain webhook setups behind a reverse proxy — see our localhost reverse-proxy fix.)

  1. Set the override to your full public address, scheme included, with a trailing slash:
    N8N_WEBHOOK_URL=https://n8n.your-domain.com/
    In Docker Compose, put it in the environment: block of the n8n service (or an .env file that the Compose file actually references via env_file: — a .env that never reaches the process is a classic silent failure).
  2. Restart the n8n container so the new value takes effect, then deactivate and reactivate the workflow to re-register the callback with Meta.
  3. What each part does: N8N_WEBHOOK_URL is the single source of truth for every webhook address n8n advertises, including the one the WhatsApp Trigger registers with Meta on activation. Pasting a bare subdomain without https:// produces the same “Invalid parameter” rejection — the scheme matters. Note: the older WEBHOOK_URL name is deprecated from n8n 2.35 (still works, logs a warning); use N8N_WEBHOOK_URL.

You should see: the trigger node’s production URL now shows https://n8n.your-domain.com/webhook/... instead of http://localhost:5678/....

Two tunnel-specific traps worth ruling out while you are here:

  • ngrok free tier serves an interstitial “you are about to visit” warning page to callers it does not recognize as a browser — and Meta’s verification request is exactly that kind of caller. If Meta receives the interstitial instead of n8n’s challenge response, you get the same generic “Invalid parameter”. Either use a tunnel without the interstitial (Cloudflare Tunnel is the common choice) or a real domain.
  • Rotating tunnel URLs: on ngrok’s free plan the URL changes every restart, so you must update N8N_WEBHOOK_URL, restart n8n, and re-verify with Meta every single time. A stable subdomain or domain eliminates this class of bug permanently.

Step 3 - Subscribe your app to the WABA (the step everyone skips)

Clearing a conflict and restoring delivery are two separate API calls, and the second one is the one people forget. After any unsubscribe — or on a fresh setup — Meta sends zero webhooks for a WABA with no subscribed app. No error, no execution, nothing.

Why: subscribed_apps is the registry Meta checks before routing a message. n8n’s activation registers the callback URL, but the WABA-level subscription is a separate record that can be missing or point at a different app.

  1. In the Graph API Explorer, select your Meta app and a token with whatsapp_business_management permission, then run:
    GET /{your-WABA-ID}/subscribed_apps
    If the response does not list your app, that is your root cause.
  2. Re-subscribe — no request body needed:
    POST /{your-WABA-ID}/subscribed_apps
  3. Leave Meta’s Configure Webhooks fields alone. The WhatsApp Trigger registers the subscription itself on publish and uses the trigger node’s own ID as the verify token, so any token you type in manually on Meta’s side can never match — that mismatch is exactly what the “response does not match challenge” error is.
  4. In n8n, deactivate the workflow, wait a few seconds, and reactivate it to force a fresh registration.

You should see: GET /{WABA_ID}/subscribed_apps now lists your app, and incoming messages produce executions.

Step 4 - Confirm the messages webhook field is subscribed

Even with a healthy subscription, Meta silently drops incoming events if the messages field is not ticked.

Why: Meta lets you subscribe to granular webhook fields. Registration can succeed while no fields are selected, which looks green everywhere and delivers nothing.

  1. Go to Meta App Dashboard → your app → WhatsApp → Configuration.
  2. Under Webhook fields, make sure messages is explicitly marked Subscribed (check the box; “Configured” alone is not enough).
  3. While here, confirm the callback URL shown is your current production URL, not an old tunnel address or the test URL.

You should see: messages: Subscribed in the dashboard. Send a test message — executions should now appear.

Step 5 - Clear a stale or conflicting subscription (the stubborn case)

Meta allows one webhook URL per WhatsApp Business Account. If you previously registered a webhook on the same number or account — from another app, an earlier n8n setup, or a tool you were testing — Meta keeps sending to the old URL, and activating the new workflow throws a “webhook subscription conflict” error. Several forum users lost days to this before finding the stale record.

  1. Audit for duplicates first: check all workflows (active and inactive) that use the same Meta App ID. Even a deactivated duplicate can hold the subscription lock.
  2. Check which app your WABA is actually subscribed to:
    GET /{your-WABA-ID}/subscribed_apps
    If it points at a different app than the one holding your current webhook, real messages reach only that app.
  3. Remove the stale registration:
    DELETE /{your-WABA-ID}/subscribed_apps
    Then re-subscribe your app (POST, Step 3) and toggle the n8n workflow Inactive → Active to register cleanly.
  4. If the conflict persists after the Meta side is clean, n8n itself may hold a cached webhook registration in its database that survives credential deletion and recreation. The fastest fix: fully stop the workflow, delete the entire WhatsApp Trigger node, save, re-add it fresh, re-enter credentials, and activate. This forces n8n to drop its internal record and register from scratch.

You should see: activation succeeds without the conflict error, and the callback URL in the Meta dashboard matches your production URL exactly.

Step 6 - Verify end-to-end, then lock it down

Run this checklist once, in order. Every item must pass:

  1. Workflow is Active (toggle on, not just saved).
  2. Trigger node’s production URL starts with your public HTTPS domain — never http://localhost.
  3. GET /{WABA_ID}/subscribed_apps lists your app.
  4. Meta dashboard shows your production callback URL and messages: Subscribed.
  5. Send a message from the WABA’s number (or an allowed test recipient if you are still on the Meta test number — test numbers only deliver to whitelisted recipients). An execution appears in the Executions tab within seconds.

If everything above passes but real customer numbers still fail, you have left n8n territory: the Meta app is likely still in development mode, the number is not registered on the WABA, or the temporary access token expired (~24h — create a System User token with whatsapp_business_messaging + whatsapp_business_management for a permanent one). And if the customer has not messaged you in 24 hours, WhatsApp blocks normal replies — you need a pre-approved template, which is a Meta policy, not an n8n bug.

Prevent it next time:

  • Pin the address permanently. A stable domain + N8N_WEBHOOK_URL set once beats re-verifying a rotating tunnel URL every restart.
  • Never type a verify token on Meta’s side. n8n owns that handshake; manual tokens guarantee a mismatch.
  • Treat Active as the test mode. For trigger workflows, the editor’s “Listen for test event” is a trap for WhatsApp — test against the production URL with real executions.
  • Keep one app per WABA. Before registering a second tool or rebuilding, run the GET subscribed_apps check so stale registrations never accumulate silently.

FAQ

My trigger works with the test number but not my real number — is the webhook broken?

Probably not. When it works with the test number, check the Meta side: the real number must be added and registered in the WhatsApp Business setup, the Meta app must be in Live mode (not development), the webhook must point at the production URL, and the workflow must be published. Test numbers only deliver to whitelisted recipients — that restriction alone explains most “works in testing” reports.

Why does verification pass but no messages arrive?

Passing verification only proves the callback URL is reachable — it says nothing about whether Meta will route events to it. Routing depends on subscribed_apps (Step 3) and the messages field subscription (Step 4). This is the single most misunderstood part of the setup.

Can I just use a regular Webhook node instead of the WhatsApp Trigger?

You can — several forum users report it is more predictable — but you then own the handshake yourself: callback verification (hub.mode/hub.verify_token/hub.challenge), the verify token matching, and parsing Meta’s event payload. The trigger node does all of that for free when its three registrations agree. Fix the registrations first; fall back to a manual webhook only if you need custom verification logic.

I get “response does not match challenge” — what does that mean?

Meta echoed a challenge to your callback URL and the response did not contain the expected token. The common cause: you typed your own verify token into Meta’s Configure Webhooks fields. The WhatsApp Trigger uses its own node ID as the token — clear those fields and let the trigger register itself on activation (Step 3).

Does this apply to n8n Cloud too?

The same three registrations apply, but n8n Cloud removes the address problem: your instance has a stable public HTTPS URL, so N8N_WEBHOOK_URL is handled for you. Cloud users who hit this almost always land on Steps 1, 3, or 4.

Conclusion

A WhatsApp message dies silently when any of three registrations disagrees: n8n’s advertised webhook address, Meta’s callback configuration, and the WABA’s subscribed_apps record. Work the five fixes in order — publish the workflow, pin N8N_WEBHOOK_URL to public HTTPS, POST /{WABA_ID}/subscribed_apps, tick the messages field, clear stale subscriptions — and verify with the five-point checklist before touching anything else.

Key takeaways:

  • Every trigger node has two URLs; Meta knows only one, and the test URL dies 120 seconds after you stop listening.
  • n8n builds its callback URL from N8N_HOST — on Docker that means http://localhost:5678 unless you set N8N_WEBHOOK_URL=https://.../.
  • GET /{WABA_ID}/subscribed_apps is the single most useful diagnostic; a missing or wrong entry explains total silence.
  • The trigger node owns the verify-token handshake — never type your own token into Meta’s dashboard.
  • One WABA, one webhook URL: stale registrations from old setups keep stealing your events until you DELETE them.

Next step: if your trigger is now firing and you want to turn it into something useful, build the actual bot — our WhatsApp AI chatbot guide walks through the Meta Cloud API setup with n8n end to end.

Images: none — no license-verified stock images were available for this topic, so none were used rather than an unrelated one.

DOC. CF-RSS-001 · FORMAT: XML

Want more like this?

Practical tutorials on AI agents, automation, and chatbots — straight to your reader.

Subscribe via RSS

Doc. CF-NL-001 · Dispatch

Get the next build in your inbox

One practical email per new post. No spam, unsubscribe anytime.

One email per new post. No spam. Unsubscribe anytime.