My n8n webhooks are not arriving
The test URL works and the production one does nothing, or the address n8n gives you points at your own machine. Two different problems, both fixable.
What you are seeing
The webhook URL n8n shows you starts with localhost or an internal address, and the service you pasted it into cannot reach it.
Or the URL looks right, testing works while you watch it, and nothing arrives once you stop watching.
Why it happens
Problem one: n8n is telling people the wrong address
n8n has no way of knowing what address the outside world sees. It builds the webhook URL it shows you from what you told it, and if you told it nothing, it says localhost, because that is where it is listening.
That URL is not decoration. It is what you hand to Stripe or GitHub or your form tool, and they will try to reach it exactly as written.
Problem two: the test URL and the production URL are different things
The test URL only exists while you have the editor open and have clicked to listen for an event. It is a temporary listener for building, and it stops the moment you stop watching.
The production URL only works when the workflow is switched on. An inactive workflow returns nothing at its production address, and this catches almost everybody once.
Problem three, the quiet one: nothing can reach your machine anyway
A home connection usually has no public address, no open port and no certificate. The webhook never gets close enough to n8n for n8n to be the problem.
The development tunnel that n8n offers is for building, not for running. It is not a stable address, it is not meant to be one, and pointing a live integration at it is a slow way to discover that.
How to fix it
Tell n8n its real address
Set these to the address the outside world uses, restart, and reopen the workflow. The URL shown in the editor should change to the public one. If it did not, the variables are not reaching the process.
services:
n8n:
image: docker.n8n.io/n8nio/n8n:1.70.0
environment:
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- N8N_PORT=5678
- WEBHOOK_URL=https://n8n.example.com/
- N8N_EDITOR_BASE_URL=https://n8n.example.com/
- N8N_PROXY_HOPS=1 # you are behind exactly one proxy
ports:
- "127.0.0.1:5678:5678" Put something in front of it that has a certificate
n8n should not be the thing facing the internet. Terminate the certificate in front and pass the request through. Caddy is the shortest version of this, because the certificate is automatic.
n8n.example.com {
reverse_proxy 127.0.0.1:5678
} Then check the three things that are not the address
Switch the workflow on. The production URL does nothing while it is inactive.
Use the production URL, not the test one. They differ by one path segment and they behave completely differently.
Confirm the request reaches you at all. Send one yourself from somewhere outside your network, and watch the logs of whatever is in front of n8n. If it never appears there, the problem is in front of n8n and no n8n setting will fix it.
# From a machine that is not on your network
curl -i -X POST https://n8n.example.com/webhook/your-path -d '{"hello":"world"}' Stopping it happening again
Give it a permanent address once
A name that does not change, a certificate that renews itself, and the address variables set to match. Every webhook problem after that is a real one about the workflow rather than about plumbing.
If your address changes, remember that every integration you have already registered is still pointing at the old one. Nothing tells you. They just stop.