#Пакетные вызовы

Один HTTP-запрос объединяет до 50 операций над разными сущностями. Каждый вызов идентифицируется собственным id и обрабатывается независимо: ошибка одного вызова не отменяет остальные.

POST /v1/batch

Скоуп: проверяется индивидуально по сущности (crm, task, im, disk и др.) | Базовый URL: https://vibecode.bitrix24.tech/v1 | Авторизация: X-Api-Key (APP-ключ)

#Поля запроса (body)

Поле Тип Обяз. Описание
calls array Массив вызовов (от 1 до 50). Каждый элемент — объект, формат описан в таблице ниже.

#Поля одного вызова

Поле Тип Обяз. Описание
id string нет Идентификатор вызова в ответе. Если не передан — присваивается порядковый индекс ("0", "1", ...). Длина до 64 символов.
entity string Имя сущности во множественном числе: deals, contacts, companies, tasks, users, files, folders и другие. Полный список сущностей, доступных вашему ключу, возвращает GET /v1/me — см. Ключи и авторизация.
action string Операция: list, get, create, update, delete, fields, search.
entityId number / string для get / update / delete Идентификатор записи.
params object нет Параметры операции в едином entity-формате (имена полей в camelCase, фильтры в синтаксисе фильтрации).

Параметры внутри params совпадают с параметрами одиночного эндпоинта Entity API:

  • list и searchfilter, select, order, limit
  • get — поле include, если сущность его поддерживает
  • create и update — поля сущности (имена в camelCase)
  • delete и fields — параметры не нужны
  • смарт-процессы (entity: "items") — внутри params обязательно entityTypeId

#Примеры

#curl — личный ключ

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/batch \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "calls": [
      {
        "id": "deals",
        "entity": "deals",
        "action": "list",
        "params": {
          "filter": { "stageId": "NEW" },
          "select": ["id", "title", "amount"],
          "limit": 50
        }
      },
      {
        "id": "contacts",
        "entity": "contacts",
        "action": "list",
        "params": {
          "select": ["id", "name", "lastName"],
          "limit": 20
        }
      },
      {
        "id": "user1",
        "entity": "users",
        "action": "get",
        "entityId": 1
      }
    ]
  }'

#curl — OAuth-приложение

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/batch \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "calls": [
      {
        "id": "deals",
        "entity": "deals",
        "action": "list",
        "params": {
          "filter": { "stageId": "NEW" },
          "select": ["id", "title", "amount"],
          "limit": 50
        }
      },
      {
        "id": "contacts",
        "entity": "contacts",
        "action": "list",
        "params": {
          "select": ["id", "name", "lastName"],
          "limit": 20
        }
      },
      {
        "id": "user1",
        "entity": "users",
        "action": "get",
        "entityId": 1
      }
    ]
  }'

#JavaScript — личный ключ

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/batch', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    calls: [
      { id: 'deals', entity: 'deals', action: 'list', params: { filter: { stageId: 'NEW' }, select: ['id', 'title', 'amount'], limit: 50 } },
      { id: 'contacts', entity: 'contacts', action: 'list', params: { select: ['id', 'name', 'lastName'], limit: 20 } },
      { id: 'user1', entity: 'users', action: 'get', entityId: 1 }
    ]
  })
})

const { data } = await res.json()
console.log('Сделки:', data.results.deals)
console.log('Контакты:', data.results.contacts)
console.log('Сводка:', data.summary)

#JavaScript — OAuth-приложение

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/batch', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    calls: [
      { id: 'deals', entity: 'deals', action: 'list', params: { filter: { stageId: 'NEW' }, select: ['id', 'title', 'amount'], limit: 50 } },
      { id: 'contacts', entity: 'contacts', action: 'list', params: { select: ['id', 'name', 'lastName'], limit: 20 } },
      { id: 'user1', entity: 'users', action: 'get', entityId: 1 }
    ]
  })
})

const { data } = await res.json()
console.log('Сделки:', data.results.deals)

#Поля ответа

Поле Тип Описание
success boolean true, если запрос принят. Частичные ошибки внутри data.errors не переводят его в false.
data.results object Результаты по id каждого вызова. Значение — то, что вернул бы соответствующий эндпоинт Entity API: массив записей для list / search, объект для get / create, схема полей для fields.
data.totals object Общее количество записей под фильтр для list / search-вызовов. Ключи — id соответствующих вызовов.
data.errors object Ошибки по id неудачных вызовов. Каждое значение — { "code": "...", "message": "..." }.
data.summary.total number Общее количество вызовов в запросе.
data.summary.succeeded number Количество успешных вызовов.
data.summary.failed number Количество вызовов с ошибкой.
data.meta object Дополнительные сведения по id вызовов с action: "list" или action: "search": total, returned, hasMore, truncated.

#Пример ответа

JSON
{
  "success": true,
  "data": {
    "results": {
      "deals": [
        { "id": 575, "title": "Тест валюты", "amount": 0 },
        { "id": 741, "title": "Поставка оборудования", "amount": 250000 }
      ],
      "contacts": [
        { "id": 1, "name": "Иван", "lastName": "Петров" }
      ],
      "user1": [
        { "ID": "1", "NAME": "Летта", "ACTIVE": true }
      ]
    },
    "totals": {
      "deals": 1798,
      "contacts": 305
    },
    "errors": {},
    "summary": {
      "total": 3,
      "succeeded": 3,
      "failed": 0
    },
    "meta": {
      "deals": { "total": 1798, "returned": 2, "hasMore": true, "truncated": false },
      "contacts": { "total": 305, "returned": 1, "hasMore": true, "truncated": false }
    }
  }
}

