Chapter 22

Webhook: let outside systems call into n8n

The first 21 chapters were all about "n8n going out and doing things" — running on a schedule, calling someone else's API, reading Gmail. This chapter turns it around: you let other people call you. A form is submitted, a LINE bot receives a message, an HA sensor trips, someone pushes to GitHub — all of it reaches n8n through the Webhook node. This is also the last chapter in the book, so stay with it to the wrap-up.

Why Webhook is the last piece of the puzzle

Lay out the trigger types from the last few chapters and one thing stands out:

  • Manual Trigger (Chapter 10) — the workflow only moves when you press the button.
  • Schedule Trigger — the time comes and the workflow moves by itself.
  • Gmail / Slack / Sheets Trigger (Chapter 11) — the SaaS side has a new event and n8n polls for it on a timer to bring it back.
  • The HTTP Request node (Chapter 12) — n8n goes out and calls someone else's API.

What they share: n8n is always the one making the move. One mode is missing — "an outside system wants to wake your workflow up". That is exactly what the Webhook node does.

Webhook comes up in far more situations than you would think:

  • Someone fills in the contact form on your company website, and the data goes into Google Sheets, a Slack notification goes to sales, and a record goes into the CRM.
  • Your LINE Official Account receives a customer message, AI Agent (Chapter 21) produces the reply, and it goes back to LINE.
  • A Home Assistant door sensor detects "someone came home" and triggers an n8n workflow that logs it to Notion and turns off the company VPN while it is at it.
  • Someone opens a PR on GitHub: notify QA, open a Jira ticket, run a round of internal lint.
  • A new order arrives through Stripe / ECPay payments: write it into the ERP, send the invoice, add loyalty points.

Put simply: if the other system has a "webhook" or "callback URL" field you can fill in, it can call into n8n. This chapter covers how to receive the call, how to configure it, how to reply, and how to keep strangers from hammering it.

Chapter goal: build a Webhook node, understand the difference between the Test URL and the Production URL, set up auth to keep strangers out, customize the response with the Respond to Webhook node, and run it once so data really does arrive from outside.

A webhook is your workflow's doorbell

The plainest way to put it:

  • Schedule Trigger is an alarm clock — it goes off when the time comes.
  • The HTTP Request node is you making a phone call — you go out to ask someone something.
  • The Webhook node is a doorbell — someone arrives, presses it, and you know about it.

When you add a Webhook node to a workflow, n8n hands you a URL that looks like this:

https://n8n.woowtech.io/webhook/form-abc123

Anyone (a person, a server, LINE, HA, a curl command) who calls that URL triggers your workflow. Everything that comes in (body, query string, headers) becomes the $json of the workflow's first item — so the nodes after it can pull the values out with an expression ({{ $json.name }} and so on).

In other words, the Webhook node turns your workflow into a simple HTTP API. Any service that knows the URL can trigger it. That is also why Zapier / Make have a "Webhooks" trigger of their own — it is the bridge every automation platform shares.

Tip: The Webhook node and the HTTP Request node in Chapter 12 are a symmetric pair. HTTP Request is "n8n calling out"; Webhook is "someone calling in". Opposite directions, the same HTTP idea underneath.

Two URLs: how Test and Production differ

Open the Webhook node's settings panel and you see two URLs — the first big trap for beginners.

TypeWhen it is liveWhat it is forHow long it stays live
Test URL Only after you press the Listen for test event button inside the node. Testing while you build — press the button, call it once, see what the incoming data looks like. It starts listening when you press the button and closes itself after one event; with no event the docs state no timeout, but in practice it stops after about two minutes, and pressing again reopens it.
Production URL Live permanently once the workflow is Active (the toggle at the top right is on). Going live — the URL you hand to an outside service for the long term. Live for as long as the workflow stays Active; turn Active off and it is a 404.

