CallListV2.make

Метод для быстрого получения всех данных из list-методов REST API Bitrix24 версии 2.
Bitrix24 постепенно переходит на REST API версии 3.

Обзор

Когда нужно получить все записи из list-методов REST API версии 2 с максимальной эффективностью и вы готовы хранить полный набор данных в памяти, используйте CallListV2.make().

Метод автоматически обрабатывает пагинацию и возвращает все данные в едином массиве.

Для импорта, экспорта, обработки всех элементов и генерации отчётов рекомендуем использовать FetchList — он возвращает асинхронный генератор для поэтапной обработки больших списков.
// Базовое использование
import { EnumCrmEntityTypeId } from '@bitrix24/b24jssdk'

const response = await $b24.actions.v2.callList.make({
  method: 'crm.item.list',
  params: {
    entityTypeId:  EnumCrmEntityTypeId.deal,
    filter: { '>opportunity': 10000 }
  },
  idKey: 'id',
  customKeyForResult: 'items',
  requestId: 'unique-request-id'
})

Когда использовать CallListV2.make()

  1. Малые и средние объёмы данных: когда общее число записей не превышает нескольких тысяч.
  2. Простая обработка: когда нужен простой доступ ко всем данным сразу.
  3. Агрегация данных: когда нужно выполнить операции над всем набором данных (суммирование, группировка и т.д.).

Сигнатура метода

make<T = unknown>(
  options: ActionCallListV2
): Promise<Result<T[]>>

Параметры

Объект options содержит следующие свойства:

ПараметрТипОбязательныйОписание
methodstringДаИмя метода REST API, возвращающего список данных (например, crm.contact.list, tasks.task.list).
paramsOmit<TypeCallParams, 'start' | 'order'>НетПараметры запроса без параметров start и order. Параметр start зарезервирован, так как метод получает все данные одним вызовом. Параметр order зарезервирован, так как курсорной пагинации нужна строгая сортировка по cursorIdKey (по умолчанию равен idKey) по возрастанию — см. Ограничения. Для сужения выборки используйте filter и select.
idKeystringНетИмя поля id так, как оно приходит в каждом элементе ответа; его значение управляет курсором. По умолчанию: 'ID' (верхний регистр). Для методов, возвращающих id в нижнем/camelCase (например, tasks.task.list возвращает id), задайте 'id'.
cursorIdKeystringНетИмя поля, используемое в запросе для order и постраничного фильтра >. По умолчанию равно idKey. Задавайте, только когда имя сортируемого / фильтруемого поля отличается от поля в ответе — например, tasks.task.list сортирует и фильтрует по ID, но возвращает id: передайте idKey: 'id', cursorIdKey: 'ID'.
customKeyForResultstringНетКлюч, по которому в ответе REST API будет выбран массив данных. Например: items для списка элементов CRM.
requestIdstringНетУникальный идентификатор запроса для отслеживания. Используется для дедупликации запросов и отладки.

Возвращаемое значение

Promise<Result<T[]>> — promise, разрешающийся в объект Result<T[]>, содержащий массив всех полученных элементов.

Этот объект предоставляет:

  • .getData(): T[] — возвращает массив всех полученных элементов.
  • .isSuccess: boolean — флаг успешного выполнения всех запросов.
  • .getErrorMessages(): string[] — массив сообщений об ошибках.

Ключевые понятия

Автоматическое предупреждение

При вызове методов, которые доступны в REST API версии 3, система автоматически выводит предупреждение:

"The method {method_name} is available in restApi:v3. It's worth migrating to the new API."

Это указывает на то, что стоит рассмотреть миграцию на более новую версию REST API.

Оптимизация производительности

Метод реализует рекомендованный Bitrix24 алгоритм для эффективной работы с большими объёмами данных:

  1. start: -1: отключает подсчёт общего числа записей, значительно ускоряет выполнение запроса.
  2. Фильтрация по возрастающему id: каждый следующий запрос использует фильтр >cursorIdKey с id последнего полученного элемента (читается через idKey).
  3. Автоматическое определение конца данных: запросы останавливаются при получении пустого массива или если число элементов меньше размера страницы (50).

Структура ответа REST API v2

В REST API версии 2 разные методы могут возвращать данные в разных структурах:

  • Прямой массив: { result: [...] }
  • Сгруппированный массив: { result: { items: [...] } }

Параметр customKeyForResult позволяет указать ключ, по которому расположены данные в ответе.

