v2.0.0

Filtering

Reference for building filter parameters in Bitrix24 REST API v2 (prefix operators) and v3 (array-of-triples), including date formatting and the order-stripping rule.

Overview

Bitrix24 has two filter dialects, and they are not interchangeable — each API version accepts only its own.

  • v2 ($b24.actions.v2.{call,callList,fetchList}.make) uses a prefix-keyed object: the operator is a prefix on the field name.
  • v3 ($b24.actions.v3.{call,callList,fetchList}.make) uses an array of triples: [field, operator, value].

Passing a v3-style filter to a v2 action silently misparses; passing a v2-style filter to a v3 action returns UnknownFilterOperatorException.

v2 — prefix operators

The operator is a prefix on the field name. Multiple keys are combined with AND. Two operators on the same field need two separate keys (e.g. a range).

filter: {
  '>=opportunity': 50000,
  '<=opportunity': 200000,
  '!stageId': 'LOST',
  '=%title': 'A%'
}
PrefixMeaningExample
(none)exact match{ stageId: 'NEW' }
>=greater than or equal{ '>=opportunity': 50000 }
>greater than{ '>id': 100 }
<=less than or equal{ '<=opportunity': 200000 }
<less than{ '<closeDate': '2026-01-01' }
!not equal{ '!stageId': 'LOST' }
!=not equal (alternate){ '!=stageId': 'LOST' }
%LIKE (substring, case-insensitive){ '%title': 'supply' }
=%LIKE with explicit pattern (% / _){ '=%title': 'A%' }
!%NOT LIKE{ '!%title': 'test' }

A plain array value means IN; combine with ! for "not in":

filter: {
  stageId: ['NEW', 'PREPARATION', 'EXECUTING'], // IN
  '!categoryId': [4, 7]                          // NOT IN
}

v3 — array of triples

The filter is a JSON array; each element is a [field, operator, value] condition. The top-level array is implicitly AND.

filter: [
  ['stageId', '=', 'NEW'],
  ['createdTime', '>=', '2026-01-01T00:00:00+03:00'],
  ['responsibleId', 'in', [1, 2, 3]]
]

v3 operators — the only 8

=   !=   >   >=   <   <=   in   between
No like / % / substring operator at the v3 protocol level. Substring search is currently a v2-only feature — use v2 with % or =%. A v3 ['title', 'like', 'A%'] fails with UnknownFilterOperatorException.
  • between value must be a 2-element array: [min, max].
  • in value must be an array.

Two-arg forms are sugar:

['id', 42]              // same as ['id', '=', 42]
['stageId', ['A', 'B']] // same as ['stageId', 'in', ['A', 'B']]

For anything beyond a flat list, prefer the typed FilterV3 builder — it validates operators and in / between shapes client-side. See the b24jssdk-filtering skill.

Dates

Use the SDK helper Text.toB24Format(date) for both dialects — it produces the Bitrix24 format yyyy-MM-dd'T'HH:mm:ssZZ and accepts Date, DateTime, or string input.

import { Text } from '@bitrix24/b24jssdk'

const sixMonthsAgo = new Date()
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6)

// v2
const filterV2 = { '>=createdTime': Text.toB24Format(sixMonthsAgo) }

// v3
const filterV3 = [['createdTime', '>=', Text.toB24Format(sixMonthsAgo)]]
Always include the timezone offset in date strings — Bitrix24 portals run in a portal-configured timezone. Text.toB24Format() emits the offset for you.

The order parameter and list actions

callList.make and fetchList.make (both v2 and v3) strip any user-supplied order and force sorting by the cursor id ({ [cursorIdKey]: 'ASC' }), because they page the dataset with a keyset cursor. If you pass an order, the SDK discards it and logs a warning — the value is silently ignored for the result set.

If you need a specific sort order, drop down to call.make and page manually — but you almost always want to filter more narrowly instead. See the CallList Limitations for details.

Side-by-side: the same query in v2 and v3

Open deals (stageId not in WON / LOSE) with an amount between 50 000 and 200 000, created in the last six months:

v2
import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'

const sixMonthsAgo = new Date()
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6)

const response = await $b24.actions.v2.callList.make({
  method: 'crm.item.list',
  params: {
    entityTypeId: EnumCrmEntityTypeId.deal,
    filter: {
      '!stageId': ['WON', 'LOSE'],
      '>=opportunity': 50000,
      '<=opportunity': 200000,
      '>=createdTime': Text.toB24Format(sixMonthsAgo)
    },
    select: ['id', 'title', 'stageId', 'opportunity']
  },
  idKey: 'id',
  customKeyForResult: 'items'
})
v3
import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'

const sixMonthsAgo = new Date()
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6)

const response = await $b24.actions.v3.callList.make({
  method: 'crm.item.list',
  params: {
    entityTypeId: EnumCrmEntityTypeId.deal,
    filter: [
      // v3 has no "not in" operator — wrap `in` in a NOT group (`negative: true`).
      // The `FilterV3.not(FilterV3.in(...))` helper builds the same shape.
      { negative: true, conditions: [['stageId', 'in', ['WON', 'LOSE']]] },
      ['opportunity', 'between', [50000, 200000]],
      ['createdTime', '>=', Text.toB24Format(sixMonthsAgo)]
    ],
    select: ['id', 'title', 'stageId', 'opportunity']
  },
  idKey: 'id',
  customKeyForResult: 'items'
})

See also