The differences between the two URLs are small but they matter:

  • The two URLs have different paths — the Test URL is usually /webhook-test/xxx and Production is /webhook/xxx. Look carefully and pick the right one when you copy from the node panel.
  • The Test URL takes one event per trigger and then closes itself, which suits tweaking fields and reading the schema.
  • The Production URL does not show up as the live preview in Executions — to see the records of runs that really happened, open the Executions tab.
Warning: The most common mistake — handing the Test URL to an outside service or a customer. By the time they have it set up and want to use it, you closed listen mode long ago, so nothing ever gets through. The rule for going live: the workflow must be Active, and the URL you hand over must be the Production URL (/webhook/, not /webhook-test/).

Hands-on: catch form data and write it to Google Sheets

The most classic and most useful starter example: expose one URL, let a web form POST what the user typed, and have n8n write it into Google Sheets automatically. Once it works you can wire it straight to the contact form on your own site or landing page.

  1. Create a new workflow and pick Webhook as the first node

    Top right + Add workflow → you land on an empty canvas → click the + in the middle → search the nodes panel for Webhook (under the Triggers category). Add it.

  2. Set the HTTP Method and the Path

    Once the Webhook node is open:

    • Set HTTP Method to POST — a form sending data in uses POST by default.
    • Give Path any memorable English name, for example form-contact. It is appended to the end of the URL.

    Once that is set, the bottom of the node panel shows both URLs:

    Test URL:       https://n8n.woowtech.io/webhook-test/form-contact
    Production URL: https://n8n.woowtech.io/webhook/form-contact
  3. Press Listen for test event and call it once with curl

    Press Listen for test event at the top right of the Webhook node — the node goes into waiting mode (it ends by itself after the first event, and in practice it stops after about two minutes if no event arrives). Open a terminal and use curl to send fake data to the Test URL:

    curl -X POST https://n8n.woowtech.io/webhook-test/form-contact \
      -H "Content-Type: application/json" \
      -d '{"name":"Wang Xiaoming","email":"[email protected]","message":"I would like a quote"}'

    Back on the n8n canvas, the Webhook node turns green and the output panel on the right shows the JSON you just sent. Once you see the data arrive, this step is done.

  4. Wire up a Google Sheets node: Append Row

    Add a Google Sheets node after the Webhook node. Set Operation to Append Row in Sheet. Pick your credential (create one the first time; see Chapter 13). Choose a spreadsheet and a sheet (with the columns name, email, message, received_at already created).

    Switch every field in the Columns block to Expression mode and map them like this:

    name          →  {{ $json.body.name }}
    email         →  {{ $json.body.email }}
    message       →  {{ $json.body.message }}
    received_at   →  {{ $now.toISO() }}

    Note that the Webhook node keeps the body under $json.body, the query string under $json.query, and the headers under $json.headers.

  5. Execute step and confirm the Sheet really has a new row

    Press Execute step on the Google Sheets node — it sends the item the Webhook just received. Open Google Sheets and check whether a row with that data appeared. If it did, the whole chain is connected.

    Webhook → Send Email three-node workflow canvas
    Figure 22-1 The typical three-node shape after a Webhook trigger: an outside POST hits the Webhook node, and the data flows on to the next node to do the work.
  6. Save, then switch Active on at the top right

    Press Save at the top right. Then flip the Active toggle at the top right to on — this step matters, because without it the Production URL is a 404.

  7. Verify by calling the Production URL once

    Back in the terminal, call the Production URL instead (replace /webhook-test/ with /webhook/):

    curl -X POST https://n8n.woowtech.io/webhook/form-contact \
      -H "Content-Type: application/json" \
      -d '{"name":"Li Xiaohua","email":"[email protected]","message":"Live submission"}'

    Another row appears in the Sheet — this URL is now ready to hand to an outside frontend engineer or a customer. For the history, go to the Executions tab in the sidebar.

Tip: The Test URL suits "tuning one call at a time while you build", the Production URL suits "receiving for the long haul once you are live". The two coexist — after the workflow is live you can still press Listen for test event and use the Test URL to tweak fields and watch the result. Save when you are done and it syncs to Production automatically.

