- What a webhook is and how it differs from traditional API polling
- How to create and configure a webhook trigger node in n8n
- How to extract and manipulate incoming JSON data using expressions
- How to connect webhook data to Google Sheets, Slack, or Telegram
- How to secure, debug, and troubleshoot your n8n webhooks
You get a form submission. You copy the data into a spreadsheet. You paste the email into your CRM. You send a Slack message to your team. Sound familiar? That loop eats hours every week, and it does not have to.
n8n webhook tutorial step by step is exactly what this guide covers. n8n is an open-source automation tool that lets you connect apps and build workflows without writing a full codebase. Webhooks are the engine behind real-time automation. They let apps talk to each other the moment something happens, no waiting, no manual checks.
By the end of this guide, you will know how to set up a webhook in n8n, pull data from it, and send that data anywhere you want. We have built hundreds of these workflows at GrowthSpike. This is the guide we wish we had on day one.
Webhooks sound technical. They are not. Once you understand the pattern, you will see automation opportunities everywhere. Let us get into it.
Understanding Webhooks: The Basics You Need to Know
Think of a webhook like a doorbell. You do not stand outside your friend's house checking every five seconds if they are home. You ring the bell once, and they come to the door. That is exactly how a webhook works.
An external app rings your n8n workflow the moment something happens. A form gets submitted. A payment goes through. A new user signs up. n8n answers the door and gets to work.
Webhooks vs. API Polling
Traditional API polling is the opposite. Your system asks another app, "Got anything new?" on a schedule, every minute, every hour. Most of the time the answer is no. You are burning resources on empty requests.
Webhooks flip that. The other app pushes data to you the second an event fires. That is what makes them perfect for real-time workflows.
The Two Webhook Types in n8n
n8n gives you two ways to work with webhooks:
- Catch Webhook (Trigger): This is the most common one. n8n listens at a URL you generate. When another app sends data to that URL, your workflow starts. Think of it as receiving incoming data.
- HTTP Request Node (Outgoing): This sends a request from n8n to another app's webhook URL. You are the one doing the pushing here.
Most beginner workflows use the Catch Webhook. That is what we focus on in this guide.
Common Use Cases
- A form submission on your website kicks off a CRM entry
- A Stripe payment triggers a welcome email sequence
- A GitHub push syncs data to a project management tool
- A Typeform response populates a Google Sheet row
All of these run without anyone touching a keyboard.
Here is our honest take: most people skip over the concept and jump straight to clicking buttons in n8n. That works until it does not. When your workflow breaks, and it will at some point, understanding what a webhook actually does is what gets you unstuck fast. Do not skip this part.
Setting Up Your First n8n Workflow with a Webhook Trigger
Let us build your first webhook-triggered workflow from scratch. This takes about ten minutes.
Step 1: Create a New Workflow
Open your n8n instance. Click "New Workflow" in the top right corner. You will land on a blank canvas. This is where everything happens.
Step 2: Add the Webhook Node
Click the "+" button on the canvas or hit the "Add first step" prompt. Search for "Webhook" and select it. It will appear as your trigger node, the first box in your workflow.
Step 3: Understand the Two URL Types
When you open the Webhook node, you will see two URLs:
- Test URL: Use this while you are building. It only works when you are actively listening in the editor. Perfect for debugging.
- Production URL: Use this once your workflow is live and activated. This URL is always listening as long as your workflow is active.
A common mistake we see: people paste the test URL into their app and wonder why it stops working after they close the editor. Always switch to the production URL before going live.
Step 4: Copy the Test URL
For now, copy the Test URL. You will paste this somewhere to send a test request.
Step 5: Click "Listen for Test Event"
Back in the Webhook node, click "Listen for test event". n8n is now waiting. It will sit there until it receives a request at that URL. This is your debugging window.
Step 6: Send a Test Request
You have a few options here:
- Postman or Insomnia: Create a new POST request, paste the test URL, add a JSON body like
{"name": "Jane", "email": "jane@example.com"}, and hit Send. - A simple HTML form: Point the form action to your test URL.
- cURL in your terminal:
curl -X POST YOUR_TEST_URL -H "Content-Type: application/json" -d '{"name":"Jane","email":"jane@example.com"}'
We recommend Postman if you do not have it already. It makes testing webhooks much faster.
Step 7: Verify the Incoming Data
Once you send the request, n8n will show you the data it received right inside the node panel. You will see the full JSON object. Click on the node to inspect it. This is your proof that the webhook is working.
If the node shows data, you are ready for the next step. If it times out, check that you clicked "Listen for test event" before sending the request.
Processing Webhook Data: Extracting and Using Information
Your webhook is receiving data. Now you need to do something with it.
How n8n Receives Webhook Data
Every incoming webhook arrives as a JSON object. When you use the Webhook node, n8n wraps the payload in a structure that looks like this: See also: building an AI roadmap for your business.
{
"body": {
"name": "Jane",
"email": "jane@example.com"
},
"headers": { ... },
"query": { ... }
}
The data you care about is almost always inside body.
Using Expressions to Access Data
n8n uses a double-curly-brace expression syntax. To pull the name from the example above, you would write:
{{ $json.body.name }}
To get the email:
{{ $json.body.email }}
You can use these expressions inside any node that follows the webhook trigger. Field inputs, message text, spreadsheet cells, all of them accept expressions.
Practical Example: Extracting Name and Email
Add a Set node after your Webhook node. This node lets you define new fields using the incoming data.
- Set
Nameto{{ $json.body.name }} - Set
Emailto{{ $json.body.email }}
Now those two fields are clean variables you can pass into any downstream node.
Adding Conditional Logic with the IF Node
Want to route data based on what comes in? Add an IF node after your Set node.
Example condition: Check if the email ends with @yourcompany.com.
- Left value:
{{ $json.email }} - Condition: Contains
- Right value:
@yourcompany.com
If true, send the data one way. If false, send it another. This is how you build smart workflows that react differently based on what they receive.
Flat vs. Nested JSON
Not all webhook payloads are simple. Some are deeply nested:
{
"body": {
"user": {
"contact": {
"email": "jane@example.com"
}
}
}
}
To access that email, your expression would be:
{{ $json.body.user.contact.email }}
Just follow the path down the object tree.
Our advice: always click on the Webhook node output and read the actual data structure before writing a single expression. We have wasted time writing expressions against a structure we assumed was there. Check first. Write second. See also: n8n Google Sheets automation tutorial.
Connecting Your Webhook to Other Applications (Real-World Examples)
This is where n8n gets fun. You have data coming in. Now you send it somewhere useful.
Example 1: Send Data to Google Sheets
This is one of the most common patterns we build at GrowthSpike. A form submission lands in a spreadsheet automatically.
- Add a Google Sheets node after your Set node.
- Click "Add Credential" and connect your Google account via OAuth2.
- Set the Operation to Append Row.
- Paste your Spreadsheet ID (grab it from the URL of your Google Sheet).
- Select your Sheet Name.
- Map your columns. Set the "Name" column to
{{ $json.Name }}and the "Email" column to{{ $json.Email }}.
Run a test. A new row should appear in your sheet within seconds.
One thing to watch: make sure your column headers in Google Sheets match exactly what you are mapping. Case matters.
Example 2: Send a Slack Notification
Your team wants to know the moment a new lead comes in. Here is how to wire that up.
- Add a Slack node after your Set node (or after the Google Sheets node to chain both).
- Connect your Slack app via the credential panel. You will need a Slack Bot Token.
- Set the Operation to Send Message.
- Choose your Channel (e.g.,
#leadsor#sales). - Write your Message Text:
New lead: {{ $json.Name }} ({{ $json.Email }})
Now every form submission drops a message into Slack automatically.
If your team uses Telegram instead, the setup is almost identical. Add a Telegram node, connect your bot token, pick your chat ID, and write your message using the same expression syntax.
Chaining Nodes
The real power here is chaining. One webhook can trigger a Google Sheets append, then a Slack message, then a CRM entry, all in sequence. Or you can branch with IF nodes and send different data to different places based on what came in.
We encourage you to experiment. Try connecting your webhook to tools you already use. The n8n node library has over 400 integrations. Somewhere in there is the exact connection your business needs. See also: n8n blog.
Best Practices and Troubleshooting Your n8n Webhooks
Getting a webhook working is one thing. Keeping it working reliably is another.
Secure Your Webhooks
By default, your webhook URL is public. Anyone who finds it can send data to your workflow. That is a problem.
n8n gives you two authentication options inside the Webhook node:
- Basic Auth: Requires a username and password with every request.
- Header Auth: Requires a specific header key-value pair. This is the one we use most. Set a secret header like
X-API-Key: your-secret-tokenand check for it in your workflow.
For any production workflow, add authentication. Full stop.
Debugging Tips
- Check execution logs: In n8n, go to Executions in the left sidebar. Every workflow run is logged there. You can see exactly what data came in and where it failed.
- Use "Listen for test event" actively: Do not guess. Trigger the webhook, inspect the data, then build your next node. One step at a time.
- Pin test data: Once you have a good test payload, pin it inside the Webhook node. This lets you re-run the workflow without needing to send a new request every time.
Common Pitfalls
- Wrong URL: Using the test URL in production is the most common mistake. The test URL only works when the editor is open and listening.
- Malformed JSON: If the sending app is not setting
Content-Type: application/json, n8n may not parse the body correctly. Check the raw incoming data in the execution log. - Workflow not activated: Your production URL does nothing if the workflow is not active. Always click "Activate" in the top right of the editor after saving.
- Network issues: If you are running n8n locally, external apps cannot reach your localhost URL. Use a tool like ngrok to expose your local instance, or run n8n on a cloud server.
Naming Conventions
This sounds minor. It is not. When you have 30 workflows and 200 nodes, clear names save hours. Name every node by what it does: "Receive Lead Form Data", "Extract Name and Email", "Append to Leads Sheet". Name workflows the same way.
We have inherited messy n8n instances from clients. Nodes named "Webhook 3" and "Set 7" tell you nothing. Good names are free documentation.
- Webhooks push data to your workflow in real time. Polling pulls on a schedule. For automation, push wins every time.
- Always use the Test URL while building and the Production URL after activating. Mixing them up is the most common beginner mistake.
- Access webhook payload data with expressions like {{ $json.body.fieldName }}. Always inspect the actual data structure first before writing expressions.
- Secure every production webhook with Header Auth or Basic Auth. An unsecured webhook URL is an open door.
- Chain multiple nodes after a webhook trigger to send data to several apps in one automated sequence. One trigger, many actions.