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

Terminal
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

Terminal
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

javascript
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

javascript
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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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.

See also