Filter syntax

Filters are JSON objects attached to each route. A webhook passes the filter when every condition is true (AND logic). An empty conditions array matches all events.

Filter shape
{
  "conditions": [
    { "field": "type", "op": "eq", "value": "checkout.session.completed" },
    { "field": "data.object.amount_total", "op": "gte", "value": 5000 }
  ]
}

Field paths

Use dot notation to read nested fields from the parsed JSON payload—for example data.object.amount_total on Stripe events or pull_request.user.login on GitHub. Array indices work too: line_items.0.title.

If a field is missing, comparison operators (everything except exists) do not match.

Operators

Hooks supports these ten operators:

eq

Field equals the value (strict equality).

{ "field": "type", "op": "eq", "value": "checkout.session.completed" }

neq

Field does not equal the value.

{ "field": "action", "op": "neq", "value": "deleted" }

gt

Numeric field is greater than the value.

{ "field": "data.object.amount_total", "op": "gt", "value": 1000 }

gte

Numeric field is greater than or equal to the value.

{ "field": "data.object.amount_total", "op": "gte", "value": 5000 }

lt

Numeric field is less than the value.

{ "field": "total_price", "op": "lt", "value": 100 }

lte

Numeric field is less than or equal to the value.

{ "field": "total_price", "op": "lte", "value": 50 }

contains

String field contains the substring.

{ "field": "pull_request.title", "op": "contains", "value": "urgent" }

starts_with

String field starts with the prefix.

{ "field": "ref", "op": "starts_with", "value": "refs/heads/release" }

in

Field value is one of the values in the array.

{ "field": "action", "op": "in", "value": ["opened", "reopened"] }

exists

Field is present (not undefined). No value key needed.

{ "field": "pull_request", "op": "exists" }

AND-only (MVP)

All conditions in one filter are combined with AND. There is no OR or nested grouping in the MVP—if you need “event A or event B”, create two routes with different filters and the same channel.

OR logic and grouped conditions are planned for post-MVP.

Example: high-value Stripe checkouts only

Forward checkout.session.completed only when amount_total is at least 5000 (Stripe amounts are in the smallest currency unit—5000 = ¥5,000 or $50.00 depending on currency).

{
  "conditions": [
    { "field": "type", "op": "eq", "value": "checkout.session.completed" },
    { "field": "data.object.amount_total", "op": "gte", "value": 5000 }
  ]
}