Для AI-агентов: markdown этой страницы — /docs-content/entities/shipment-items/batch.md индекс документации — /llms.txt
Пакетные операции с позициями отгрузок
POST /v1/shipment-items/batch
Массовое создание, изменение, удаление или чтение позиций отгрузок одним запросом — до 500 элементов на запись и до 50 вызовов на чтение. Это отдельный эндпоинт сущности, не путать с универсальным batch, который объединяет операции разных сущностей и ограничен 50 вызовами.
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
action |
string | да | Операция пакета: create, update, delete — запись, list, get — чтение. Один запрос выполняет одну операцию |
items |
array | да при create и update |
Список элементов, до 500 |
items[].orderDeliveryId |
number | да при create |
ID отгрузки. Список: GET /v1/shipments. При update не передаётся — поле только для чтения |
items[].basketId |
number | да при create |
ID позиции корзины того же заказа. Список: GET /v1/basket-items. При update не передаётся — поле только для чтения |
items[].quantity |
number | да | Количество товара в отгрузке, дробное значение сохраняется без округления. Обязательно и при create, и в каждом элементе update. Элемент update без quantity не отклоняет пакет, а завершается ошибкой внутри ответа 200 |
items[].xmlId |
string | нет | Внешний код |
items[].id |
number | да при update |
ID позиции отгрузки. Список: GET /v1/shipment-items |
ids |
number[] | да при delete |
ID позиций отгрузок для удаления, до 500. Список: GET /v1/shipment-items |
calls |
array | да при list и get |
Список вызовов чтения, до 50. Каждый вызов — объект { "params": { … } } |
calls[].params |
object | да | Для list — параметры списка позиций: filter, select, limit, offset. Для get — { "id": 1363 } |
Набор полей элемента items совпадает с телом POST /v1/shipment-items и PATCH /v1/shipment-items/:id. Полный список полей позиции — GET /v1/shipment-items/fields.
Тело create — в разделе «Примеры». Тела остальных операций:
update—{ "action": "update", "items": [{ "id": 1363, "quantity": 0.75 }] }delete—{ "action": "delete", "ids": [1363] }list—{ "action": "list", "calls": [{ "params": { "filter": { "orderDeliveryId": 985 }, "limit": 50 } }] }get—{ "action": "get", "calls": [{ "params": { "id": 1363 } }] }
Примеры
curl — личный ключ
curl -X POST "https://vibecode.bitrix24.tech/v1/shipment-items/batch" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "create",
"items": [
{ "orderDeliveryId": 1215, "basketId": 1387, "quantity": 0.5 }
]
}'
curl — OAuth-приложение
curl -X POST "https://vibecode.bitrix24.tech/v1/shipment-items/batch" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "create",
"items": [
{ "orderDeliveryId": 1215, "basketId": 1387, "quantity": 0.5 }
]
}'
JavaScript — личный ключ
const res = await fetch('https://vibecode.bitrix24.tech/v1/shipment-items/batch', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'create',
items: [
{ orderDeliveryId: 1215, basketId: 1387, quantity: 0.5 },
],
}),
})
const { data } = await res.json()
data.results.forEach((item) => {
if (item.success) console.log(`#${item.index} → id=${item.id}`)
else console.log(`#${item.index} → ошибка: ${item.error} ${item.message}`)
})
JavaScript — OAuth-приложение
const res = await fetch('https://vibecode.bitrix24.tech/v1/shipment-items/batch', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'create',
items: [
{ orderDeliveryId: 1215, basketId: 1387, quantity: 0.5 },
],
}),
})
const { data } = await res.json()
Поля ответа
Форма data зависит от операции. Для create, update и delete:
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | Всегда true, если запрос прошёл проверку целиком. Результат каждого элемента — в data.results[i].success |
data.results |
array | Массив результатов в том же порядке, что items или ids запроса |
data.results[].index |
number | Индекс элемента, начиная с 0 |
data.results[].success |
boolean | Результат этой операции |
data.results[].id |
number | ID позиции отгрузки — созданной, изменённой или удалённой. В элементе с ошибкой отсутствует |
data.results[].error |
string | Код ошибки элемента с ошибкой, например 201250000001 для повтора пары basketId + orderDeliveryId |
data.results[].message |
string | Текст ошибки элемента с ошибкой |
data.summary.total |
number | Всего обработано элементов |
data.summary.succeeded |
number | Сколько выполнено успешно |
data.summary.failed |
number | Сколько завершилось ошибкой |
Для list и get поле data — массив результатов в порядке calls, а не объект с results. Каждый элемент несёт либо data, либо error. Код ошибки здесь лежит в объекте error.code, а при записи — строкой в data.results[].error:
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | Всегда true, если запрос прошёл проверку целиком |
data[].data |
array | object | null | Для list — массив позиций, для get — объект позиции или null. Поля позиции — Поля позиции отгрузки. С select в позиции только перечисленные поля |
data[].total |
number | Только list — количество позиций под фильтр вызова |
data[].hasMore |
boolean | Только list — есть ли позиции за пределами limit и offset |
data[].error.code |
string | Код ошибки вызова с ошибкой: CALL_FAILED для несуществующего id, INVALID_PARAMS для нецелого id, код проверки фильтра для неверного filter, например UNKNOWN_FILTER_FIELD |
data[].error.message |
string | Текст ошибки вызова с ошибкой |
Пример ответа
action: create — позиция создана:
{
"success": true,
"data": {
"results": [
{ "index": 0, "success": true, "id": 1363 }
],
"summary": { "total": 1, "succeeded": 1, "failed": 0 }
}
}
action: create — второй элемент повторил пару basketId + orderDeliveryId первого и завершился ошибкой, а верхний success остался true:
{
"success": true,
"data": {
"results": [
{ "index": 0, "success": true, "id": 1361 },
{
"index": 1,
"success": false,
"error": "201250000001",
"message": "Duplicate entry for key [basketId, orderDeliveryId]"
}
],
"summary": { "total": 2, "succeeded": 1, "failed": 1 }
}
}
action: list — два вызова по отгрузкам 975 и 985 с фильтром { "orderDeliveryId": { "$in": [975, 985] } }: первый с select: ["id", "orderDeliveryId", "quantity"], второй с limit: 1 и offset: 1:
{
"success": true,
"data": [
{
"data": [
{ "id": 875, "orderDeliveryId": 975, "quantity": 1 },
{ "id": 885, "orderDeliveryId": 985, "quantity": 10 },
{ "id": 887, "orderDeliveryId": 985, "quantity": 5 }
],
"total": 3,
"hasMore": false
},
{
"data": [
{
"basketId": 953,
"dateInsert": "2025-03-03T22:02:39.000Z",
"id": 885,
"orderDeliveryId": 985,
"quantity": 10,
"reservedQuantity": 0,
"xmlId": "bx_67c618efc3256"
}
],
"total": 3,
"hasMore": true
}
]
}
Пример ответа при ошибке
400 — в элементе create нет обязательного поля, пакет отклонён целиком:
{
"success": false,
"error": {
"code": "BATCH_ITEM_VALIDATION",
"message": "Item at index 0: field 'basketId' is required to create shipmentItem"
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | INVALID_BATCH_ACTION |
action не передан или не входит в список допустимых операций — список приходит в тексте ошибки |
| 400 | BATCH_ITEM_VALIDATION |
items, ids или calls пустой либо не массив, или элемент items не объект |
| 400 | BATCH_ITEM_VALIDATION |
В элементе create нет orderDeliveryId, basketId или quantity, либо передано поле только для чтения: id, dateInsert, reservedQuantity |
| 400 | BATCH_ITEM_VALIDATION |
В элементе update нет id, нет ни одного поля, кроме id, или передано поле только для чтения: orderDeliveryId, basketId |
| 400 | BATCH_ITEM_VALIDATION |
Значение поля не того типа, например объект в quantity — сообщение называет поле и ожидаемый тип |
| 400 | BATCH_ITEM_VALIDATION |
В элементе передан объект fields; сообщение содержит индекс элемента и NESTED_FIELDS_ENVELOPE. Передавайте поля позиции плоско в корне элемента |
| 400 | BATCH_ITEM_VALIDATION |
ID в ids или items[].id не целое неотрицательное число, например "1.5" |
| 400 | BATCH_LIMIT_EXCEEDED |
Больше 500 элементов в items или ids, либо больше 50 вызовов в calls |
| 403 | SCOPE_DENIED |
API-ключ не имеет скоупа sale |
| 403 | WRITE_BLOCKED_READONLY_KEY |
create, update или delete ключом в режиме «только чтение» — пакет не выполняется |
| 403 | MANAGEMENT_KEY_NO_ENTITY_ACCESS |
Управляющий ключ: разделы с сущностями ему недоступны, нужен личный ключ или ключ OAuth-приложения |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 401 | TOKEN_MISSING |
API-ключ не имеет настроенных токенов |
| 429 | RATE_LIMITED |
Превышен лимит запросов: 30 в минуту на портал — пакетный запрос дороже одиночного чтения, все API-ключи портала делят один лимит. Точное значение — в заголовке x-ratelimit-limit (потолок делится на реплики). Повторите после срока из заголовка Retry-After |
Ответ 400 означает, что пакет отклонён целиком до записи. Ошибки отдельных элементов приходят внутри ответа 200: при записи — в data.results[i] полями error и message, при чтении — в data[i].error. Так завершается, например, элемент update без quantity — с ошибкой «Required fields: quantity».
Полный список общих ошибок API — Ошибки.
Известные особенности
Позиция системной отгрузки в get возвращается как null, а update по ней не проходит. В отличие от одиночного GET /v1/shipment-items/:id, который отвечает 404, вызов get в пакете возвращает { "data": null } без ошибки. Элемент update для такой позиции завершается ошибкой, как и одиночный PATCH, а остальные элементы пакета продолжают обрабатываться. Что такое системная отгрузка — Позиции отгрузок.