Skip to the content.

Filtering & Transformation

Event Filtering

Use filter on a handler to only create jobs when the payload matches a condition. Events that don’t match are silently skipped – no job is created.

handlers:
  paid-only:
    source: stripe
    events: [invoice.*]
    url: http://backend:3000/paid
    filter: "$.data.object.status == paid"

Filter Expressions

Syntax Example Description
$.path == value $.status == active Equality (strings, numbers, booleans)
$.path != value $.env != test Inequality
$.path >= value $.amount >= 1000 Greater than or equal (numeric)
$.path > value $.retries > 0 Greater than (numeric)
$.path <= value $.priority <= 5 Less than or equal (numeric)
$.path < value $.age < 18 Less than (numeric)
$.path in [a, b] $.type in [created, updated] Set membership
$.path contains value $.name contains admin Substring match (strings) or array membership
$.path starts_with value $.email starts_with admin String prefix match
$.path ends_with value $.file ends_with .json String suffix match
$.path matches <regex> $.id matches ^ord_[0-9]+$ Regex match
$.path exists $.metadata.tag exists Field existence (non-null)
not <expr> not $.status == draft Logical negation of any expression
$.path $.data.verified Truthy (exists, not null/false/0/””)

Examples

# Only process paid invoices
filter: "$.data.object.status == paid"

# Exclude test events
filter: "$.environment != test"

# Multiple event types
filter: "$.action in [opened, synchronize, reopened]"

# Check if a field is truthy (exists and not null/false/0)
filter: "$.data.customer.verified"

# Nested paths
filter: "$.data.object.customer.email == user@example.com"

# Substring match
filter: "$.message contains error"

# Array membership (value exists in an array field)
filter: "$.tags contains urgent"

# String prefix/suffix
filter: "$.email starts_with admin"
filter: "$.filename ends_with .csv"

# Regex match
filter: "$.order_id matches ^ORD-[0-9]{6}$"

# Field existence
filter: "$.metadata.trace_id exists"

# Negation (works with any expression)
filter: "not $.status == draft"
filter: "not $.env in [staging, dev]"

Payload Transformation

Use transform to reshape the payload before delivery. The original payload is preserved in the database; transformation is applied at delivery time.

handlers:
  slack-notify:
    source: stripe
    events: [checkout.session.completed]
    url: http://slack-bot:3000/notify
    transform: |
      {"text": "New order from  for  cents"}

Placeholder Syntax

Examples

Reshape for a downstream API:

transform: |
  {"order_id": "", "customer": "", "total": }

Input: {"id": "ord_123", "customer": "alice", "amount": 4999, "currency": "jpy"}

Output: {"order_id": "ord_123", "customer": "alice", "total": 4999}

Slack notification format:

transform: |
  {"text": "Order  from :  "}

Output: {"text": "Order ord_123 from alice: 4999 jpy"}

Combining Filter and Transform

Filter is evaluated first. If it matches, the transform is applied before delivery.

handlers:
  audit-paid:
    source: stripe
    events: [invoice.*]
    url: http://audit:3000/log
    filter: "$.status == paid"
    transform: |
      {"invoice_id": "", "amount": , "paid": true}

Only paid invoices are delivered, and they arrive in a compact audit format.

See Also