CallListV3.make

Метод для быстрого получения всех данных из list-методов REST API Bitrix24 версии 3.
Важно отметить, что REST API версии 3 позволяет получать до 1000 элементов за один запрос через параметр пагинации parameter: { limit: 1000, page: 1 }.

Обзор

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

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

Для импорта, экспорта, обработки всех элементов и генерации отчётов рекомендуем использовать FetchList — он возвращает асинхронный генератор для поэтапной обработки больших списков.
// Базовое использование
const response = await $b24.actions.v3.callList.make({
  method: 'main.eventlog.list',
  params: {
    filter: [
      ['userId', '=', 1]
    ],
    select: ['id', 'userId']
  },
  idKey: 'id',
  customKeyForResult: 'items',
  requestId: 'unique-request-id',
  limit: 600
})

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

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

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

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

Параметры

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

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

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

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

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

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

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

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

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

  1. Фильтрация по возрастающему id: каждый следующий запрос использует фильтр [cursorIdKey, '>', id] с id последнего полученного элемента (читается через idKey).
  2. Автоматическое определение конца данных: запросы останавливаются при получении пустого массива или когда страница короче самой большой из виденных. Это привязывает остановку к размеру страницы, который реально возвращает сервер, а не к запрошенному options.limit, поэтому метод, молча ограничивающий страницу ниже limit (например, tasks.task.list, зафиксирован на 50), всё равно проходит все записи, а не останавливается после первой урезанной страницы.

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

Параметр customKeyForResult сохранён для обратной совместимости. В будущем после анализа реального использования будет принято решение о его необходимости.

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

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

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

Некоторые v3 list-методы (например, note.*) также возвращают в конверте ответа поле nextCursor рядом с items{ result: { nextCursor, items: [...] } }. Читать или передавать его не нужно: CallListV3.make() листает собственным курсором по idKey (внедрённый фильтр [idField, '>', n]) и проходит все страницы независимо от nextCursor. Поле информационное; SDK его игнорирует.

Ограничения

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

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

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

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

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

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

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

Примеры

Получение всех элементов журнала событий с фильтрацией

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

type MainEventLogItem = {
  id: number
  userId: number
}

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

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

  const response = await $b24.actions.v3.callList.make<MainEventLogItem>({
    method: 'main.eventlog.list',
    params: {
      filter: [
        ['timestampX', '>=', Text.toB24Format(sixMonthAgo)] // созданы как минимум 6 месяцев назад
      ],
      select: ['id', 'userId']
    },
    idKey: 'id',
    customKeyForResult: 'items',
    requestId,
    limit: 60
  })

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

  return response.getData() ?? []
}

// Использование
const requestId = 'some-main-event-log-item-list'
try {
  const list = await getMainEventLogItemList(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 })
  }
}

Когда поля id в запросе и ответе различаются

Некоторые методы сортируют / фильтруют по одному имени поля, но возвращают другое (например, ID в верхнем регистре в запросе против id в нижнем в payload). Задайте idKey на поле ответа, а cursorIdKey — на поле запроса:

const response = await $b24.actions.v3.callList.make({
  method: 'some.list',
  params: { select: ['ID', 'TITLE'] },
  idKey: 'id', // читаем id из каждого возвращённого элемента
  cursorIdKey: 'ID', // order + постраничный фильтр ["ID", ">", n] в запросе
  customKeyForResult: 'items'
})

Если idKey не удаётся прочитать из полной страницы, SDK логирует warning и прекращает пагинацию, вместо того чтобы молча обрезать данные.

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

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