Webhook Node
The Webhook is the foundational node in every HostWebhook pipeline. It acts as the entry point that receives inbound webhooks via a unique ingress URL and delivers them to your target server, with full control over retries, rate limiting, circuit breaking, and chaos testing.
Overview
Every webhook pipeline starts with at least one Webhook node. When an external service (Stripe, GitHub, your own app) sends an HTTP request to the webhook's ingress URL, HostWebhook captures the payload as an event, validates it against any attached Schema Validators or Filters, and then delivers it to the configured targetUrl. Webhooks support automatic retries with exponential backoff, circuit breaker protection, priority-based queue ordering, fallback URLs, and even chaos injection for resilience testing.
On the canvas, Webhook nodes appear as violet/indigo rectangles. They can connect to Routers, Filters, Transforms, Schema Validators, Chains, and more.
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
| name | string | — | Friendly label for the webhook |
| targetUrl | string | — | The URL where events are delivered (your server) |
| isActive | boolean | true | When false, events are queued but not delivered |
| signingSecret | string | auto-generated | HMAC-SHA256 secret used to sign deliveries |
| rateLimitPerSecond | number | 0 (unlimited) | Max deliveries per second to this endpoint |
| retryPolicy.maxRetries | number | 3 | Number of retry attempts after initial failure |
| retryPolicy.backoffMultiplier | number | 2 | Multiplier for exponential backoff between retries |
| circuitBreaker.enabled | boolean | false | Enable circuit breaker protection |
| circuitBreaker.threshold | number | 5 | Consecutive failures before circuit opens |
| circuitBreaker.cooldownSeconds | number | 60 | Seconds to wait before half-open probe |
| priority | number | 3 | Queue priority (1 = highest, 5 = lowest) |
| fallbackUrl | string | null | URL to deliver to when primary target fails all retries |
| chaosConfig.enabled | boolean | false | Enable chaos injection for testing |
| chaosConfig.failureRate | number | 0 | Percentage of requests to artificially fail (0-100) |
| chaosConfig.latencyMs | number | 0 | Artificial latency added to each delivery in ms |
403 Forbidden.Create a Webhook
Send a POST request to create a new webhook. The response includes the auto-generated ingressUrl and signingSecret.
curl -X POST /api/webhooks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Stripe Production",
"targetUrl": "https://api.myapp.com/webhooks/stripe",
"isActive": true,
"rateLimitPerSecond": 50,
"retryPolicy": {
"maxRetries": 5,
"backoffMultiplier": 2
},
"circuitBreaker": {
"enabled": true,
"threshold": 10,
"cooldownSeconds": 120
},
"priority": 1,
"fallbackUrl": "https://api.myapp.com/webhooks/stripe-fallback"
}'Response
{
"_id": "6654a1b2c3d4e5f6a7b8c9d0",
"name": "Stripe Production",
"targetUrl": "https://api.myapp.com/webhooks/stripe",
"ingressUrl": "https://app.hostwebhook.com/ingress/abc123token",
"ingressToken": "abc123token",
"signingSecret": "whsec_k8x2mPqR9vN3wL5yT7uJ1aB4cD6eF0gH",
"isActive": true,
"rateLimitPerSecond": 50,
"retryPolicy": {
"maxRetries": 5,
"backoffMultiplier": 2
},
"circuitBreaker": {
"enabled": true,
"threshold": 10,
"cooldownSeconds": 120
},
"priority": 1,
"fallbackUrl": "https://api.myapp.com/webhooks/stripe-fallback",
"chaosConfig": {
"enabled": false,
"failureRate": 0,
"latencyMs": 0
},
"ownerId": "org_abc123",
"createdAt": "2025-05-01T12:00:00.000Z",
"updatedAt": "2025-05-01T12:00:00.000Z"
}Update a Webhook
Use PATCH to update specific fields. Only provided fields are modified; omitted fields retain their current values.
curl -X PATCH /api/webhooks/6654a1b2c3d4e5f6a7b8c9d0 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"rateLimitPerSecond": 100,
"circuitBreaker": {
"enabled": true,
"threshold": 5,
"cooldownSeconds": 300
},
"chaosConfig": {
"enabled": true,
"failureRate": 10,
"latencyMs": 500
}
}'chaosConfig in production will cause a percentage of deliveries to fail intentionally. Only use this for resilience testing.Internal calls & AI tools
By default a webhook is only callable from outside — someone sends an HTTP POST to the ingress URL. Enabling Internal calls turns the webhook into a reusable building block that other flows and AI agents inside your organization can invoke directly, without HTTP, without signing, and without exposing a public URL.
acceptsInternalCalls is a consent gate, not a convenience toggle. Only someone with access to the webhook's workspace can opt it in — this prevents a user in workspace A from silently escalating to invoke a webhook in workspace B just by adding it as an AI tool. Once opt-in, any other flow or AI Node in the org can reference it.Two modes
- FlowLink (persistent edge) — Wire a source node from another flow's canvas to this endpoint. Every time the source fires, this endpoint's pipeline runs. The relationship lives in the
flowlinkscollection and shows in the webhook's Incoming list with a flow-link badge. Supports sync vs fire-and-forget. - AI tool (ephemeral, LLM-decided) — Add this endpoint to an AI Node's
tools[]via the Node-as-Tool picker. At runtime the LLM chooses whether to invoke it; no FlowLink record is created. The reference shows in Incoming with a tool badge (scanned org-wide from every AI Node's tool list).
How to enable
- Open the webhook detail page.
- In the Internal calls section, flip the violet toggle on.
- The webhook now appears in the Node-as-Tool picker and is a valid FlowLink target for any other flow in the org.
Canvas Integration
On the visual canvas, the Webhook node is rendered as a violet/indigo rectangle with the node type webhook. It is typically the leftmost node in a pipeline and serves as the root from which all other nodes branch.
Node connections
- Outgoing edges connect to Router, Filter, Transform, Schema Validator, Delay, Merge, and Approval nodes.
- Chain edges connect to other Webhook nodes (rendered to the right). Chains fire sequentially on delivery success.
- Scheduled Workflow edges use
swEdge: truein edge data to differentiate from regular connections.
{
"id": "webhook-6654a1b2c3d4e5f6a7b8c9d0",
"type": "webhook",
"position": { "x": 100, "y": 200 },
"data": {
"label": "Stripe Production",
"webhookId": "6654a1b2c3d4e5f6a7b8c9d0",
"isActive": true,
"targetUrl": "https://api.myapp.com/webhooks/stripe"
}
}Payload Examples
Inbound event payload
Any valid JSON body sent to the ingress URL is captured as an event:
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_3PxQR4567abcdef",
"amount": 5000,
"currency": "usd",
"customer": "cus_abc123"
}
}
}Delivery payload (sent to targetUrl)
HostWebhook delivers the original payload with additional headers:
{
"Content-Type": "application/json",
"X-HostWebhook-Signature": "sha256=a1b2c3d4...",
"X-HostWebhook-Event-Id": "evt_6654a1b2c3d4e5f6a7b8c9d0",
"X-HostWebhook-Timestamp": "1714564800",
"X-HostWebhook-Delivery-Attempt": "1"
}Chain payload (when chained to another webhook)
{
"original": {
"type": "payment_intent.succeeded",
"data": { "object": { "amount": 5000 } }
},
"previous": {
"statusCode": 200,
"body": { "processed": true, "orderId": "ORD-123" }
}
}Use Cases
- Payment processing — Receive Stripe/PayPal webhooks and deliver to your order fulfillment service with retries and circuit breaker protection.
- CI/CD pipelines — Capture GitHub push events and trigger deployment pipelines with priority-based ordering.
- Multi-region failover — Use
fallbackUrlto route to a secondary region when the primary target is down. - Chaos engineering — Enable
chaosConfigin staging to test how your system handles partial delivery failures and added latency. - Rate-sensitive APIs — Use
rateLimitPerSecondto avoid overwhelming third-party APIs with strict rate limits.
API Reference
| Method | Webhook | Description |
|---|---|---|
| GET | /api/webhooks | List all webhooks for the authenticated organization |
| POST | /api/webhooks | Create a new webhook |
| GET | /api/webhooks/:id | Get a specific webhook by ID |
| PATCH | /api/webhooks/:id | Update an existing webhook |
| DELETE | /api/webhooks/:id | Delete a webhook and all associated events |
?page=1&limit=20 query parameters.