Filters & Transforms
9 filter operators and JSONata transforms for event routing and payload reshaping.
Filters decide which events a connection or subscription receives. Transforms reshape the payload before delivery. Together they let you route precisely and deliver exactly the shape your downstream system expects.
Content-Based Filters
Filters let you selectively route events based on their content. Each filter has three parts: a field path (dot-notation), an operator, and a value. Multiple filters on the same connection are AND-combined — every rule must match for the event to pass.
Filter Operators
hookstream supports 9 operators:
| Operator | Description | Types |
|---|---|---|
eq | Exact match | string, number, bool |
neq | Inverse of eq | string, number, bool |
contains | Substring match | string only |
gt | Greater than | number |
gte | Greater than or equal | number |
lt | Less than | number |
lte | Less than or equal | number |
exists | Field is present (true) or absent (false) | any |
in | Value is in an array of allowed values | any |
Numeric comparisons (gt, gte, lt, lte) return false when either the field value or the rule value isn't a number — they don't coerce strings.
Field Paths
Field paths use dot-notation to reach values in the event:
payload.type— top-level body fieldpayload.data.customer.id— nested body fieldheaders.x-github-event— request header (case-insensitive)method— HTTP methodcontent_type— request content typesource_ip— client IP address
Paths are case-sensitive except for headers. Missing paths resolve to undefined — pair them with the exists operator to branch on presence.
Filter Example
[
{ "field": "method", "op": "eq", "value": "POST" },
{ "field": "headers.x-github-event", "op": "in", "value": ["push", "pull_request"] },
{ "field": "payload.repository.private", "op": "eq", "value": false }
]curl -X PATCH https://hookstream.io/v1/connections/conn_abc \
-H "Authorization: Bearer $HOOKSTREAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_rules": [
{ "field": "method", "op": "eq", "value": "POST" },
{ "field": "headers.x-github-event", "op": "in", "value": ["push", "pull_request"] },
{ "field": "payload.repository.private", "op": "eq", "value": false }
]
}'This connection only matches public GitHub push/PR events delivered via POST.
JSONata Transforms
Transforms reshape event payloads using JSONata — a lightweight query and transformation language built specifically for JSON. Transforms run after filters and before the event is handed to the destination.
Transform Examples
{
"event": body.type,
"customer_id": body.data.customer.id,
"amount": body.data.amount / 100
}{
"text": "New order " & body.data.order_id &
" for $" & $string(body.data.amount / 100)
}{
"id": body.id,
"email": body.email
}JSONata runs in a sandboxed interpreter — no eval(), no filesystem, no network. It's safe to let end users author their own transforms.
Schema Validation
Sources can validate incoming payloads against a JSON Schema — a complementary feature that runs before filters. Two modes:
reject— invalid payloads return400and aren't stored.warn— invalid payloads are stored with a validation warning flag.
Schema validation uses @cfworker/json-schema, a Workers-native validator. See the schema validation guide for details.