Ограничения

  • Размер страницы: фиксированное ограничение Bitrix24 REST API версии 2 — 50 записей на запрос.
  • Сортировка фиксирована: метод всегда сортирует по cursorIdKey (по умолчанию равен idKey) по возрастанию, потому что курсорная пагинация опирается на фильтр >cursorIdKey для прохождения по набору. Пользовательское значение order нарушило бы этот инвариант, поэтому сигнатура типа исключает order, а любое значение, переданное в runtime, отбрасывается с записью warning в лог. Для сужения выборки используйте filter.
  • Только для list-методов: предназначен только для методов, возвращающих массивы данных.

Обработка ошибок

Всегда проверяйте результат через isSuccess и обрабатывайте ошибки:

// @check-ignore: top-level return in error-handling illustration

const response = await $b24.actions.v2.callList.make({
  method: 'some.method',
  params: { /* some_params */ },
  idKey: 'id',
  customKeyForResult: 'items',
  requestId: 'unique-request-id'
})

if (!response.isSuccess) {
  // Обработка ошибки
  console.error(new Error(`Error: ${response.getErrorMessages().join('; ')}`))
  return
}

// Работа с успешным результатом
const data = response.getData()

Примеры

Получение всех компаний с фильтрацией

AllCrmItems.ts
import { B24Hook, EnumCrmEntityTypeId, LoggerFactory, Text, SdkError, AjaxError } from '@bitrix24/b24jssdk'

type Company = {
  id: number
  title: string
}

const devMode = !!(typeof import.meta !== 'undefined' && (import.meta.dev || import.meta.env?.DEV))
const $logger = LoggerFactory.createForBrowser('Example:AllCrmItems', devMode)
const $b24 = B24Hook.fromWebhookUrl('https://your_domain.bitrix24.com/rest/1/webhook_code/')

async function getCrmItemList(requestId: string): Promise<Company[]> {
  const sixMonthAgo = new Date()
  sixMonthAgo.setMonth((new Date()).getMonth() - 6)
  sixMonthAgo.setHours(0, 0, 0)

  const response = await $b24.actions.v2.callList.make<Company>({
    method: 'crm.item.list',
    params: {
      entityTypeId: EnumCrmEntityTypeId.company,
      filter: {
        // фильтрация по названию
        '=%title': 'Prime%',
        '>=createdTime': Text.toB24Format(sixMonthAgo) // созданы как минимум 6 месяцев назад
      },
      select: ['id', 'title']
    },
    idKey: 'id',
    customKeyForResult: 'items',
    requestId
  })

  if (!response.isSuccess) {
    throw new SdkError({
      code: 'MY_APP_GET_PROBLEM',
      description: `Problem ${response.getErrorMessages().join('; ')}`,
      status: 404
    })
  }

  return response.getData() ?? []
}

// Использование
const requestId = 'some-crm-item-list'
try {
  const list = await getCrmItemList(requestId)
  $logger.info(`List [${list?.length}]`, { requestId, list })
} catch (error) {
  if (error instanceof AjaxError) {
    $logger.critical(error.message, { requestId, code: error.code })
  } else {
    $logger.alert('Problem', { requestId, error })
  }
}

Получение всех записей tasks.task.list (поле запроса ≠ поле ответа)

tasks.task.list сортирует и фильтрует по ID (верхний регистр), но возвращает каждую задачу с id в нижнем регистре. Задайте idKey на поле ответа, а cursorIdKey — на поле запроса:

AllTasks.ts
type TaskListItem = { id: string, title: string }

const response = await $b24.actions.v2.callList.make<TaskListItem>({
  method: 'tasks.task.list',
  params: {
    filter: { RESPONSIBLE_ID: 1 }, // поля фильтра задач в верхнем регистре
    select: ['ID', 'TITLE'] // выбираем в верхнем регистре, но в ответе id / title в нижнем
  },
  idKey: 'id', // читаем task.id из ответа
  cursorIdKey: 'ID', // order + постраничный фильтр ">ID" в запросе
  customKeyForResult: 'tasks'
})

console.log(`Loaded ${response.getData()?.length ?? 0} tasks`)

Без cursorIdKey значение idKey: 'ID' по умолчанию невозможно прочитать из ответа в нижнем регистре, поэтому пагинация остановится после первых 50 задач — и SDK залогирует warning, указывающий сюда.

Альтернативы и рекомендации

  • Для работы со списками: вместо ручного управления пагинацией используйте:
    • FetchList — возвращает асинхронный генератор для поэтапной обработки больших списков.
  • Для пакетных операций: используйте Batch для выполнения до 50 команд в одном запросе.
  • На стороне клиента (браузер): используйте встроенный объект B24Frame.
  • См. также: Фильтрация — построение filter (и почему order отбрасывается).