Skip to content

Both are per gateway and both live in the same editor: Destinations tab → Edit routing on the row.

A rule addresses one value in the request, compares it, and the group decides how the rules combine.

{
"operator": "and",
"rules": [
{ "path": "body.type", "op": "eq", "value": "invoice.paid" },
{ "path": "body.data.object.amount", "op": "gt", "value": 5000 }
]
}

A path starts with one of two roots and then walks the JSON:

RootReads
body.The payload, when it is JSON.
headers.The inbound headers. Names are lowercase.

body.data.object.id, headers.x-github-event. A path with any other root never matches.

OperatorTrue when
eqThe value equals the rule’s value.
neIt differs, or the path is absent.
containsA string contains the substring, or an array contains the value.
existsThe path resolves to anything, including null.
gt / ltBoth sides are numbers and compare that way.
inThe value is one of the array in the rule.

The top level has an operator of and or or. A rule entry can itself be a group, giving one level of nesting — enough for “A and (B or C)”:

{
"operator": "and",
"rules": [
{ "path": "headers.x-github-event", "op": "eq", "value": "push" },
{
"operator": "or",
"rules": [
{ "path": "body.ref", "op": "eq", "value": "refs/heads/main" },
{ "path": "body.ref", "op": "eq", "value": "refs/heads/release" }
]
}
]
}

Nesting deeper is rejected when you save.

A non-matching event is stored, and its delivery for that gateway is recorded as filtered. It is visible in the event log, was never sent, and is not retried. Other gateways on the same source are unaffected.

An empty filter matches everything. A payload that is not valid JSON makes every body. rule fail to match, so filter on headers when you expect non-JSON bodies.

Filter rules on a connectionFilter rules on a connection
A filter with two rules joined by AND: only large successful payments reach this destination.

Applied after the filter and before the authentication headers.

Transformations operate on the headers Webhooker is about to send — the content type copied from the event, plus the destination’s fixed headers — not on the sender’s own headers, which are not forwarded (see HTTP headers).

  • Set headers — add a header, or overwrite it if it already exists.
  • Rename headers — change the name of a header already in the outbound set, keeping its value.
  • Remove headers — drop a header from the outbound set, for example the content type or a fixed header that one endpoint must not receive.

Header names are matched case-insensitively. Set values support placeholders:

PlaceholderBecomes
{{event.id}}The event id.
{{source.name}}The source’s name.
{{timestamp}}The delivery’s Unix timestamp.

Merge body fields takes a JSON object and merges it into the top level of a JSON payload. Existing keys with the same name are overwritten, everything else is kept, and values support the same placeholders.

{ "received_via": "webhooker", "trace_id": "{{event.id}}" }

A body that is not valid JSON is forwarded byte for byte; header rules still apply.

  1. Base headers: content type, then the destination’s fixed headers.
  2. Transformation: renames, removals, then sets.
  3. Body merge.
  4. Authentication headers.

Because authentication comes last, a transformation cannot overwrite or remove the signature headers — so a broken transformation can never quietly turn a signed delivery into an unsigned one.