HTTP methods: which one to use when

The Webhook node's HTTP Method dropdown offers GET / POST / PUT / PATCH / DELETE / HEAD. In practice you only use the first two often; the rest come up when you are building a REST-style API.

MethodWhat the caller does with itWhere the data isClassic use
GET The outside system wants to "look something up" or "trigger without carrying much data". The query string (the ?key=value after the URL); n8n keeps it in $json.query. A simple ping, a health check, testing by pasting the URL into a browser.
POST The outside system "sends new data" in. The body (JSON or a form); n8n keeps it in $json.body. Form submissions, LINE webhooks, GitHub webhooks, payment callbacks — the one you use most.
PUT The outside system "replaces a whole record" of some resource. The body. Only when you hand n8n to someone else as a REST API.
PATCH The outside system "partially updates" some resource. The body. Same as above, for the case where only a few fields change.
DELETE The outside system "deletes" some resource. The URL path or the query. Same as above; only a REST-style API needs it.

The wrong Method gives you a 404 — the outside system calls with POST while your Webhook node is set to GET, and n8n answers 404 outright (because as far as it is concerned, "this path has no POST route"). When incoming data is stuck, the first thing to do is confirm that both sides use the same Method.

Concept: Pick POST in almost every situation. Use GET only when all you want is a simple "paste the URL in a browser and it fires" trigger; or when the other system's docs say plainly "we use GET/PUT/DELETE", in which case follow what they ask for.

Response modes: what n8n sends back to the caller

The Webhook node's Respond option decides "what HTTP response n8n returns once an outside call comes in". This matters — services like LINE, Slack and Stripe all read what you return to judge whether the webhook succeeded. Answer wrong and they may retry (which gives you duplicate runs) or disable your webhook outright.

Response modeBehaviorWhen to use it
Immediately n8n answers 200 OK with an empty body the moment the request arrives, and the workflow keeps running in the background. The caller only cares "did it arrive" and does not read the content; the workflow takes a long time (an AI Agent generating for 30 seconds) and you do not want to keep the caller waiting; webhooks like Stripe / GitHub that want "an answer within 3 seconds".
When Last Node Finishes The whole workflow runs to the end, and the last node's output goes back as the response. The caller wants the result the workflow produced (for example a LINE bot receives a message and n8n sends the finished reply straight back to LINE). The workflow has to finish within a few seconds.
Using 'Respond to Webhook' Node You name the node in the middle of the workflow that does the answering — drop a Respond to Webhook node at the point you want to reply from. When you need a custom response — the status code, the headers, the body and the content type are all yours to decide. The right choice when you are building an API for someone else.
Streaming Response It streams the answer back piece by piece, usually paired with a node like AI Agent that produces chunked content. When you want a ChatGPT-style frontend that types out live, or a downstream that supports SSE / streaming.

The Respond to Webhook node is the key to that third mode — put it after whichever node you want to answer from (it does not have to be the last one) and you can set:

  • Respond With — the shape of the answer: JSON, Text, Binary File, Redirect, JWT Token, No Data, All Incoming Items, First Incoming Item.
  • Response Code — type the number yourself. Common ones: 200 (success), 201 (Created), 400 (client error), 500 (server error).
  • Response Headers — for example Content-Type: application/json, or CORS-related headers.

Watch out: the Respond to Webhook node only handles the first incoming item; even if the node before it emits many, only the first one is used for the reply. A second Respond to Webhook node in the same workflow is ignored. If the workflow runs to the end without passing through any Respond to Webhook node, n8n answers a standard 200 by itself; if it errors on the way and never reaches the node, it answers 500.

Tip: Not sure which one to pick? — a SaaS webhook on the other end (Stripe / GitHub / a Slack event) means Immediately; a LINE bot or a form that wants to see the reply means When last node finishes; building your own REST API means Using Respond to Webhook Node.

