Loading tutorials…
Loading tutorials…
n8n webhooks are how your tools tell n8n something happened — Stripe payments, Typeform submissions, custom app events. They are also where most production setups quietly leak data. This walks the right pattern.
Who this is forOperators building integrations between n8n and apps that push data (Stripe, Typeform, Calendly, custom internal tools). If you have ever copied a webhook URL into a vendor and watched silence, this fixes that.
What you'll need
Step 1
The Webhook node shows TWO URLs. Test URL works ONLY while the editor is open. Production URL works when the workflow is Active. Use the right one.
Add a Webhook node to a workflow. The node panel shows two URLs: "Test URL" and "Production URL."
Test URL: works only while the n8n editor is open AND you have clicked "Listen for Test Event." This is for development.
Production URL: works when the workflow is set to Active. This is the URL you give vendors.
Critical: copying the Test URL into Stripe/Typeform/etc. is the #1 webhook setup mistake. It works during your testing session and stops working the moment you close the tab. Vendors retry for a while, then stop. Weeks of data lost silently.
Always: build with Test URL, then switch to Production URL before going live.
Step 2
Set HTTP Method, response mode, and authentication. For most webhooks, POST + "Respond Immediately" + no auth is right.
In the Webhook node settings:
- HTTP Method: usually POST (most webhooks). GET for callback-style integrations.
- Path: leave the default UUID OR set a custom path like `stripe-payments`. Custom paths are easier to remember but less secure.
- Response Mode: "Respond Immediately" sends a 200 OK as soon as n8n receives the webhook (recommended — fast vendor acknowledgement). "Respond When Last Node Finishes" waits for the entire workflow to complete (slow; risks vendor timeout).
- Authentication: "None" for vendors that sign payloads (Stripe, GitHub). "Header Auth" for shared-secret vendors. "Basic Auth" for legacy integrations.
Save the workflow. Copy the Production URL.
Step 3
For webhooks from Stripe, GitHub, Twilio, etc.: validate the request signature in the next node. Reject mismatched signatures.
Most reputable webhook senders sign payloads with HMAC. The signature is in a header (e.g., `Stripe-Signature`, `X-Hub-Signature-256`).
In the next node after Webhook, add a Code or Function node:
```
const crypto = require('crypto')
const signature = $input.first().headers['stripe-signature']
const secret = $env.STRIPE_WEBHOOK_SECRET
const body = JSON.stringify($input.first().body)
// vendor-specific signature verification
const expected = crypto.createHmac('sha256', secret).update(body).digest('hex')
if (signature !== expected) throw new Error('Invalid signature')
return $input.all()
```
Without signature validation, anyone who guesses or scans your webhook URL can inject fake data into your workflow. Skipping this is a real security issue, not a theoretical one.
Step 4
Most webhook senders expect a 200 OK within 5-10 seconds. Set 'Respond Immediately' and process async, OR keep the workflow fast.
If the workflow takes longer than ~10 seconds to complete, the vendor will time out and retry. You will see the same webhook fire multiple times.
Pattern 1 (recommended): "Respond Immediately" mode. The Webhook node returns 200 OK instantly. The rest of the workflow processes async. Fast and safe.
Pattern 2: "Respond When Last Node Finishes." Only use when the vendor needs your processed response. Keep the workflow under 8 seconds total.
For long-running workflows, use Pattern 1 + a "Respond to Webhook" node later in the flow if you need to return data. The Respond to Webhook node sends the response back to the original caller even after async processing.
Step 5
Don't trust your local curl tests alone. Send a real webhook from the vendor's test dashboard. Verify n8n logs the request and processes it.
In the vendor dashboard, find the test/replay feature: Stripe Dashboard → Webhooks → Send test event. Typeform → Connect → Test webhook.
Send a real test from the vendor. Watch the n8n Executions tab in real-time.
Verify three things: (1) the execution appears within a few seconds, (2) the request body matches what you expected, (3) the signature validation passes.
If anything fails, check the vendor side too — most vendor dashboards have a "delivery log" showing the response code n8n returned. A 500 there tells you n8n received the request but errored; a timeout there tells you n8n is taking too long; a 404 means the URL is wrong.
Step 6
Vendors retry webhooks on timeouts or 5xx. Make your workflow safe to receive the same event twice. Use the event ID for deduplication.
Most webhook senders include a unique event ID (e.g., `evt_1234` from Stripe). Use it.
Add a "deduplication" check early in the workflow: store recently-seen event IDs in a small store (Redis, Postgres, n8n Data Tables, or a Google Sheet).
If the event ID has been seen in the last 24 hours, short-circuit the workflow — return 200 to the vendor but skip downstream actions.
Without this, every Stripe payment that times out + retries creates duplicate records, duplicate emails, duplicate Slack notifications. Idempotency is non-negotiable for webhooks that mutate data.
Common mistakes
Using the test URL in production
What goes wrong: You copy the test URL into Stripe during setup. It works during your testing session. You close the editor. From that moment, every Stripe webhook gets a 404. Stripe retries for 3 days, then stops. Three weeks later, you notice a gap in revenue data — but the webhooks are long gone.
How to avoid: Always use the Production URL for live integrations. The Test URL is for development only. Verify the workflow is set to Active before handing the URL to a vendor.
No signature validation
What goes wrong: Webhook URL leaks (in a screenshot, a Slack thread, a former employee's notes). Someone POSTs fake payment events. Your workflow happily creates fake records, sends fake confirmation emails, updates real customer profiles with fake data. Cleanup is forensic.
How to avoid: Validate signatures for every webhook from a vendor that supports it. For internal-only webhooks, use shared-secret header auth. Never trust an unauthenticated webhook URL in production.
No idempotency — duplicate events double-processed
What goes wrong: Stripe retries a payment.succeeded webhook because your workflow returned 200 just after the 10-second timeout. The same payment writes a second order, sends a second confirmation email, charges nothing (no card retry) but creates a phantom $200 of revenue in your reports.
How to avoid: Always dedupe by vendor event ID. Store seen IDs in an external store with a 24-72hr TTL. Skip downstream actions if seen.
Long-running workflow with default response mode
What goes wrong: Workflow takes 30 seconds to process a Typeform submission. Default mode waits for the last node before responding. Typeform times out at 10s, retries 3x. Your workflow processes the same form submission 4 times. Lead duplicated 4x in HubSpot.
How to avoid: Set Response Mode to 'Respond Immediately' for any workflow that takes more than a few seconds. Process async after the 200 OK.
WEBHOOK_URL env var wrong on self-hosted
What goes wrong: Self-hosted n8n. WEBHOOK_URL is set to http://localhost:5678 by default. Production webhook URLs returned to the editor are unreachable from outside. Every external webhook fails. You spend a day debugging the wrong layer.
How to avoid: Set WEBHOOK_URL to your exact public HTTPS URL: `WEBHOOK_URL=https://automations.yourdomain.com/`. Restart the container.
Recap
Done — what's next
How to build your first workflow in n8n
Read the next tutorial
Hand it off
Webhook integrations are easy to build and hard to operate. EverestX automation specialists handle the signature validation, idempotency, and async-response patterns by default. Most teams that build 5+ webhook integrations themselves end up rebuilding all of them with help inside a year.
See specialist rates
Most common cause: you copied the Test URL into the vendor and it stopped working when the editor closed. Always copy the Production URL and ensure the workflow is set to Active.
For self-hosted n8n behind a firewall, you need to either (a) expose port 443 to the public internet via a reverse proxy, or (b) use a tunneling service like Cloudflare Tunnel or ngrok to forward requests. Vendors cannot reach n8n if it is not publicly accessible.
Three steps: (1) Check the vendor's delivery log — did they actually send a request? What response code did they get? (2) Test the URL directly with curl from outside your network. (3) Watch the n8n Executions tab while sending a test webhook from the vendor.
Webhook is the entry point — it receives incoming HTTP requests and starts the workflow. Respond to Webhook is an optional later node that sends a response back to the caller after async processing. Use both together when you want to return processed data, not just an acknowledgement.
n8n webhook URLs use a UUID (or a custom path) that does not auto-rotate. To 'rotate,' create a new workflow with a new webhook node, point the vendor at the new URL, leave the old workflow active for 24-48 hours to catch any in-flight retries, then deactivate the old.
n8n
You have n8n running. Now build one real workflow that does something useful. This walks a real trigger → action chain end-to-end with the expression-mapping detail most tutorials skip.
n8n
Workflows fail silently by default. By the time someone notices the missing data, the gap is unrecoverable. This walks the proper error-handling pattern — error workflow, alerts, retries, and the monitoring that catches the rest.
n8n
Your workflow ran fine for weeks. Now it fails — or worse, it succeeds but produces garbage. This is the diagnostic sequence specialists run to isolate the root cause in 15-30 minutes instead of an afternoon.
n8n
DIY n8n is great until you have 15 workflows and a credentials audit you keep deferring. This is the honest framework: when the cost of self-managing exceeds the cost of a specialist, and how to tell which side you are on.
Zapier
If your app sends data and Zapier needs to receive it instantly, polling won't cut it. Webhooks by Zapier handle the instant case — once you get past the auth, payload-shape, and parsing gotchas that bite every first-timer.