Filters

Filters allow you to permit and route events conditionally based on the contents of their Headers, Body, Query, or Path.

The two most common uses of filters are:

  • Allowing only events with useful information to pass through to a destination.
  • Routing events to different destinations based on their contents, as in a fan out approach.

Filters utilize JSON, and support matching on any value (string, number, boolean, null), on nested objects, and on arrays. There is also support for special operators. For a full rundown of supported schema, see filter syntax.

Filter limitations

Filters were designed for JSON payloads. To filter XML payloads, please first transform the payload to JSON.

Basic, non-structured filters, such as partial or exact matches on strings, will function with XML payloads.

Filters syntax

Filters utilize JSON, and support matching on any value (string, number, boolean, null), on nested objects, and on arrays.

The following events would be permitted through the filter, based on their request bodies and respective filters.

Simple matches

Single value match

// Event request body
false

// Filter
false

Simple primitive match

// Event request body
{
  "type": "order/created",
  "order": {
    "id": 123
  }
}

// Filter
{
  "type": "order/created"
}

Nested object match

// Event request body
{
  "product": {
    "title": "A product",
    "inventory": 0
  }
}

// Filter
{
  "product": {
    "inventory": 0
  }
}

Also valid:

// Event request body
{
  "order": {
    "id": 123,
    "items": [
      {
        "id": 456,
        "title": "My product"
      }
    ]
  }
}

// Filter
{
  "order": {
    "items": {
      "id": 456
    }
  }
}

Array contains match

// Event request body
{
  "product": {
    "title": "Gift Card",
    "tags": ["gift", "something"]
  }
}

// Filter
{
  "product": {
    "tags": "gift"
  }
}

Array contains (multiple) match

Array must contain all the specified values.

// Event request body
{
  "product": {
    "title": "Gift Card",
    "tags": ["gift", "something", "another"]
  }
}

// Filter
{
  "product": {
    "tags": ["gift", "something"]
  }
}

Non-object match

To match on a string that is not part of an object structure (for example, to set a filter on a path), simply consider the string to be at the root of your filter:

// Path
"/path/test"

// Filter
{
  "$in": "/path"
}

Complex matches using operators

Operators allow for more complex matching strategies, beyond simple equivalency tests.

OperatorSupported TypeDescription
$gtenumber, stringGreater than or equal to
$gtnumber, stringGreater than
$ltnumber, stringLess than
$ltenumber, stringLess than or equal to
$eqarray, number, object, stringEqual (or deep equal)
$neqarray, number, object, stringNot Equal (or deep not equal)
$inarray, stringContains
$ninarray, stringDoes not contain
$startsWithstringStarts with text
$endsWithstringEnds with text
$orarrayArray of conditions to match
$andarrayArray of conditions to match
$ref<field>Reference a field
$existbooleanUndefined or not undefined
$notValid syntaxNegation

Value comparison operators

The following demonstrates a matching filter using the $lte (less than or equal to) operator.

// Event request body
{
  "product": {
    "title": "A product",
    "inventory": 5
  }
}

// Filter
{
  "product": {
    "inventory": {
      "$lte": 10
    }
  }
}

$or and $and operators

$or and $and evaluate matches across an array of values. The array of conditions can contain any other valid schema.

The following demonstrates a matching filter using the $or operator.

// Event request body
{
  "product": {
    "title": "A product",
    "inventory": 5
  }
}

// Filter
{
  "product": {
    "inventory": {
      "$or": [1, 5]
    }
  }
}

The following demonstrates a non-matching filter using the $or operator.

// Event request body
{
  "hello": "world"
}

// Non-matching filter
{
  "$or": [
    {  "hello": "johny"},
    {  "hello": "mark"}
  ]
}

Reference operator

$ref references other values in your JSON input when evaluating a match. The reference input must be a string representing the value path.

// Event request body
{
  "type": "example",
  "nested_object": {
    "hello": "world",
    "array": [1, 2, 3]
  }
}

// Example reference values
"$ref" : "type" // evaluates to "example"
"$ref" : "nested_object.hello" // evaluates to "world"
"$ref" : "nested_object.array[1]" // evaluates to 1
"$ref" : "nested_object.array[$index]" // evaluates to 1, 2, or 3 (depending on the current index)

The following demonstrates a matching filter using the $ref operator.

// Event request body
{
  "updated_at": "2020-04-20",
  "created_at": "2020-04-20"
}

// Filter
{
  "updated_at": {
    "$ref": "created_at"
  }
}

You may also reference the current array index, instead of a specific index, using $index. Multiple indexes can be referenced when dealing with nested arrays.