Services that commonly call your webhook

Almost every modern SaaS has a webhook feature — when they have an event to tell you about, they POST to a URL you name. Put your n8n Webhook node's Production URL in that field and the two are wired together. Here are the ones you meet most often:

SourceHow to set it upWatch out for
Google Forms Google Forms has no native webhook — you need Apps Script, or Zapier / Make as a bridge. Or switch to a form service with a native webhook such as Tally or Typeform. If Google Forms is a must, you can also go through the Google Sheets Trigger (form answers get written into a Sheet).
LINE Official Account LINE Developers Console → Messaging API channel → paste the n8n Production URL into Webhook URL. Turn on Use webhook. LINE wants a 200 within 3 seconds, so set Response = Immediately; signature verification uses the X-Line-Signature header.
Home Assistant HA Automation → set Trigger to Webhook and give it a webhook_id → when HA fires (a door sensor, say) it calls the URL you named. Or the other way around, HA receiving a webhook: set the URL on the webhook trigger. When HA calls out you pick the Method and the body yourself, and they have to line up with the Webhook node's settings.
Typeform / Tally Paste the URL on the Integrations or Webhooks tab in the form settings. Every submission then calls your n8n. Their body follows their own schema, so use the Test URL to read the field paths clearly before you map them.
GitHub / GitLab Repo Settings → Webhooks → Add webhook → paste the n8n URL into Payload URL. Pick the events (push / PR / issue). GitHub sends a great many kinds of event, so use an IF node (Chapter 15) to filter down to the ones you care about.
Slack slash command / event Slack App settings → Slash Commands or Event Subscriptions → paste the n8n URL into Request URL. Slack also wants a 200 within 3 seconds; Event Subscriptions sends a verification challenge the first time, and you have to return the challenge field.
Stripe / ECPay / TapPay The webhook / notification URL setting in the payment provider's dashboard. Signature verification, idempotency, retries on failure — always pick Immediately so a 200 goes back fast, and leave the real processing to the nodes behind it.

The rule that holds everywhere: every service sends its webhook in its own JSON schema — trigger it once by hand with the Test URL, pull the body up and read the field paths, and only then write the nodes downstream. Writing $json.body.foo blind usually gives you undefined.

Add auth so nobody can guess the URL and hammer it

Once a Webhook URL is out there, anyone can call it. Someone malicious can stuff junk into your Sheet, fire an expensive AI Agent, or send spam LINE messages. There are several ways to protect it, from the simplest to the most advanced:

MethodWhere to set itSecurityWhen to use it
No auth, relying on a URL that is hard to guess Webhook node Authentication = None. Use a UUID or a long random string as the Path. Low — the URL is the password. Only for internal services you trust (HA, internal tools). Never put it in client side JavaScript or in public documentation.
Basic Auth Set Authentication to Basic Auth and set a username / password. Medium — the caller has to carry Authorization: Basic base64(user:pass) in the header. Simple server-to-server cases, when the other side supports Basic Auth.
Header Auth Set Authentication to Header Auth and name the header and its value (for example X-Api-Key: your-secret-value). Medium — with no header, or the wrong value, n8n answers 401 outright. The convention for most modern APIs, and the "general purpose" option we recommend most.
JWT Set Authentication to JWT Auth and set the secret / algorithm. n8n verifies the signature. High — it comes with an expiry time and signature verification. The caller is a real system that can issue JWTs (enterprise SSO, a mobile app).
HMAC signature verification Set Authentication to None and use a Code node (Chapter 7) to compute the HMAC and compare it with the header. High — every request carries a signature of its own. LINE, Stripe and GitHub all use this; implement it the way their docs describe.
Warning: Even with auth set up, the URL itself should not leak — think of auth as the second lock, with the URL still the first one. Store secrets in Credentials instead of hard-coding them in node fields, so nothing leaks when you take a screenshot or export the workflow.
Danger: A Webhook node with no auth that is open to the world is easy prey for bots that scan for URLs — the usual symptoms are a sudden flood of Executions, runs you cannot explain, and the cost of AI or messaging nodes shooting up. The first thing to do when you see this: turn Active off, change the Path to a new long random string, add Header Auth, and switch it back on.

