---
title: "Filtering"
description: "Reduce webhook traffic by filtering on event type, on the user who made the change, or with a JSONPath expression evaluated against the payload. Includes ready-to-use samples."
lang: en
languages:
  en: https://docs.vismasoftware.no/businessnxtapi/webhooks/filtering/index.md
lastmod: 2026-09-22
---

> Documentation index: https://docs.vismasoftware.no/businessnxtapi/webhooks/llms.txt


# Filtering

Last modified September 22, 2026

> Reduce webhook traffic by filtering on event type, on the user who made the change, or with a JSONPath expression evaluated against the payload. Includes ready-to-use samples.


By default a subscription forwards every `INSERT`, `UPDATE` and `DELETE` on the subscribed table. Two columns on the `WebhookSubscription` row let you narrow this down:

- **Filter**: flags that suppress whole event types, or changes made by your own application.
- **JQ filter**: a JSONPath expression evaluated against the webhook payload. The notification is only sent when the expression matches.

Both are set on the `WebhookSubscription` row in the layout described in [Business NXT configuration](https://docs.vismasoftware.no/businessnxtapi/webhooks/bnxt/index.md). Filters are per subscription row, so one company/table combination can have different filters for different targets.

## Event filters

The `Filter` column is a set of flags. A set flag means **do not deliver** that kind of event.

| Flag | Value | Effect when set |
| ---- | ----- | --------------- |
| Insert | 1 | `INSERT` events are not delivered. |
| Update | 2 | `UPDATE` events are not delivered. |
| Delete | 4 | `DELETE` events are not delivered. |
| User | 8 | Changes made by the subscription's own application user are not delivered. Use this to avoid being notified about your own writes. |

Flags can be combined, so `Insert + Delete` (5) delivers only `UPDATE` events.

## JSONPath filter

The `JQ filter` column holds a [JSONPath (RFC 9535)](https://www.rfc-editor.org/rfc/rfc9535) expression. It is evaluated against the full payload documented on the [Webhooks](https://docs.vismasoftware.no/businessnxtapi/index.md) page. The notification is delivered when the expression selects **at least one** node. If it selects nothing, the event is dropped for that subscription. An empty filter delivers everything.

Two rules cover nearly every filter:

1. To test a top-level field, use `$[?($.field ...)]`. The predicate is anchored on `$` (the payload). Do not write `@.field` at the top level: there `@` refers to each value inside the payload, not the payload itself, so `@.event` is never defined and the filter will silently match everything or nothing.
2. `primaryKeys` and `changedColumns` are arrays of single-key objects, so a column is tested inside the array: `$.changedColumns[?(@.WarehouseNo == 1)]`. Column names are PascalCase, the GraphQL name with an uppercase first letter (`OrderNo` in the payload, `orderNo` in GraphQL), and only columns present in the event can match. `changedColumns` is absent on `DELETE` events.

### Samples

All samples are verified against the payload shape on the [Webhooks](https://docs.vismasoftware.no/businessnxtapi/index.md) page.

| Goal | Filter |
| ---- | ------ |
| Skip deletes | `$[?($.event != 'DELETE')]` |
| Only inserts and updates | `$[?($.event == 'INSERT' \|\| $.event == 'UPDATE')]` |
| Only one company (system tables that fan out to several companies) | `$[?($.companyNo == 5199768)]` |
| Ignore changes made by a given user | `$[?($.changedByUser != 'my-integration-client')]` |
| Ignore changes made by users matching a regex | `$[?(!search($.changedByUser, '^system\\.'))]` |
| Only when a specific column changed | `$.changedColumns[?(@.Description)]` |
| Only when a column changed to a given value | `$.changedColumns[?(@.WarehouseNo == 1)]` |
| Only when a column changed to one of several values | `$.changedColumns[?(@.WarehouseNo == 1 \|\| @.WarehouseNo == 2)]` |
| Only rows with a primary key in a range | `$.primaryKeys[?(@.OrderNo >= 2000)]` |
| Updates where a specific column changed | `$[?($.event == 'UPDATE' && $.changedColumns[?(@.Description)])]` |
| Deletes, or any event where a column changed | `$[?($.event == 'DELETE' \|\| $.changedColumns[?(@.Quantity)])]` |
| Column value and user combined | `$[?($.changedColumns[?(@.WarehouseNo == 1)] && $.changedByUser != 'my-integration-client')]` |

Values are compared with their JSON type: numbers unquoted (`@.WarehouseNo == 1`), strings in single quotes (`$.event == 'UPDATE'`). Supported operators are `==`, `!=`, `<`, `<=`, `>`, `>=`, `&&`, `||` and `!`, plus the functions `length`, `count`, `match`, `search` and `value`.

### Errors and testing

An expression that fails to parse, or that fails during evaluation, is treated as **no filter**: every event is delivered. Nothing is reported back to the subscriber, so an over-delivering subscription is the symptom of a broken filter.

Test an expression before saving it, for example in the playground below. Paste a real payload from your endpoint, apply the expression and confirm that the result is non-empty exactly when you expect delivery.

> [!TIP]
> Prefer the event and user flags in the `Filter` column when they are enough. They are cheaper to evaluate and cannot be misspelled. Use JSONPath for company, column and value conditions.

## Try it

The playground evaluates the expression against the payload in your browser with an RFC 9535 engine. Edit either field, load a row from the samples table, or switch between the sample payloads. The engine follows the same RFC 9535 grammar as the Business NXT service, so the verdict is what the service does with the event.

**Update on OrderLine**

```json
{
    "tableIdentifier": "OrderLine",
    "tableNo": 128,
    "customerNo": 4801958,
    "companyNo": 5199768,
    "event": "UPDATE",
    "primaryKeys": [
        {"OrderNo": 3},
        {"LineNo": 1}
    ],
    "timestamp": "2025-02-06T21:15:28.3971469Z",
    "changedByUser": "ola.normann",
    "changedColumns": [
        {"Description": "Hello webhook"},
        {"WarehouseNo": 1},
        {"Quantity": 5},
        {"ChangedDate": 20250206},
        {"ChangedTime": 2215},
        {"ChangedByUser": "ola.normann"},
        {"ChangeTimeInMs": 80128366},
        {"ChangedTimestamp": 20250206211528366}
    ]
}
```


**Insert on OrderLine**

```json
{
    "tableIdentifier": "OrderLine",
    "tableNo": 128,
    "customerNo": 4801958,
    "companyNo": 5199768,
    "event": "INSERT",
    "primaryKeys": [
        {"OrderNo": 2001},
        {"LineNo": 1}
    ],
    "timestamp": "2025-02-06T22:15:00.1234567Z",
    "changedByUser": "my-integration-client",
    "changedColumns": [
        {"ProductNo": "1001"},
        {"Description": "Bolt M8"},
        {"Quantity": 10},
        {"WarehouseNo": 2},
        {"CreatedDate": 20250206},
        {"CreatedTime": 2215},
        {"CreatedByUser": "my-integration-client"},
        {"CreatedTimestamp": 20250206221500123}
    ]
}
```


**Delete on OrderLine**

```json
{
    "tableIdentifier": "OrderLine",
    "tableNo": 128,
    "customerNo": 4801958,
    "companyNo": 5199768,
    "event": "DELETE",
    "primaryKeys": [
        {"OrderNo": 3},
        {"LineNo": 1}
    ],
    "timestamp": "2025-02-07T08:02:11.5550000Z",
    "changedByUser": "ola.normann"
}
```

The web version of this page has an interactive playground that evaluates a JSONPath expression against these payloads.



---

[View this page](https://docs.vismasoftware.no/businessnxtapi/webhooks/filtering/)