#Частичные ошибки

Если часть вызовов не прошла проверку или вернула ошибку на стороне Битрикс24, успешные результаты остаются в data.results, неудачные — в data.errors под тем же id:

JSON
{
  "success": true,
  "data": {
    "results": {
      "deals": [
        { "id": 575, "title": "Тест валюты" }
      ]
    },
    "totals": {
      "deals": 1798
    },
    "errors": {
      "unknown": {
        "code": "UNKNOWN_ENTITY",
        "message": "Unknown entity \"foobar\". Check GET /v1/guide for available entities."
      }
    },
    "summary": {
      "total": 2,
      "succeeded": 1,
      "failed": 1
    },
    "meta": {
      "deals": { "total": 1798, "returned": 1, "hasMore": true, "truncated": false }
    }
  }
}

#Пример ответа при ошибке

Если все вызовы не прошли валидацию, возвращается 400 INVALID_REQUEST с разбивкой по id в data.errors:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "All calls in the batch failed validation"
  },
  "data": {
    "errors": {
      "x": {
        "code": "MISSING_ENTITY_ID",
        "message": "Action \"get\" requires entityId."
      }
    }
  }
}

#Ошибки

HTTP Код Описание
400 INVALID_REQUEST Тело запроса не соответствует схеме или все вызовы провалили валидацию.
400 UNKNOWN_ENTITY В одном из вызовов передано неизвестное имя сущности.
400 ACTION_NOT_SUPPORTED Сущность не поддерживает указанное действие (например, delete для справочной сущности без удаления).
400 MISSING_ENTITY_ID Действия get, update, delete требуют entityId.
400 MISSING_DYNAMIC_PARAM Для смарт-процессов (entity: "items") не передан entityTypeId внутри params.
400 INVALID_DYNAMIC_PARAM entityTypeId для смарт-процессов задан некорректно (не положительное целое).
400 USE_DEDICATED_ENTITY Для переданного entityTypeId существует выделенная сущность — использовать её, а не items.
400 ENTITY_CUSTOM_ROUTES Сущность работает только через специализированные маршруты (например, task-comments — через /v1/tasks/:taskId/comments).
400 INVALID_CALL Объект вызова не содержит обязательных полей entity и action.
401 TOKEN_MISSING У ключа нет настроенных OAuth-токенов или для OAuth-приложения не передан Authorization: Bearer ....
401 TOKEN_REFRESH_FAILED Не удалось обновить OAuth-токен портала.
403 MANAGEMENT_KEY_NO_ENTITY_ACCESS Запрос пришёл с management-ключа — пакетные вызовы доступны только APP-ключам.
403 SCOPE_NOT_ALLOWED Все вызовы запросили скоупы, которых нет у ключа. Если хотя бы один вызов проходит — этот код возвращается внутри data.errors для конкретных вызовов, а сам запрос успешен.
422 BITRIX_ERROR Битрикс24 отклонил вызов. Тело ответа содержит bitrixError.error и bitrixError.error_description.
502 BITRIX_UNAVAILABLE Битрикс24 ответил с ошибкой 5xx.
503 QUEUE_OVERFLOW На портале накопилось слишком много одновременных вызовов Битрикс24 (по умолчанию более 100 в ожидании). Ответ возвращается мгновенно с HTTP-заголовком Retry-After: N (секунды) — клиент должен дождаться его и повторить с экспоненциальным backoff + jitter. Тело: error.code = QUEUE_OVERFLOW, error.retryAfter дублирует заголовок.
504 QUEUE_TIMEOUT Запрос ожидал в очереди портала более 30 секунд. Ответ содержит userMessage и hint.
500 INTERNAL_ERROR Внутренняя ошибка прокси.

Полный список общих ошибок API — Коды ошибок.

#Известные особенности

search и list с limit > 50 обходят нативный пакетный вызов Битрикс24. Эти вызовы выполняются как отдельные последовательные запросы со страничной выборкой до 5000 записей — каждый потребляет свою квоту rate-limit Битрикс24 независимо. Остальные вызовы — list с limit ≤ 50, get, create, update, delete, fields — объединяются в один пакетный вызов на стороне Битрикс24 и стоят одну единицу rate-limit суммарно.

Стоимость list в единицах rate-limit Битрикс24. Каждые 50 записей = 1 единица. При limit > 50 авто-пагинатор делает несколько вызовов:

limit Единиц Битрикс24
1–50 1 (нативный batch)
51–2 550 2
2 551–5 000 3

Если действие в одном вызове провалилось, остальные продолжают выполняться. Ошибки попадают в data.errors под тем же id, успешные результаты — в data.results. Поле success остаётся true, проверять нужно data.summary.failed или присутствие нужного id в data.results.

users.get возвращает массив, а не объект. Это особенность Entity API: ответ get для пользователей — [ { ID, NAME, ... } ]. Первый элемент — искомая запись.

Пакетные изменения для одной сущности. Если нужно создать, обновить или удалить много записей одной сущности (до 500 штук), используется специализированный эндпоинт POST /v1/{entity}/batch с телом { "action": "create" | "update" | "delete", "items" | "ids": [...] }. Он выполняет операции внутренними пакетами по 50 записей и возвращает массив результатов с пометкой success для каждого элемента.

#Смотрите также