Worked example: a LINE bot calls n8n and AI Agent replies

Combine Webhook + AI Agent (Chapter 21) + HTTP Request (Chapter 12) into the complete chain "a customer sends a message on LINE, n8n produces a reply with GPT, and it goes back to the customer automatically" — everything from the earlier chapters comes together here in one real build.

  1. Create a Messaging API channel in the LINE Developers Console

    Go to developers.line.biz and sign in → create a Provider → add a Messaging API channel. Fill in the basics and submit.

  2. Get the Channel Secret and the Access Token

    Once the channel exists, go to the Basic settings tab and copy down the Channel Secret; at the bottom of the Messaging API tab, press Issue under Channel Access Token to generate one and copy it. Both of these go into n8n Credentials in a moment.

  3. New n8n workflow: a Webhook node on POST, and the URL it gives you

    Create a new workflow in n8n and add a Webhook node: Method = POST, Path = line-bot, Response = Immediately (LINE wants a 200 within 3 seconds). Copy the Production URL — but you cannot use it yet, because the workflow is not Active. For now, press Listen for test event and build against the Test URL.

  4. On the LINE side, put the n8n URL in Webhook URL

    Back in the LINE Console on the Messaging API tab → Webhook settings → paste the n8n Test URL → turn on Use webhook. Press Verify and it should say Success (LINE really does call it once).

  5. Add the LINE bot as a friend on your phone and send it a message

    Scan the QR code shown in the LINE Console with your phone to add the Official Account as a friend, and send it a "hello". Back on the n8n canvas, the Webhook node turns green and the output shows LINE's payload. Find the path to the message text; it is usually:

    {{ $json.body.events[0].message.text }}      →  the text the user typed
    {{ $json.body.events[0].replyToken }}        →  the token you reply with
    {{ $json.body.events[0].source.userId }}     →  the user's ID
  6. Add an AI Agent node to produce the reply

    Add an AI Agent node (Chapter 21). Use an expression in the Text field to bring in the user's message: {{ $json.body.events[0].message.text }}. Attach a Chat Model (OpenAI GPT-4o mini or another). Add Memory if you want it to remember the conversation.

  7. Add an HTTP Request node to call the LINE Reply API

    Add HTTP Request: Method = POST, URL = https://api.line.me/v2/bot/message/reply, Authentication set to Header Auth, carrying Authorization: Bearer <your-channel-access-token>. Use JSON for the body:

    {
      "replyToken": "{{ $('Webhook').item.json.body.events[0].replyToken }}",
      "messages": [
        { "type": "text", "text": "{{ $json.output }}" }
      ]
    }

    $('Webhook') reaches back to the Webhook node for the replyToken; $json.output is the reply AI Agent has just produced.

  8. Save + Active, then switch the LINE webhook to the Production URL

    Save, then switch Active on. Back in the LINE Console, change the Webhook URL from the Test URL to the Production URL (/webhook/line-bot). Send another message from your phone — the answer comes back in a second.

Concept: This whole chain is the book's demonstration of everything wired together — a Trigger (Webhook), an expression to grab the payload, Credentials to hold the LINE token, AI Agent to produce the content, and HTTP Request to call the LINE API back. You learned every piece in its own chapter; here they are simply joined into one line.

