
## Update an order

`PATCH /v1/orders/:id`

Updates the fields of an existing order. Pass only the fields being changed, flat at the root of the JSON — no `fields` wrapper.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `id` (path) | number | yes | Order identifier |

## Request fields (body)

| Field | Type | Description |
|-------|------|-------------|
| `statusId` | string | New order status. List: [`GET /v1/order-statuses?filter[type]=O`](../order-statuses/list.md). Truncated to 2 characters without an error |
| `discountValue` | number | Discount value |
| `canceled` | boolean | Whether the order is canceled |
| `reasonCanceled` | string | Cancellation reason |
| `comments` | string | Manager's comment |
| `userDescription` | string | Buyer's comment |
| `responsibleId` | number | Responsible employee |
| `userId` | number | Bitrix24 user — the buyer. Existence is not checked |
| `companyId` | number | Identifier of the order's CRM company. Source: [`GET /v1/companies`](/docs/entities/companies). Returned as `null` if no company is set |
| `xmlId` | string | External identifier |

Full list of editable fields — [`GET /v1/orders/fields`](./fields.md) (fields without the `readonly` flag).

**`price`, `marked`, and `reasonMarked` are ignored on update.** The request returns `200`, but these fields are not saved — they are applied only on [creation](./create.md). `price` is recalculated from the basket items: a manually passed amount is ignored, and if the basket is empty it becomes `0`. To change the amount, edit the [basket items](../basket-items/create.md). `payed` is read-only — managed by the payments subsystem, an attempt to pass it returns `400 READONLY_FIELD`.

## Examples

### curl — personal key

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/orders/845" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "statusId": "F",
    "comments": "Closed after full payment"
  }'
```

### curl — OAuth application

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/orders/845" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "statusId": "F",
    "comments": "Closed after full payment"
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/orders/845', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    statusId: 'F',
    comments: 'Closed after full payment',
  }),
})

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

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/orders/845', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    statusId: 'F',
    comments: 'Closed after full payment',
  }),
})

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `data` | object | The updated order object with all fields (see [Order fields](./fields.md)) |

## Response example

```json
{
  "success": true,
  "data": {
    "id": 845,
    "accountNumber": "443",
    "statusId": "F",
    "price": 100,
    "currency": "USD",
    "payed": true,
    "canceled": false,
    "comments": "Closed after full payment",
    "dateInsert": "2026-04-21T06:48:16.000Z",
    "dateUpdate": "2026-05-13T11:45:32.000Z",
    "dateStatus": "2026-05-13T11:45:32.000Z",
    "userId": 1,
    "companyId": 15,
    "clients": [
      { "entityTypeId": 3, "entityId": 2471, "isPrimary": true, "roleId": 0, "sort": 0 },
      { "entityTypeId": 4, "entityId": 15, "isPrimary": true, "roleId": 0, "sort": 0 }
    ],
    "responsibleId": 1
  }
}
```

## Error response example

422 — order not found:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "order is not exists"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 422 | `BITRIX_ERROR` | An order with this ID was not found |
| 400 | `BITRIX_ERROR` | Invalid field value — for example, an unknown `statusId` |
| 400 | `READONLY_FIELD` | A read-only field was passed — for example, `accountNumber`. The order number is assigned automatically |
| 403 | `SCOPE_DENIED` | The API key does not have the `sale` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

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

## Known specifics

**The `dateStatus` field is updated automatically.** When `statusId` changes, `dateStatus` receives the current time — do not pass it in the request.

**The `accountNumber`, `dateInsert`, `personTypeXmlId`, `statusXmlId`, and other system fields are read-only.** Passing them on update is rejected with `400 READONLY_FIELD`.

## See also

- [Get an order](./get.md)
- [List orders](./list.md)
- [Delete an order](./delete.md)
- [Order fields](./fields.md)
- [Batch](/docs/batch)
- [Limits and optimization](/docs/optimization)