// Event request body
{
  "variants": [
    {
      "updated_at": "2020-05-20",
      "created_at": "2020-04-20"
    },
    {
      "updated_at": "2020-04-20",
      "created_at": "2020-04-20"
    }
  ]
}

// Filter: Test if any of the elements in the array has the same value for `updated_at` and `created_at`.
// This will match because the 2nd element has the same date for both `updated_at` and `created_at`.
{
  "variants": {
    "updated_at": {
      "$eq": {
        "$ref": "variants[$index].created_at"
      }
    }
  }
}

$ref may also be used in conjunction with other operators.

// Event request body
{
  "inventory": 0,
  "old_inventory": 10
}

// Filter
{
  "inventory": {
    "$lte": { "$ref": "old_inventory" }
  }
}

$exist operator

$exist requires a field to be undefined when false and array, number, object, string, boolean or null when true.

// Event request body
{
  "inventory": 0,
}

// Filter
{
    "old_inventory": {
      "$exist": false
    }
}

Negation operator

$not negation of the schema.

// Event request body
{
  "inventory": 0,
}

// Filter
{
    "$not": {
      "inventory": 1,
    }
}

Examples using operators

Example 1 - Filter if property = value (nested)

Condition Don't allow "subtype" = "message_changed" OR "subtype" = "message_deleted"

// Event request body
{
  "event": {
    "type": "message",
    "subtype": "message_changed"
    }
}

// Filter
{
  "$not": {
    "event": {
      "subtype": {
        "$or": [
          "message_changed",
          "message_deleted"
        ]
      }
    }
  }
}

Example 2 - Two properties meet criteria with 'or' condition

Condition Only allow "subtype" = "message_changed" OR "subtype" = "message_deleted" AND "type"="message"

// Event request body
{
  "event": {
    "type": "message",
    "subtype": "message_changed"
    }
}

// Filter
{
  "event": {
    "subtype": {
      "$or": [
        "message_changed",
        "message_deleted"
      ]
    },
    "type": "message"
  }
}

Example 3 - using $not and $or operators

Condition

  1. Allow "event" = "message"
  2. AND don't allow "team_id" = "team1" OR "team_id" = "team2"
  3. AND if "subtype" exists, don't allow "subtype" = "message_changed" OR "subtype" = "message_deleted"
// Event request body
{
  "team_id": "team",
  "event": {
    "type": "message",
    "subtype": "message_changed"
  }
}

// Filter
{
  "event": {
    "type": "message"
  },
  "$not": {
    "$or": [
      {
        "event": {
          "subtype": {
            "$or": [
              "message_changed",
              "message_deleted"
            ]
          }
        }
      },
      {
        "team_id": {
          "$or": [
            "team1",
            "team2"
          ]
        }
      }
    ]
  }
}

Create a filter

Filters are applied to a connection, just like any other rule.

To version control your filters, consider creating or updating your connection using the API.

  1. Open the connection rules configuration.

  2. Click Filter to add a filter rule.

  3. Click Editor to configure the filter.

    • To add a filter for the Body, Headers, Query, or Path, select the appropriate tab above the editor.
    • In the right pane, enter the desired schema using proper filter syntax.
    • The left pane shows the most recent payload for reference and testing purposes. This reference text is editable.
  4. Once written, test your filter against the event in the left pane by clicking Test Filter . A check mark next to each Body, Headers, Query, or Path section indicates the event would be allowed through to its destination based on the contents of that section.

  5. Once satisfied, click Save .

  6. Make sure to click Save again on the connection form to apply your changes.

From this point on, any events not matching the filter are disregarded by Hookdeck, and will not appear in your list of events.

Edit a filter

Editing a filter changes the schema that determines a event's delivery eligibility.

  1. Open the connection rules configuration.

  2. Next to the filter rule, click Editor.

    • To edit a filter for the Body, Headers, Query, or Path, select the appropriate tab above the editor.
    • In the right pane, update the desired schema using proper filter syntax.
    • In the left pane appears the most recent payload for reference and testing purposes. This reference text is editable.
  3. Once written, test your updated filter against the event in the left pane by clicking Test Filter . A check mark next to each Body, Headers, Query, or Path section indicates the event would be allowed through to its destination based on the contents of that section.

  4. Once satisfied, click Save .

  5. Make sure to click Save again on the connection form to apply your changes.

Filters are updated immediately, and any events received going forward are tested against the new filter contents.

Delete a filter

Deleting a filter allows all events, regardless of content, to pass through a connection unimpeded.

To delete a filter, follow the instructions for configuring connection rules and click the trash icon to remove the filter from the connection rules.