## Update a shipment

`PATCH /v1/shipments/:id`

Updates an existing shipment of an online store order. Omitted fields are preserved.

Fields are passed flat at the JSON root, without a `fields` wrapper. How omitted fields are preserved — [Shipments](/docs/entities/shipments).

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `id` (path) | number | yes | Shipment ID. List: [`GET /v1/shipments`](./list.md) |

## Request fields (body)

| Field | Type | Description |
|------|-----|---------|
| `trackingNumber` | string | Tracking number |
| `deliveryDocNum` | string | Shipment document number |
| `deliveryDocDate` | datetime | Shipment document date |
| `allowDelivery` | boolean | Delivery is allowed |
| `statusId` | string | Delivery status. List: [`GET /v1/order-statuses?filter[type]=D`](/docs/entities/order-statuses/list) |
| `deliveryId` | number | Delivery service ID. List: [`GET /v1/delivery-services`](/docs/entities/delivery-services/list) |
| `priceDelivery` | number | Delivery price |
| `basePriceDelivery` | number | Base delivery price |
| `responsibleId` | number | ID of the responsible employee. List: [`GET /v1/users`](/docs/entities/users/list). An empty value, `null` or `0`, is not accepted |
| `companyId` | number | CRM company ID. List: [`GET /v1/companies`](/docs/entities/companies/list). The company's existence is not checked. An empty value is accepted only if the order has no company either — the `companyId` field in [`GET /v1/orders/:id`](/docs/entities/orders/get) |
| `comments` | string | Shipment comment |
| `xmlId` | string | External code |
| `orderId` | number | RO. Set only on [creation](./create.md) |
| `deducted` | boolean | RO. Changed via [`ship`](./ship.md) and [`unship`](./unship.md) |
| `customPriceDelivery` | boolean | RO. Manual delivery price flag |

Full field list — [`GET /v1/shipments/fields`](./fields.md).

## Examples

### curl — personal key

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/shipments/1205" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "trackingNumber": "VIBE-DOC-2",
    "deliveryDocNum": "TN-1205",
    "allowDelivery": true
  }'
```

### curl — OAuth application

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/shipments/1205" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "trackingNumber": "VIBE-DOC-2",
    "deliveryDocNum": "TN-1205",
    "allowDelivery": true
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/shipments/1205', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    trackingNumber: 'VIBE-DOC-2',
    deliveryDocNum: 'TN-1205',
    allowDelivery: true,
  }),
})

const { success, data } = await res.json()
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/shipments/1205', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    trackingNumber: 'VIBE-DOC-2',
    deliveryDocNum: 'TN-1205',
    allowDelivery: true,
  }),
})

const { success, data } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | `true` on success |
| `data` | object | The updated shipment with all fields, including omitted ones. All fields — [Shipment fields](./fields.md) |

## Response example

```json
{
  "success": true,
  "data": {
    "accountNumber": "1027/2",
    "allowDelivery": true,
    "basePriceDelivery": 500,
    "canceled": false,
    "comments": "Test shipment for documentation",
    "companyId": null,
    "currency": "USD",
    "customPriceDelivery": false,
    "dateAllowDelivery": "2026-10-06T11:31:17.000Z",
    "dateCanceled": null,
    "dateDeducted": null,
    "dateInsert": "2026-10-06T11:30:44.000Z",
    "dateMarked": null,
    "dateResponsibleId": "2026-10-06T11:30:44.000Z",
    "deducted": false,
    "deliveryDocDate": null,
    "deliveryDocNum": "TN-1205",
    "deliveryId": 1,
    "deliveryName": "Courier delivery",
    "deliveryXmlId": null,
    "discountPrice": 0,
    "empAllowDeliveryId": 1317,
    "empCanceledId": null,
    "empDeductedId": null,
    "empMarkedId": null,
    "empResponsibleId": 1317,
    "externalDelivery": false,
    "id": 1205,
    "id1c": null,
    "marked": false,
    "orderId": 1027,
    "priceDelivery": 500,
    "reasonMarked": null,
    "reasonUndoDeducted": null,
    "responsibleId": 1295,
    "shipmentItems": [],
    "statusId": "DN",
    "statusXmlId": null,
    "system": false,
    "trackingDescription": null,
    "trackingLastCheck": null,
    "trackingNumber": "VIBE-DOC-2",
    "trackingStatus": null,
    "updated1c": false,
    "version1c": null,
    "xmlId": "bx_6ac4cdd46e442"
  }
}
```

## Error response example

400 — an empty `responsibleId` was passed:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Bitrix24 cannot preserve an empty shipment responsibleId and its assignment metadata. Set an explicit nonzero responsibleId or update the shipment in Bitrix24."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `READONLY_FIELD` | The body contains `deducted`. The response contains a `hint` with the [`ship`](./ship.md) and [`unship`](./unship.md) endpoints |
| 400 | `READONLY_FIELD` | The body contains another read-only field: `customPriceDelivery`, `orderId`, `accountNumber` and others. The field name is in `message` |
| 400 | `EMPTY_UPDATE_BODY` | The request body is empty |
| 400 | `INVALID_PARAMS` | The body contains no known shipment field — `At least one writable shipment field is required.` |
| 400 | `INVALID_PARAMS` | The same field is passed twice under different names, such as `trackingNumber` and `TRACKING_NUMBER` — `Duplicate field alias` |
| 400 | `INVALID_PARAMS` | The responsible person would be empty after the write: `responsibleId` is passed as `null` or `0`, or it is omitted and the stored shipment has no responsible person. Pass a nonzero `responsibleId` |
| 400 | `INVALID_PARAMS` | The shipment company would be empty after the write, while the order has a different company. Pass a nonzero `companyId` |
| 400 | `INVALID_PARAMS` | The stored shipment has a manual delivery price (`customPriceDelivery` is `true`). Change such a shipment in the Bitrix24 interface |
| 400 | `INVALID_PARAMS` | A field value does not match its type, such as a word in the numeric `priceDelivery` or an object in the text `comments`. The field name is in `message` |
| 400 | `INVALID_PARAMS` | `id` in the path is not a non-negative integer |
| 404 | `ENTITY_NOT_FOUND` | No shipment with this `id` exists |
| 422 | `BITRIX_NO_EFFECT` | Bitrix24 did not return the shipment fields or the order needed to preserve the omitted fields. No write was performed |
| 422 | `BITRIX_ERROR` | Bitrix24 rejected the write or the read of the shipment's order. The reason is in `message` |
| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no permission to edit orders in Bitrix24 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is in read-only mode |
| 403 | `SCOPE_DENIED` | The API key does not have the `sale` scope |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**Allowing delivery records the date and the employee.** After `allowDelivery: true`, the response contains the date delivery was allowed, `dateAllowDelivery`, and the ID of the employee who allowed it, `empAllowDeliveryId`.

**Field names are also accepted in upper case.** `TRACKING_NUMBER` is saved the same way as `trackingNumber`.

## See also

- [Shipments](/docs/entities/shipments)
- [Get a shipment](./get.md)
- [Create a shipment](./create.md)
- [Set the "shipped" mark](./ship.md)
- [Remove the "shipped" mark](./unship.md)
- [Shipment fields](./fields.md)
- [Shipment items](/docs/entities/shipment-items)
