Endpoint Pipeline
Process webhooks through middleware steps before delivery, and route them to multiple destinations with conditional logic.
How It Works
Each endpoint can have a middleware pipeline and routing rules. When a webhook arrives:
- The webhook passes through each middleware step in order
- Filters may block the webhook, transforms modify headers or body, delays add latency, and deduplication prevents duplicate deliveries
- The processed webhook is routed based on the endpoint's routing mode and rules
Middleware Types
| Type | Purpose | Config Example |
|---|---|---|
filter | Block webhooks based on conditions | {"field": "headers.X-Type", "operator": "equals", "value": "test"} |
transform_headers | Modify HTTP headers before delivery | {"set": {"X-Auth": "token"}, "remove": ["X-Debug"]} |
transform_body | Modify JSON payload content | {"set": {"source": "hookwatch"}, "remove": ["debug_info"]} |
delay | Add latency before delivery | {"seconds": 5} |
deduplicate | Prevent duplicate deliveries | {"key": "headers.X-Idempotency-Key", "ttl": 3600} |
The Middleware Object
Properties
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
endpoint_id | string | Parent endpoint ID |
type | string | Middleware type: filter, transform_headers, transform_body, delay, or deduplicate |
name | string | Human-readable name |
config | object | Type-specific configuration (see below) |
sort_order | number | Execution order (lower runs first) |
is_active | boolean | Whether the middleware is enabled |
Middleware API
Base URL
https://api.hookwatch.dev/v1/webhook/endpoints/:endpoint_id/middlewaresCreate Middleware
POST /v1/webhook/endpoints/:endpoint_id/middlewaresRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Middleware type: filter, transform_headers, transform_body, delay, or deduplicate |
name | string | Yes | Name for the middleware |
config | object | Yes | Type-specific configuration |
is_active | boolean | No | Enable/disable (default: true) |
List Middlewares
Retrieve all middlewares for an endpoint, ordered by sort_order.
GET /v1/webhook/endpoints/:endpoint_id/middlewaresUpdate Middleware
Update a middleware's type, name, config, or active status.
PUT /v1/webhook/endpoints/:endpoint_id/middlewares/:middleware_idDelete Middleware
DELETE /v1/webhook/endpoints/:endpoint_id/middlewares/:middleware_idReorder Middlewares
Change the execution order by providing the middleware IDs in the desired sequence.
PUT /v1/webhook/endpoints/:endpoint_id/middlewares/reorderTest Pipeline
Dry-run a sample payload through all active middlewares to see how each step processes it.
POST /v1/webhook/endpoints/:endpoint_id/middlewares/testResponse
Routing Rules
Routing rules let you fan out webhooks to multiple destinations with conditional logic. Each rule can match on headers, body fields, or HTTP method.
Routing Modes
| Mode | Behavior |
|---|---|
single | Deliver to the endpoint's primary destination only (default) |
first_match | Evaluate rules in order, deliver to the first matching rule |
all_match | Deliver to all rules whose conditions match |
broadcast | Deliver to all rules regardless of conditions |
The Routing Rule Object
Properties
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
endpoint_id | string | Parent endpoint ID |
name | string | Human-readable name |
destination_url | string | URL to deliver the webhook to |
condition_source | string | Where to evaluate: header, body, or method |
condition_field | string | Field to check (header name or JSONPath for body) |
condition_operator | string | Comparison: equals, not_equals, contains, matches, or exists |
condition_value | string | Value to compare against |
retry_config | object | Per-rule retry configuration |
headers_override | object | Headers to add/override on delivery |
transform_body | string | Body transformation template |
sort_order | number | Evaluation order (lower runs first) |
is_active | boolean | Whether the rule is enabled |
Routing Rules API
Base URL
https://api.hookwatch.dev/v1/webhook/endpoints/:endpoint_id/routing-rulesCreate Routing Rule
POST /v1/webhook/endpoints/:endpoint_id/routing-rulesRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the routing rule |
destination_url | string | Yes | Destination URL for delivery |
condition_source | string | No | Where to evaluate: header, body, or method |
condition_field | string | No | Field to check (header name or JSONPath) |
condition_operator | string | No | Comparison operator |
condition_value | string | No | Value to compare against |
retry_config | object | No | Custom retry configuration |
headers_override | object | No | Headers to add/override on delivery |
transform_body | string | No | Body transformation template |
is_active | boolean | Yes | Enable/disable the rule |
List Routing Rules
GET /v1/webhook/endpoints/:endpoint_id/routing-rulesUpdate Routing Rule
PUT /v1/webhook/endpoints/:endpoint_id/routing-rules/:rule_idDelete Routing Rule
DELETE /v1/webhook/endpoints/:endpoint_id/routing-rules/:rule_idSet Routing Mode
Change how webhooks are routed for this endpoint.
PUT /v1/webhook/endpoints/:endpoint_id/routing-modeTest Routing Rules
Dry-run a sample payload against routing rules to see which destinations would be matched.
POST /v1/webhook/endpoints/:endpoint_id/routing-rules/testCondition Operators
| Operator | Source | Description |
|---|---|---|
equals | header, body, method | Exact string match |
not_equals | header, body, method | Not equal to value |
contains | header, body | Substring match |
matches | header, body | Regular expression match |
exists | header, body | Field is present (value ignored) |
Body Conditions
When condition_source is body, the condition_field uses JSONPath syntax (e.g., $.event_type, $.data.customer.id).
Error Codes
| Status | Error | Description |
|---|---|---|
400 | Bad Request | Invalid middleware type, missing required fields |
401 | Unauthorized | Invalid or missing access token |
404 | Not Found | Endpoint or middleware/rule not found |
500 | Server Error | Internal server error |