Filter Node

The Filter node gates events by evaluating payload conditions. Only events that pass all (or any) of the configured filter rules continue through the pipeline — everything else is dropped before delivery, saving retries and quota.

Overview

Filters inspect the event payload against a set of rules and decide whether the event should proceed. Unlike Routers (which direct events to different destinations), Filters are binary: an event either passes or is blocked. You can configure the filter to require and (all rules must pass) or or (any rule passing is sufficient).

Blocked events are saved with status filtered and no delivery job is created. On the canvas, Filter nodes appear as yellow rectangles.


Configuration

FieldTypeDefaultDescription
namestringFriendly label for the filter
filterModestringand'and' (all rules must pass) or 'or' (any rule passing is sufficient)
filtersFilterRule[][]Array of filter rules (see below)
inputNodes{ nodeType, nodeId }[][]Upstream nodes that feed this one. nodeType is the node kind (webhook, scheduledWorkflow, filter, …)
isActivebooleantrueWhether the filter is enabled

FilterRule object

FieldTypeDescription
fieldstringDot-notation path into the payload (e.g. data.status)
operatorstringComparison operator (equals, not_equals, contains, not_contains, gt, lt, exists, not_exists, regex, in, not_in)
valuestringValue to compare against (not required for exists/not_exists)
Filters share the same operator set as the Router node. The key difference is that Filters are pass/block gates, while Routers direct events to different destinations.

Create a Filter

bashCreate Filter
curl -X POST /api/filter-nodes \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "High-Value Payments Only",
    "filterMode": "and",
    "filters": [
      {
        "field": "type",
        "operator": "equals",
        "value": "payment_intent.succeeded"
      },
      {
        "field": "data.object.amount",
        "operator": "gt",
        "value": "5000"
      },
      {
        "field": "data.object.currency",
        "operator": "in",
        "value": "usd,eur,gbp"
      }
    ],
    "inputNodes": [{ "nodeType": "webhook", "nodeId": "6654a1b2c3d4e5f6a7b8c9d0" }],
    "isActive": true
  }'

Response

json201 Created
{
  "_id": "6654e5f6a7b8c9d0e1f2a3b4",
  "name": "High-Value Payments Only",
  "filterMode": "and",
  "filters": [
    {
      "field": "type",
      "operator": "equals",
      "value": "payment_intent.succeeded"
    },
    {
      "field": "data.object.amount",
      "operator": "gt",
      "value": "5000"
    },
    {
      "field": "data.object.currency",
      "operator": "in",
      "value": "usd,eur,gbp"
    }
  ],
  "inputNodes": [{ "nodeType": "webhook", "nodeId": "6654a1b2c3d4e5f6a7b8c9d0" }],
  "isActive": true,
  "ownerId": "org_abc123",
  "createdAt": "2025-05-01T12:00:00.000Z",
  "updatedAt": "2025-05-01T12:00:00.000Z"
}

Update a Filter

bashUpdate Filter
curl -X PATCH /api/filter-nodes/6654e5f6a7b8c9d0e1f2a3b4 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "filterMode": "or",
    "filters": [
      {
        "field": "data.object.amount",
        "operator": "gt",
        "value": "10000"
      },
      {
        "field": "data.object.metadata.priority",
        "operator": "equals",
        "value": "high"
      }
    ]
  }'
Updating filters replaces the entire array. Include all rules you want to keep.

Canvas Integration

The Filter uses canvas type filter-node and renders in yellow. It connects from a Webhook and acts as a gate — events that pass continue through outgoing edges; blocked events stop at the filter.

jsonCanvas node data
{
  "id": "filter-6654e5f6a7b8c9d0e1f2a3b4",
  "type": "filter-node",
  "position": { "x": 350, "y": 200 },
  "data": {
    "label": "High-Value Payments Only",
    "filterNodeId": "6654e5f6a7b8c9d0e1f2a3b4",
    "filterMode": "and",
    "ruleCount": 3,
    "isActive": true
  }
}

Payload Examples

Event that passes the filter

jsonPasses (AND mode)
{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "amount": 15000,
      "currency": "usd",
      "customer": "cus_abc123"
    }
  }
}
// Result: PASSES — type matches, amount > 5000, currency in [usd, eur, gbp]

Event that is blocked

jsonBlocked (AND mode)
{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "amount": 2500,
      "currency": "usd",
      "customer": "cus_xyz789"
    }
  }
}
// Result: BLOCKED — amount (2500) is NOT > 5000. Event saved as "filtered".

OR mode example

jsonPasses (OR mode)
// filterMode: "or"
// Rule 1: data.object.amount gt 10000
// Rule 2: data.object.metadata.priority equals "high"

{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "amount": 500,
      "metadata": { "priority": "high" }
    }
  }
}
// Result: PASSES — amount fails but priority matches (OR requires only one)

Use Cases

  • Event type filtering — Only process specific event types from a source that sends many (e.g., Stripe sends 100+ event types).
  • Amount thresholds — Block low-value transactions to reduce processing load.
  • Feature flags — Use exists to only pass events with a specific metadata field present.
  • Security filtering — Block events from untrusted sources using not_in on IP or source identifiers.
  • Quota management — Reduce event volume to stay within plan limits by filtering out non-essential events.

API Reference

MethodWebhookDescription
GET/api/filter-nodesList all filter nodes
POST/api/filter-nodesCreate a new filter node
GET/api/filter-nodes/:idGet a specific filter node
PATCH/api/filter-nodes/:idUpdate a filter node
DELETE/api/filter-nodes/:idDelete a filter node
Combine a Filter with a Router for powerful pipelines: the Filter blocks irrelevant events first, then the Router distributes remaining events to the correct destinations.