Guide
Filter And Route Events
Filters keep destinations focused. Instead of sending every accepted source request to every connection branch, attach a filter rule to the connection that feeds a specific receiver.
A filter is connection-local. The source still accepts or rejects the provider request first; then each connection decides whether its destination should receive that request.
When a filter does not match, FastHook records an ignored branch with cause FILTERED. That is intentional routing evidence, not a failed delivery attempt.
Dashboard Shape
In the dashboard, open Connections, select a route, and enable the Filter block inside Connection rules. The current editor exposes four JSON tabs: Headers, Body, Query, and Path.
You can fill one tab or several. Empty tabs are omitted when the connection is saved. If all four tabs are empty, the filter rule cannot be saved because the backend requires at least one configured target.
Where Filters Run
Filters run on connections, not globally on sources and not on destinations. This is why one accepted source request can be delivered to one destination branch and ignored for another branch.
Write filter conditions against the incoming webhook data available to the connection worker: request headers, parsed body, query params, and path. Do not rely on a transformation rule to create fields that a filter then matches.
- Filters run on connections, not globally on the source.
- A source request can be delivered to one destination and ignored for another.
- Ignored events are visible, so skipped branches can still be explained.
- Filters should use stable provider fields.
- Use separate connections when two destinations need different filters.
Targets And Match Semantics
A filter rule can match headers, body, query, and path. FastHook combines configured targets with AND semantics: every configured target must match for that connection branch to continue to destination delivery.
The dashboard accepts operator names with or without a dollar sign. For example, contains and $contains are equivalent.
- headers: inbound request headers after internal FastHook control headers are removed.
- body: parsed JSON body, or raw body string when the payload is not JSON.
- query: query string parsed into an object.
- path: request path as a string, such as /orders.
- Multiple fields inside one target are also combined with AND.
- Use $or when you need alternatives.
{
"type": "filter",
"headers": {
"x-source": "shopify"
},
"body": {
"type": "order.failed"
},
"query": {
"shop": {
"contains": "demo"
}
},
"path": "/orders"
}Create Or Patch A Filter Rule
The filter is saved inside the connection's rules array. Use PATCH /v1/connections/:id for focused changes after the route exists, or include the filter when creating the connection.
When replacing rules, keep any existing deduplicate, transform, delay, or retry rules that should remain active. A PATCH that sends a new rules array writes the rule shape you provide.
curl -X PATCH "https://api.fasthook.io/v1/connections/web_orders_failed" \
-H "Authorization: Bearer fh_api_xxx" \
-H "x-team-id: tm_xxx" \
-H "content-type: application/json" \
-d '{
"rules": [
{
"type": "filter",
"body": {
"type": "order.failed"
}
},
{
"type": "retry",
"strategy": "exponential",
"interval": 1000,
"count": 5,
"response_status_codes": ["429", "500-599", "!501"]
}
]
}'Use Filters For Routing
Use a separate connection for each destination branch that needs different routing logic. Put the filter on the branch whose destination needs only part of the source stream.
This is the same FastHook model used for fan-out and fan-in: source requests are accepted once, then each connection branch applies its own rules.
- Send order.failed events to an incident worker.
- Send order.paid events to a billing worker.
- Send all /orders path traffic to an audit destination.
- Filter staging or demo traffic away from production destinations.
- Keep high-volume provider noise away from constrained receivers.
Source my-api
-> connection orders-failed
filter body.type == "order.failed"
destination incident-worker
Source my-api
-> connection orders-paid
filter body.type == "order.paid"
destination billing-worker
Source my-api
-> connection audit-orders
filter path starts /orders
destination audit-storeDesign Guidelines
Good filters use fields that are stable, provider-documented, and present on every event type the branch cares about.
- Filter on event type, account id, mode, or path when those fields are stable.
- Avoid filtering on timestamps, delivery ids, retry counters, or mutable descriptions.
- Keep filters narrow for constrained receivers.
- Use transformations when the receiver needs a different payload shape, not just inclusion or exclusion.
- Prefer lowercase header keys in filter JSON.
- Use include/exclude field deduplication for duplicate suppression; use filters for routing decisions.
- Test filters with real provider payloads before enabling production traffic.
Inspect Filter Outcomes
Debug filters from the request outward. First confirm the source accepted the provider request. Then inspect the request's created events and ignored events.
A filtered branch has ignored evidence and no destination attempt. A delivered branch has an event and attempts. Do not debug receiver logs until you know whether the filter allowed that branch to deliver.
- Accepted request plus ignored event often means the filter worked.
- No event at all usually means no active or paused connection exists.
- Use connection_id filters in Events to inspect one branch.
- Compare the stored request body with the filter fields.
- Replay a request after fixing a filter only when receivers are idempotent.
curl "https://api.fasthook.io/v1/requests/req_xxx/events" \
-H "Authorization: Bearer fh_api_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/requests/req_xxx/ignored_events" \
-H "Authorization: Bearer fh_api_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/events?from=now-24h&to=now&connection_id=web_orders_failed" \
-H "Authorization: Bearer fh_api_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/attempts?event_id=evt_xxx&order_by=created_at&dir=desc" \
-H "Authorization: Bearer fh_api_xxx" \
-H "x-team-id: tm_xxx"Common Mistakes
- Putting a filter on the wrong connection branch.
- Expecting a filter to run globally on the source.
- Filling every tab when one stable body or header field is enough.
- Using a transformation-created field as the only filter input.
- Treating cause FILTERED as a destination failure.
- Replacing the whole rules array and accidentally removing retry or deduplication.