How to Use Webhooks in n8n to Trigger Automated Workflows
Webhooks are the backbone of real-time automation. Instead of polling for changes every few minutes, webhooks push data to your workflow the moment something happens — a form submission, a new payment, a CRM update, or a Slack message.
Mastering webhooks in n8n is one of the most important skills for any automation agency. Almost every client workflow you build will use them. This guide covers everything from basic setup to advanced routing and security.
What is a Webhook?
A webhook is an HTTP callback — when Event A happens in System X, System X sends an HTTP POST request to a URL you provide. Your n8n workflow lives at that URL and executes every time it receives a request.
Common webhook use cases:
- Typeform or Jotform submits → triggers lead workflow
- Stripe payment completed → triggers onboarding workflow
- Calendly booking → triggers reminder workflow
- GitHub push → triggers deployment notification
- Shopify order → triggers fulfillment workflow
Step 1: Add a Webhook Node in n8n
In any n8n workflow, click the + button to add a node and search for Webhook. This is a trigger node — it starts your workflow.
When you add a Webhook node, n8n generates two URLs:
- Test URL:
https://your-n8n.com/webhook-test/[path]— use during development - Production URL:
https://your-n8n.com/webhook/[path]— use when workflow is activated
The test URL works only when you manually execute the workflow (the "Listen for Test Event" button). The production URL works only when the workflow is activated (toggle in the top right).
Step 2: Configure the Webhook Node
Key settings in the Webhook node:
- HTTP Method: POST for most webhooks (some services use GET)
- Path: the URL slug — keep it descriptive:
new-lead,stripe-payment,calendly-booking - Authentication: Header Auth, Basic Auth, or None
- Response Mode: "Immediately" (fastest, returns 200 right away) or "Last Node" (waits and returns your custom response)
Step 3: Authentication Best Practices
Never leave a production webhook completely open. Anyone who discovers your URL can trigger your workflow. Use one of these authentication methods:
Header Auth (recommended for most cases):
- In the Webhook node, set Authentication: Header Auth
- Header Name: x-api-key
- Header Value: a strong random string (generate one at randomkeygen.com)
- The calling service must include this header with every request
HMAC Signature (for services like Stripe, Shopify, GitHub):
These services sign the payload with a secret and include it in a header. Verify the signature in a Code node:
const crypto = require('crypto'); const signature = $input.first().headers['x-hub-signature-256']; const expected = 'sha256=' + crypto.createHmac('sha256', 'YOUR_SECRET').update(JSON.stringify(body)).digest('hex'); return signature === expected;
Step 4: Receiving and Parsing Webhook Data
After the Webhook node, your data is available in $json. The structure depends on the sending service.
For a Typeform submission, $json looks like:
{ "event_id": "abc123", "form_response": { "answers": [{ "field": { "ref": "name" }, "text": "John Smith" }, { "field": { "ref": "email" }, "email": "john@example.com" }] } }
Add a Code node to flatten this into a clean object:
const answers = $input.first().json.form_response.answers; const data = {}; answers.forEach(a => { data[a.field.ref] = a.text || a.email || a.phone_number || a.number || ''; }); return [{ json: data }];
Step 5: Handling Multiple Event Types
Many services send different event types to the same webhook URL. For example, Stripe sends payment_intent.succeeded, customer.subscription.created, invoice.payment_failed all to the same webhook.
Use a Switch node to route by event type:
- Value:
{{$json.type}}(the event type field) - Case payment_intent.succeeded: → onboarding workflow branch
- Case invoice.payment_failed: → dunning workflow branch
- Case customer.subscription.cancelled: → churn workflow branch
- Default: → log and do nothing
Step 6: Returning Custom Responses
Sometimes the calling service expects a specific response. For example, Typeform wants a 200 OK. Slack slash commands need a JSON response with the message to display. GitHub webhooks need a 204 No Content.
Set Response Mode: Last Node in the Webhook node and add a Respond to Webhook node at the end:
- Response Code: 200
- Response Headers:
Content-Type: application/json - Response Body: your JSON response
For Slack slash commands, the response body must be:
{ "response_type": "ephemeral", "text": "{{$json.ai_response}}" }
Step 7: Testing Webhooks During Development
Use the test URL during development. In n8n:
- Click Listen for Test Event in the Webhook node
- Send a test request to the test URL using a tool like Postman, curl, or the service's own test button
- n8n receives the data and shows you the parsed payload
- Build the rest of your workflow with this real data structure
- Click Execute Workflow to run the full flow with the captured test data
Use curl for quick tests:
curl -X POST https://your-n8n.com/webhook-test/new-lead -H "Content-Type: application/json" -H "x-api-key: your-key" -d '{"name":"Test User","email":"test@example.com"}'
Step 8: Connecting Common Services to n8n via Webhook
Typeform: Settings → Integrations → Webhooks → Add Webhook → paste your n8n URL
Calendly: Integrations → Webhooks → Create Webhook → paste URL, select events (invitee.created, invitee.canceled)
Stripe: Developers → Webhooks → Add Endpoint → paste URL, select events
Shopify: Settings → Notifications → Webhooks → Create Webhook → select event, paste URL
GitHub: Repository Settings → Webhooks → Add Webhook → paste URL, select events
Step 9: Error Handling for Webhooks
Webhooks fail silently if n8n isn't running or throws an error. Build resilience:
- Use n8n Cloud or a reliable hosting platform (Railway, Render, DigitalOcean) — never run production on localhost
- Enable Error Workflow in n8n settings — this workflow fires whenever a node throws an error
- Log all incoming webhook data to a Google Sheet or database before processing — if something fails, you can replay it
- Return the right HTTP status codes — 400 for bad requests, 500 for server errors, 200 for success
Real Business Workflow Example
A complete client workflow that uses multiple webhooks: a customer fills out a Typeform (webhook → n8n) → n8n creates a HubSpot contact → n8n charges via Stripe (webhook back to n8n) → n8n sends onboarding emails → Calendly booking (webhook to n8n) → n8n adds to project management tool. Five different webhooks, one coherent client journey.
For more on building complete workflows, see our n8n AI agent beginner's guide and our breakdown of n8n vs Make vs Zapier for agency workflows.
Want to learn how to build and sell AI automations? Join our free community. Join the free AI Agency Sprint community.
Join 215+ AI Agency Owners
Get free access to our LinkedIn automation tool, AI content templates, and a community of builders landing clients in days.