Common pitfalls

  1. You called the Test URL and nothing happened; n8n received nothing

    Two causes: (a) you did not press Listen for test event — the Test URL only lives in listen mode; (b) the listen session expired (it ends after one event, and in practice it also stops when nothing arrives for a while) — just press it again. Also check that you picked the right URL — when you copy, make sure it is the /webhook-test/ one.

  2. Calling the Production URL returns 404 Not Found

    Almost always the workflow is not Active — while the toggle at the top right is off, the Production URL is a 404. The fix: save, then switch Active on at the top right. If it still returns 404 with Active on, check that the Path matches what you are calling (it is case sensitive, and a stray space breaks it).

  3. The webhook arrives but the body is empty

    Their request set no Content-Type, or set it to text/plain instead of application/json — n8n will not parse it for you. Ask them to add the Content-Type: application/json header when they call; or turn on Options → Raw Body on the Webhook node and parse it yourself in a Code node. Also note that the n8n Webhook node caps a single payload at 16MB — anything larger is rejected outright, so large files have to go through an upload URL or be sent in pieces.

  4. You get 405 Method Not Allowed

    The Method the caller uses does not match the Webhook node's setting — they POST while your node is set to GET, or the other way around. Open the node panel and set both sides to the same Method. Sometimes the outside service defaults to GET while you assumed POST, so test it by hand once with curl or Postman.

  5. The caller keeps retrying the same request (the same record is processed many times)

    The caller (Stripe / LINE / GitHub) retries when it does not get a 200 in time. The usual cause is that you picked Response = When last node finishes and the workflow runs past their timeout (LINE is 3 seconds, Stripe is 3 seconds, GitHub is 10 seconds). The fix: switch to Response = Immediately so n8n answers 200 instantly and the processing runs in the background.

  6. Calls come in too fast, n8n rejects them, Executions queue up

    An n8n instance has a concurrency limit — too many calls in a short window and requests jam up or get rejected outright. The fixes: (a) turn on Queue Mode (Appendix B) and add workers; (b) pair it with Split In Batches or a Wait node to stagger the work; (c) split "receive and store" from "process afterwards" into two workflows, where the first only writes and answers fast, and the second reads on a schedule.

  7. Auth is on but the caller keeps getting 401

    They typed the header name or the value wrong — it is case sensitive, and a stray space or a quote around the value makes it fail. Use curl by hand to send the same header they send and test it once; and the header name in their docs has to line up with the field name in the n8n Header Auth node. It can also be the wrong Authentication type (Basic vs Header).

  8. Executions shows no record of the webhook firing

    The Executions tab shows only recent successful runs by default — the filter at the top has Include failed, and you have to turn it on to see the failures. Beyond that, turn on Save Execution Progress in the workflow Settings to see the detail of each node. While you are building, set all three of Save Manual / Save Failed / Save Successful to Save.

Wrapping up: 22 chapters done — now it is your turn

You have worked through the whole Woow n8n Onboarding Guide. From Chapter 1, "What n8n is", to Chapter 22, "Webhook", this learning path took you from "I have heard of Zapier" to "I can wire up a LINE bot myself and give a workflow a brain that thinks". Here is what you can do now:

  • Create a new workflow yourself, drop nodes in, and chain Trigger + Action + Core (Chapters 7–10).
  • Integrate the SaaS your company uses most — Slack, Gmail, Google Sheets, Drive, any service with an API (Chapters 11–13).
  • Write expressions to grab upstream data, branch with IF/Switch, and handle many items with Merge/Split (Chapters 14–16).
  • Handle errors, reshape data, pull reusable logic into a sub-workflow, and write a few lines of Code as an escape hatch (Chapters 17–20).
  • Give a workflow AI judgment, and receive webhooks from outside (Chapters 21–22).

The rest is doing it. Honest advice: find one thing your company has done over and over in the past three months — tidying a report by hand every morning, sending a reminder email every week, replying to every LINE customer with the same canned message — and open a workflow that kills it off. The moment your first workflow goes live you will realize: "so this really does not need a person at all." And then you will not be able to stop.

When you get stuck along the way:

  • You forgot how to configure a node → go back to the matching chapter (the contents list them all at the start).
  • A node with a red border that does not run → see Appendix B · Error troubleshooting.
  • You cannot find a setting → see Appendix A · Settings reference.
  • You want to go deeper on self-hosting → see Appendix C · How it works underneath.

