For AI agents: markdown of this page — /docs-content-en/entities/shipment-items/batch.md documentation index — /llms.txt
Batch operations on shipment items
POST /v1/shipment-items/batch
Create, update, delete or read shipment items in bulk with one request — up to 500 items per write and up to 50 calls per read. This is a dedicated endpoint for this entity, not to be confused with the universal batch, which combines operations on different entities and is limited to 50 calls.
Request fields (body)
| Field | Type | Required | Description |
|---|---|---|---|
Fieldaction |
Typestring | Requiredyes | DescriptionBatch operation: create, update, delete for writes, list, get for reads. One request performs one operation |
Fielditems |
Typearray | Requiredyes for create and update |
DescriptionList of items, up to 500 |
Fielditems[].orderDeliveryId |
Typenumber | Requiredyes for create |
DescriptionShipment ID. List: GET /v1/shipments. Not passed in update — the field is read-only |
Fielditems[].basketId |
Typenumber | Requiredyes for create |
DescriptionID of a basket item of the same order. List: GET /v1/basket-items. Not passed in update — the field is read-only |
Fielditems[].quantity |
Typenumber | Requiredyes | DescriptionProduct quantity in the shipment; a fractional value is stored without rounding. Required both in create and in every update item. An update item without quantity does not reject the batch — it fails inside a 200 response |
Fielditems[].xmlId |
Typestring | Requiredno | DescriptionExternal code |
Fielditems[].id |
Typenumber | Requiredyes for update |
DescriptionShipment item ID. List: GET /v1/shipment-items |
Fieldids |
Typenumber[] | Requiredyes for delete |
DescriptionIDs of the shipment items to delete, up to 500. List: GET /v1/shipment-items |
Fieldcalls |
Typearray | Requiredyes for list and get |
DescriptionList of read calls, up to 50. Each call is an object { "params": { … } } |
Fieldcalls[].params |
Typeobject | Requiredyes | DescriptionFor list — the item list parameters: filter, select, limit, offset. For get — { "id": 1363 } |
The field set of an items element matches the body of POST /v1/shipment-items and PATCH /v1/shipment-items/:id. The full list of item fields is in GET /v1/shipment-items/fields.
The create body is in the "Examples" section. Bodies of the other operations:
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 } }] }
Examples
curl — personal key
curl -X POST "https://vibecode.bitrix24.com/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 application
curl -X POST "https://vibecode.bitrix24.com/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 — personal key
const res = await fetch('https://vibecode.bitrix24.com/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} → error: ${item.error} ${item.message}`)
})
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/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()
Response fields
The shape of data depends on the operation. For create, update and delete:
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true if the request passed validation as a whole. The result of each item is in data.results[i].success |
Fielddata.results |
Typearray | DescriptionArray of results in the same order as the request's items or ids |
Fielddata.results[].index |
Typenumber | DescriptionItem index, starting from 0 |
Fielddata.results[].success |
Typeboolean | DescriptionResult of this operation |
Fielddata.results[].id |
Typenumber | DescriptionID of the shipment item — created, updated or deleted. Absent in a failed item |
Fielddata.results[].error |
Typestring | DescriptionError code of a failed item, for example 201250000001 for a repeated basketId + orderDeliveryId pair |
Fielddata.results[].message |
Typestring | DescriptionError text of a failed item |
Fielddata.summary.total |
Typenumber | DescriptionTotal items processed |
Fielddata.summary.succeeded |
Typenumber | DescriptionHow many succeeded |
Fielddata.summary.failed |
Typenumber | DescriptionHow many failed |
For list and get, the data field is an array of results in the order of calls, not an object with results. Each element carries either data or error. Here the error code is in the error object as error.code, while for writes it is a string in data.results[].error:
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true if the request passed validation as a whole |
Fielddata[].data |
Typearray | object | null | DescriptionFor list — an array of items, for get — an item object or null. Item fields — Shipment item fields. With select, an item contains only the listed fields |
Fielddata[].total |
Typenumber | Descriptionlist only — number of items matching the call's filter |
Fielddata[].hasMore |
Typeboolean | Descriptionlist only — whether there are items beyond limit and offset |
Fielddata[].error.code |
Typestring | DescriptionError code of a failed call: CALL_FAILED for a non-existent id, INVALID_PARAMS for a non-integer id, a filter validation code for an invalid filter, for example UNKNOWN_FILTER_FIELD |
Fielddata[].error.message |
Typestring | DescriptionError text of a failed call |
Response example
action: create — the item is created:
{
"success": true,
"data": {
"results": [
{ "index": 0, "success": true, "id": 1363 }
],
"summary": { "total": 1, "succeeded": 1, "failed": 0 }
}
}
action: create — the second item repeated the basketId + orderDeliveryId pair of the first one and failed, while the top-level success stayed 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 — two calls for shipments 975 and 985 with the filter { "orderDeliveryId": { "$in": [975, 985] } }: the first with select: ["id", "orderDeliveryId", "quantity"], the second with limit: 1 and 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
}
]
}
Error response example
400 — a create item lacks a required field, so the whole batch is rejected:
{
"success": false,
"error": {
"code": "BATCH_ITEM_VALIDATION",
"message": "Item at index 0: field 'basketId' is required to create shipmentItem"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeINVALID_BATCH_ACTION |
Descriptionaction is not passed or is not one of the allowed operations — the list comes in the error text |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
Descriptionitems, ids or calls is empty or not an array, or an items element is not an object |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
DescriptionA create item lacks orderDeliveryId, basketId or quantity, or a read-only field is passed: id, dateInsert, reservedQuantity |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
DescriptionAn update item lacks id, has no field other than id, or a read-only field is passed: orderDeliveryId, basketId |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
DescriptionA field value has the wrong type, for example an object in quantity — the message names the field and the expected type |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
DescriptionAn item contains an object under fields; the message carries the item index and NESTED_FIELDS_ENVELOPE. Pass shipment item fields flat at the item's root |
| HTTP400 | CodeBATCH_ITEM_VALIDATION |
DescriptionAn ID in ids or items[].id is not a non-negative integer, for example "1.5" |
| HTTP400 | CodeBATCH_LIMIT_EXCEEDED |
DescriptionMore than 500 elements in items or ids, or more than 50 calls in calls |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key lacks the sale scope |
| HTTP403 | CodeWRITE_BLOCKED_READONLY_KEY |
Descriptioncreate, update or delete with a read-only key — the batch is not executed |
| HTTP403 | CodeMANAGEMENT_KEY_NO_ENTITY_ACCESS |
DescriptionManagement key: entity sections are not available to it. A personal key or an OAuth application key is required |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header is not passed |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no configured tokens |
| HTTP429 | CodeRATE_LIMITED |
DescriptionRate limit exceeded: 30 requests per minute per portal (a batch costs more than a plain read). All API keys of the portal share one limit. The current limit is returned in the x-ratelimit-limit header. Retry after the delay in the Retry-After header |
A 400 response means the whole batch is rejected before any write. Errors of individual items come inside a 200 response: for writes — in data.results[i] as the error and message fields, for reads — in data[i].error. This is how, for example, an update item without quantity fails — with the error "Required fields: quantity".
For the full list of common API errors, see Errors.
Known specifics
An item of a system shipment is returned as null by get, and update on it fails. Unlike the single GET /v1/shipment-items/:id, which responds with 404, a get call in the batch returns { "data": null } without an error. An update element for such an item fails, just like the single PATCH, while the other items of the batch continue to be processed. For an explanation of system shipments, see Shipment items.