Skip to main content

n8n Webhook Node: Receive Data from External Services and Trigger Workflows

5 min read Updated:

Most n8n workflows run on a schedule. The Webhook node flips this: instead of n8n polling for data, external services push data to n8n the moment something happens.

A form submission, a Stripe payment, a GitHub push event, a Shopify order — any system that can send an HTTP request can trigger an n8n workflow instantly using the Webhook node.

How the Webhook Node Works

The Webhook node creates a URL endpoint that listens for incoming HTTP requests. When a request arrives at that URL, n8n starts executing the workflow with the request body, headers, and query parameters available as data.

Every Webhook node gets two URLs:

  • Test URL — active only while you have the workflow open in the editor and click “Listen for Test Event.” Useful for building and debugging.
  • Production URL — active whenever the workflow is activated. This is the URL you give to external services.

The URLs follow the pattern:

https://your-n8n-instance.com/webhook/{unique-path}

You can customize the path in the node settings.

Basic Configuration

The key settings in the Webhook node:

HTTP Method — which method the node listens on. POST is most common for receiving data. Use GET for triggering workflows from simple links or cron-style external systems. Set to “Multiple Methods” to handle both.

Path — the URL path after /webhook/. Use a descriptive name like stripe-payment or github-push. Avoid generic names like test in production.

Response Mode — what n8n sends back to the caller:

  • “Respond immediately” (default): returns {"message":"Workflow was started"} instantly, then continues processing asynchronously.
  • “Respond using ‘Respond to Webhook’ node”: lets you control exactly what response to send after processing.
  • “Last node”: returns the output of the last executed node.

For most integrations, “Respond immediately” is correct. Use “Respond to Webhook” node when the calling service needs a specific response body (like Slack slash commands that require an immediate reply).

Accessing Incoming Data

Inside the workflow, the incoming request data is available as:

  • $json.body — the parsed JSON body (if Content-Type is application/json)
  • $json.headers — request headers
  • $json.query — URL query parameters
  • $json.params — path parameters (if you use a parameterized path)

For form submissions (application/x-www-form-urlencoded), the body is also automatically parsed.

Example: a Stripe webhook sends an event like:

{
  "type": "payment_intent.succeeded",
  "data": { "object": { "amount": 5000, "currency": "usd" } }
}

In n8n, you access it as $json.body.type and $json.body.data.object.amount.

Securing Webhooks

An unsecured webhook URL accepts requests from anyone. For production workflows, always add authentication.

Header Authentication — the simplest approach. Set a secret header value that calling services must include. In the Webhook node, set Authentication to “Header Auth” and specify the header name and expected value. Store the secret in n8n credentials, not hardcoded.

Example verification: the caller sends X-Webhook-Secret: your-secret-value. The Webhook node rejects requests without the correct header.

Basic Auth — for services that support HTTP Basic Authentication. The Webhook node handles the verification automatically.

Signature Verification — for services like GitHub, Stripe, and Shopify that sign their webhook payloads with HMAC. The Webhook node does not handle signature verification natively; use a Code node immediately after to verify the signature before processing the payload.

GitHub signature example:

const crypto = require('crypto');
const secret = 'your-github-webhook-secret';
const signature = $json.headers['x-hub-signature-256'];
const payload = JSON.stringify($json.body);
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');

if (signature !== expected) {
  throw new Error('Invalid signature');
}
return $input.all();

Responding to the Caller

When you need to send a specific response back — not just a generic acknowledgment — use the “Respond to Webhook” node.

Set the Webhook node’s Response Mode to “Respond using ‘Respond to Webhook’ node.” Then place a “Respond to Webhook” node anywhere in the flow with the response body and status code you want to return.

This is required for:

  • Slack slash commands (must return a message within 3 seconds)
  • Typeform webhooks that check for 200 responses
  • Any service that validates the webhook response before marking delivery as successful

Common Integration Patterns

Receive → Transform → Store: a form submission comes in, the workflow cleans and validates the data, then writes it to a database or spreadsheet.

Receive → Notify: a monitoring system sends an alert webhook, n8n routes it to Slack or sends an email with enriched context.

Receive → Branch: an e-commerce webhook arrives, an IF node checks the event type (order.created vs order.cancelled), and each branch handles its case differently.

Receive → Acknowledge → Process: the Webhook node responds immediately to satisfy the caller’s timeout requirement, then a long-running process continues asynchronously. This is the standard pattern for Stripe and other payment webhooks.

Debugging Tips

Use the Test URL to capture a real request from the external service before activating the workflow. n8n will show you the exact payload structure, which makes mapping the data much easier than guessing from documentation.

If the external service requires HTTPS and your n8n instance is local, use a tool like ngrok to expose your local instance during development. Never put a local tunnel URL into production.

Check the n8n execution log when a webhook fires unexpectedly or silently fails. The log shows whether the request was received and exactly where execution stopped.

Test vs Production URLs

A common mistake: forgetting to activate the workflow before giving out the production URL. The test URL only works while you are actively listening in the editor. The production URL only works after you click “Activate” on the workflow.

The production URL is permanent and stable — it does not change when you modify the workflow, as long as you keep the same path value. Change the path and you break every integration pointing at the old URL.

The Webhook node is one of the most versatile triggers in n8n. Pair it with any external service that supports webhooks and you can build real-time automations that react to events the moment they happen.

Tools Used in This Article

This article mentions several tools from my tech stack.

Get insights and updates first

Subscribe to get updates on agentic engineering, data pipelines, MCP infrastructure, and new projects straight to your inbox.