May your workflows all run smoothly, may they go live without incident, and may your boss give you a raise when the automation lands. You can always come back to a chapter, or ask the official n8n community at community.n8n.io — plenty of people are walking the same road.

Tip: The easiest mistake to make once you know n8n is "wanting to automate everything" — first work out "how many times a week does this process run". Something that runs once a week is not necessarily worth two hours of building a workflow. Automate first the things "you do many times a day that need no judgment" — that is where the return is highest.

FAQ

Can crawlers find my Webhook URL, or can outsiders guess it and hammer it?
If the path part of the URL (for example /webhook/form-abc123) is a guessable string like form-abc123, a scanning bot really can stumble onto it. Use a UUID as the path (for example /webhook/8f3b2c9a-...) and the odds get very low. Add Header Auth on top and it is safer still. If you are genuinely worried, treat the URL as only one lock and rely on auth or an IP allowlist as the second.
How many Webhook nodes can one workflow have?
It can have plenty, as long as each one has its own Path. A common pattern is two Webhook nodes in one workflow: one for the real business traffic and one for a health check or an admin action. Or one workflow exposing several endpoints (for example /webhook/order-create and /webhook/order-cancel) that go down different branches.
What if the Webhook node's URL changes? Do the outside services have to be set up again?
Yes. The Webhook URL is generated from the node's Path field — change the Path and the URL changes. Every outside service already holding the old URL has to be changed too, or it gets a 404. Good moments to change it: (a) you find strangers calling the old URL, (b) you are moving to a new workflow, (c) the Path is badly named and needs a refactor. Always tell every downstream service once you have changed it.
Can an n8n Webhook trigger another n8n workflow?
Two ways: (a) workflow A uses the HTTP Request node to call workflow B's Webhook URL — just like an outside service, cleanly isolated but with one round trip over HTTP; (b) workflow A uses the Execute Workflow node (a Core node) to call workflow B directly, passing the data straight across without HTTP, which is faster. For internal calls pick Execute Workflow; only reach for HTTP Request on a Webhook when you cross instances or accounts.
Does the Webhook node have a timeout? Will my workflow be cut off if it runs for 5 minutes?
The Webhook node itself is not cut off — but the caller almost always has a timeout: LINE 3 seconds, GitHub 10 seconds, Stripe a few seconds, a browser usually 30–60 seconds. Go past their timeout and they treat it as a failure (and may retry). The answer for long jobs: set Response to Immediately so a 200 goes back instantly and the real processing runs in the background; notify separately or write the result back once it finishes.
Do the Test URL and the Production URL use the same data format? Is it safe to go straight to Production once Test works?
The format is exactly the same — only the URL path and what triggers it differ. If Test works, Production works. But watch out: while developing against Test you may not have switched Active on or set up sharing on the Credentials, and then a live call gets stuck at some node further down whose credential is disconnected — run the full chain once before you cut over.
How do I debug a webhook? What do I do when a call comes in and I see no log?
Three tricks: (a) use the Test URL plus listen mode to watch the payload live — fastest and most direct; (b) in the workflow Settings, set both Save Successful Executions and Save Failed Executions to Save, then go through the Executions tab record by record; (c) put a Set / Edit Fields node in as the first node that only passes data through, so at least the raw incoming data shows up in Executions.
Can a webhook store the data and process it slowly, instead of chaining the processing nodes onto it?
The usual way to decouple: once the Webhook receives, it does exactly one thing — write into Google Sheets / Postgres / Redis / even an n8n Data Table — and answers 200 straight away with Immediately. Then build a separate Schedule Trigger workflow that reads the new data every minute and processes it. That way the caller always gets an instant answer, and slow processing behind it changes nothing, and a node dying does not lose data. This is the right architecture for high traffic or an unreliable third-party API.