Skip to content

Webhooks Overview

Trigger workflows via HTTP requests.

What are Webhooks?

Webhooks allow external systems to trigger workflows:

External Service → HTTP POST → m9m Webhook → Workflow Execution

Creating a Webhook

Add a Webhook node as the workflow trigger:

{
  "nodes": [
    {
      "id": "webhook",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [250, 300],
      "parameters": {
        "path": "/my-webhook",
        "httpMethod": "POST"
      }
    }
  ]
}

Webhook URL

After activating the workflow, the webhook is available at:

http://localhost:8080/webhook/my-webhook

Production URL:

https://your-domain.com/webhook/my-webhook

Triggering Webhooks

POST Request

curl -X POST http://localhost:8080/webhook/my-webhook \
  -H "Content-Type: application/json" \
  -d '{"event": "user_created", "user_id": 123}'

GET Request

curl "http://localhost:8080/webhook/my-webhook?event=ping"

Webhook Configuration

Parameters

Parameter Type Default Description
path string Required URL path for webhook
httpMethod string POST HTTP method to accept
responseMode string onReceived When to respond
responseData string allEntries What to return

HTTP Methods

{
  "parameters": {
    "httpMethod": "POST"  // or GET, PUT, DELETE
  }
}

Response Mode

Mode Description
onReceived Respond immediately (default)
lastNode Respond after workflow completes

Accessing Webhook Data

In downstream nodes:

Request Body

{{ $json.body }}           // Full body
{{ $json.body.event }}     // Specific field

Query Parameters

{{ $json.query }}          // All query params
{{ $json.query.token }}    // Specific param

Headers

{{ $json.headers }}                    // All headers
{{ $json.headers["x-custom-header"] }} // Specific header

Request Info

{{ $json.webhookUrl }}     // Full webhook URL
{{ $json.httpMethod }}     // Request method

Response Configuration

Immediate Response

{
  "parameters": {
    "responseMode": "onReceived",
    "responseCode": 200,
    "responseData": "allEntries"
  }
}

Custom Response

{
  "parameters": {
    "responseMode": "lastNode",
    "responseData": "noData"
  }
}

Then add a Set node at the end:

{
  "name": "Response",
  "type": "n8n-nodes-base.set",
  "parameters": {
    "assignments": [
      {"name": "status", "value": "success"},
      {"name": "message", "value": "Processed"}
    ]
  }
}

Webhook Types

Production Webhook

Active when workflow is activated:

POST /webhook/my-webhook

Test Webhook

For testing without activation:

POST /webhook-test/my-webhook

Common Use Cases

GitHub Webhooks

{
  "parameters": {
    "path": "/github-events",
    "httpMethod": "POST"
  }
}

Filter by event:

{{ $json.headers["x-github-event"] === "push" }}

Stripe Webhooks

{
  "parameters": {
    "path": "/stripe",
    "httpMethod": "POST"
  }
}

Access event:

{{ $json.body.type }}     // "payment_intent.succeeded"
{{ $json.body.data }}     // Event data

Slack Events

{
  "parameters": {
    "path": "/slack-events",
    "httpMethod": "POST",
    "responseMode": "lastNode"
  }
}

Handle challenge:

// Return challenge for Slack URL verification
{{ $json.body.challenge }}

Webhook Management

List Active Webhooks

curl http://localhost:8080/api/v1/webhooks \
  -H "Authorization: Bearer <token>"

Webhook Status

curl http://localhost:8080/api/v1/webhooks/my-webhook \
  -H "Authorization: Bearer <token>"

Best Practices

1. Use Descriptive Paths

/github-push-events     # Good
/webhook1               # Less clear

2. Validate Input

Add a Filter node after webhook:

{
  "type": "n8n-nodes-base.filter",
  "parameters": {
    "conditions": [
      {
        "leftValue": "={{ $json.body.event }}",
        "operator": "exists"
      }
    ]
  }
}

3. Respond Quickly

For slow workflows, use immediate response:

{
  "responseMode": "onReceived"
}

4. Handle Errors

Return appropriate status codes:

{
  "responseCode": 400  // For invalid requests
}

5. Log Requests

Add a Code node to log:

console.log('Webhook received:', JSON.stringify($json.body));
return items;

Error Handling

Invalid Webhook

404 Not Found
Webhook not found or workflow not active

Invalid Method

405 Method Not Allowed
Webhook only accepts POST requests

Processing Error

500 Internal Server Error
Workflow execution failed

Rate Limiting

Configure rate limits:

webhooks:
  rateLimit:
    enabled: true
    requests: 100
    window: 60  # seconds

Returns 429 Too Many Requests when exceeded.

Next Steps