Introduction
Webhooks and API integrations are the backbone of modern automation. n8n provides powerful nodes for both receiving events via webhooks and making outbound API calls. This guide covers everything you need to build robust webhook-powered workflows and integrate with any API.
Understanding Webhooks in n8n
How Webhooks Work
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Webhook Flow โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ External Service n8n โ
โ โโโโโโโโโโโโโโโโ โโโโโโ โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Stripe โ โโโโโโโโโโโโโบ โ Webhook โ โ
โ โ Payment โ HTTP POST โ Trigger โ โ
โ โโโโโโโโโโโโ โโโโโโฌโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโ โ
โ โ Process โ โ
โ โ Request โ โ
โ โโโโโโโโฌโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโผโโโโโโโโโโโโโ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Update โ โ Send โ โ Call โ โ
โ โ Databaseโ โ Slack โ โ API โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Webhook Types
| Type | Trigger | Use Case |
|---|---|---|
| Production | Real-time events | Payment processing |
| Test | Manual test | Development |
| Webhook | Standard HTTP | General purpose |
| REST Hook | Subscription-based | Long-lived events |
Receiving Webhooks
Basic Webhook Setup
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Webhook Configuration โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Webhook Node: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ Path: my-webhook โ โ
โ โ Method: POST โ โ
โ โ Response Mode: On Received โ โ
โ โ Response Data: All Entries โ โ
โ โ โ โ
โ โ Webhook URL: โ โ
โ โ https://your-n8n.com/webhook/my-webhook โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Configuration Options
# Webhook Node Settings
{
"path": "stripe-payment",
"method": "POST",
"responseMode": "onReceived",
"responseData": "allEntries",
"options": {
"rawBody": false,
"headerAuthentication": {
"type": "Bearer Token",
"property": "authorization"
}
}
}
Handling Different Methods
# Handle GET, POST, PUT, DELETE
Method: "{{ $input.params.method }}"
# Access in workflow
{{ $input.body }} # Request body
{{ $input.params }} # Query parameters
{{ $input.headers }} # Request headers
{{ $input.files }} # Uploaded files
Responding to Webhooks
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Webhook Response โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Node: Respond to Webhook โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ Response Body: โ โ
โ โ { โ โ
โ โ "status": "success", โ โ
โ โ "message": "Order received", โ โ
โ โ "order_id": "{{ $json.order_id }}" โ โ
โ โ } โ โ
โ โ โ โ
โ โ Response Status Code: 200 โ โ
โ โ Response Headers: Content-Type: json โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Making API Calls
HTTP Request Node
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HTTP Request Node โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Configuration โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ โ โ
โ โ Method: GET / POST / PUT / DELETE / PATCH โ โ
โ โ โ โ
โ โ URL: https://api.example.com/v1/endpoint โ โ
โ โ โ โ
โ โ Authentication: โ โ
โ โ โโโ None โ โ
โ โ โโโ Basic Auth โ โ
โ โ โโโ Bearer Token โ โ
โ โ โโโ API Key โ โ
โ โ โโโ OAuth2 โ โ
โ โ โโโ Header Auth โ โ
โ โ โ โ
โ โ Headers: โ โ
โ โ Content-Type: application/json โ โ
โ โ โ โ
โ โ Body: โ โ
โ โ { โ โ
โ โ "data": "{{ $json.data }}" โ โ
โ โ } โ โ
โ โ โ โ
โ โ Query Parameters: โ โ
โ โ limit: 100 โ โ
โ โ offset: 0 โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Authentication Methods
Bearer Token
Authentication:
Type: Bearer Token
Token: "{{ $credentials.api_token }}"
Basic Auth
Authentication:
Type: Basic Auth
User: "{{ $credentials.username }}"
Password: "{{ $credentials.password }}"
API Key
Authentication:
Type: API Key
Header: X-API-Key
Value: "{{ $credentials.api_key }}"
OAuth2
Authentication:
Type: OAuth2
Client ID: "{{ $credentials.client_id }}"
Client Secret: "{{ $credentials.client_secret }}"
Authorization URL: https://provider.com/oauth/authorize
Access Token URL: https://provider.com/oauth/token
Scopes: read write
Request Body Examples
# JSON Body
Body Content:
{
"name": "{{ $json.name }}",
"email": "{{ $json.email }}",
"metadata": {
"source": "webhook",
"timestamp": "{{ $now.toISOString() }}"
}
}
# Form Data
Body Content Type: Form URL Encoded
Body: name=John&[email protected]
# Raw Body (for files)
Body Content Type: Binary File
Advanced API Patterns
Pagination
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Handling Pagination โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ Trigger โ โ
โ โโโโโโโโฌโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโ โ
โ โ HTTP โ โโโบ GET /users?page=1 โ
โ โ Request โ โ
โ โโโโโโโโฌโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโ โ
โ โ If โ โโโบ {{ $json.hasMore === true }} โ
โ โ โ โ
โ โโโโโโโโฌโโโโโโโ โ
โ โโโโโดโโโโ โ
โ โ โ โ
โ YES NO โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Wait โ โ Continue โ โ
โ โ (rate) โ โ โ โ
โ โโโโโโฌโโโโโ โโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโ โ
โ โ Loop Back โ โโโ Increment page โ
โ โ to HTTP โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Code Implementation
// Using Split In Batches for pagination
const response = await $input.first();
const data = response.json;
// Get pagination info
const nextPage = response.json.next_page;
const hasMore = response.json.has_more;
// Store for next iteration
$input.first().json.hasMore = hasMore;
$input.first().json.nextPage = nextPage;
return [{
json: {
items: data.items,
hasMore: hasMore || false,
nextPage: nextPage
}
}];
Rate Limiting
# Using Wait node for rate limiting
1. HTTP Request (Batch 1)
2. If: more_pages === true
3. Wait: 1000ms (respect API limits)
4. HTTP Request (Batch 2)
Retry Logic
# Automatic retry configuration
{
"retryOnFail": true,
"maxTries": 3,
"wait": 1000,
"maxWait": 10000
}
Error Handling for API Calls
# Handle API errors
1. HTTP Request
- Continue on Fail: true
2. If Error Exists
- Log to database
- Notify via Slack
3. If Success
- Continue processing
// Error handling in Code node
try {
const response = await axios.get(url);
return { success: true, data: response.data };
} catch (error) {
// Check for specific errors
if (error.response?.status === 429) {
// Rate limited - retry
throw new Error('Rate limited - should retry');
}
if (error.response?.status === 401) {
// Unauthorized - notify
return {
success: false,
error: 'Authentication failed',
action: 'notify_admin'
};
}
// Other errors
return { success: false, error: error.message };
}
Real-World Examples
Stripe Payment Processing
# Stripe Webhook Handler
1. Webhook Trigger
Path: stripe-webhook
Headers: stripe-signature
2. Code (Verify Signature)
- Verify Stripe signature
- Parse event
3. Switch (Event Type)
- payment_intent.succeeded โ Process Order
- payment_intent.payment_failed โ Notify Customer
- customer.subscription.created โ Create Subscription
- invoice.payment_failed โ Send Alert
4. Database (Update)
- Update order status
5. Slack/Email (Notify)
- Send confirmation
GitHub Integration
# GitHub Webhook Handler
1. Webhook Trigger
Path: github-webhook
2. Switch (Event Type)
- push โ Run Build
- pull_request โ Run Tests
- issues.opened โ Create Task in Linear
- release.published โ Deploy & Notify
3. Conditional Logic
- Branch filter
- Repository filter
CRM Data Sync
# Two-way CRM Sync
Direction 1: External โ n8n
1. Webhook Trigger (receive CRM updates)
2. Process data
3. Update local database
Direction 2: n8n โ External
1. Schedule Trigger (every hour)
2. Fetch changes from database
3. Batch API calls to CRM
4. Handle conflicts
5. Log sync status
Working with GraphQL
GraphQL in n8n
# Using HTTP Request for GraphQL
{
"method": "POST",
"url": "https://api.github.com/graphql",
"authentication": "Bearer",
"headers": {
"Content-Type": "application/json"
},
"body": {
"query": "query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { name description } }",
"variables": {
"owner": "{{ $json.owner }}",
"name": "{{ $json.repo }}"
}
}
}
GraphQL vs REST
| Feature | REST | GraphQL |
|---|---|---|
| Multiple endpoints | Multiple | Single |
| Data shape | Fixed | Flexible |
| Over-fetching | Common | Avoided |
| Under-fetching | Common | Avoided |
| Caching | Simple | Complex |
| Learning curve | Lower | Higher |
Best Practices
Good Patterns
# Good: Validate webhook source
1. Webhook Trigger
2. Code: Verify signature/secret
3. If invalid โ Stop & Error
# Good: Handle idempotency
1. Webhook Trigger
2. Code: Check if processed (ID)
3. If new โ Process
4. If exists โ Skip (prevent duplicates)
# Good: Timeout handling
{
"timeout": 30000,
"maxTimeout": 60000
}
Bad Patterns
# Bad: No authentication on webhooks
# Always validate webhook source!
# Bad: Storing secrets in workflow
# Use Credentials instead!
# Bad: Not handling errors
# Always add error handling!
Security
Webhook Security
# Add webhook verification
1. Webhook Trigger
- Enable header authentication
- Set expected header
2. Code Node
- Verify signature/hmac
- Validate source IP
- Check timestamp (prevent replay)
API Key Security
# Never expose credentials
# GOOD: Use n8n credentials
Authentication:
Type: API Key
Credentials: My API Key (saved)
# BAD: Hardcode in workflow
URL: https://api.com?key=secret123
Testing Webhooks
Testing Tools
# Using curl
curl -X POST https://your-n8n.com/webhook/test \
-H "Content-Type: application/json" \
-d '{"event": "test", "data": {"id": 123}}'
# Using n8n test button
# Click "Test workflow" in editor
# n8n sends test webhook
Local Development
# Use ngrok for local testing
ngrok http 5678
# Configure webhook URL in external service
# to ngrok URL
Monitoring and Debugging
Execution Logging
# Enable detailed logging
{
"logExecution": "always",
"saveDataOnError": "all"
}
Health Checks
# Monitor webhook health
1. Schedule Trigger (every 5 min)
2. HTTP Request โ health endpoint
3. If: health === unhealthy
4. Slack โ Alert team
Conclusion
Mastering webhooks and API integration in n8n opens endless automation possibilities. Always validate webhook sources, handle errors gracefully, and implement proper authentication for secure integrations.
Related Articles
- n8n Complete Guide: AI-Powered Workflow Automation
- n8n Advanced Workflow Patterns
- n8n Self-Hosted Production Guide
Comments