# Writeoff. Списания

> Источник: https://wiki.virtualpos.ru/hc/api/writeoff  
> Обновлено: 2026-09-26

Методы для работы с документами «Списание»: получение документов со строками, создание документа и его строк, проведение (списание товара со склада) и аннулирование, удаление.

> **Примечание:**
> Как получить ключ, как формируются запросы и какие бывают ответы и ошибки — в статье [Общие сведения](https://wiki.virtualpos.ru/hc/api/overview). Здесь описаны только особенности методов раздела `writeoff`. Как работать со списаниями в панели управления — в статье [Списание товара](https://wiki.virtualpos.ru/hc/stock/writeoff).

## Методы

| Метод | Адрес | Что делает |
| --- | --- | --- |
| Получить списания | `/api/writeoff` | Возвращает документы списания с фильтрами по датам и точке продаж |
| Создать или изменить документ | `/api/writeoff/update` | Обновляет шапку документа или создаёт документ, проводит и аннулирует |
| Удалить документ | `/api/writeoff/delete` | Удаляет документ-черновик |
| Создать или изменить строку | `/api/writeoff/updateItems` | Обновляет строку черновика или добавляет новую |
| Удалить строку | `/api/writeoff/deleteItems` | Удаляет строку черновика |

> **Важно:**
> **Где передавать параметры.** Ключ `apikey` и формат `format` принимаются и в адресной строке, и в теле POST-запроса. Параметры `id`, `external_id` и `create_if_not_exist` в методах `update`, `delete`, `updateItems` и `deleteItems` читаются **только из адресной строки (GET)**. Остальные параметры можно передавать и в адресной строке, и в теле POST. Значения с кириллицей, пробелами и знаками `+` кодируйте.

## Статусы документа

| Значение | Название | Что означает |
| --- | --- | --- |
| `draft` | Черновик | Документ наполняется, остатки не менялись. Только черновик и его строки можно изменять и удалять |
| `done` | Списан | Товар списан со склада, остатки уменьшены |

Статус меняется параметром `status` метода `update`: `done` проводит документ и списывает товар, `draft` у проведённого документа аннулирует списание и возвращает остатки.

## Получение списаний

```
GET https://[компания].myvirtualpos.ru/api/writeoff?apikey=MySecret&days=90&warehouse_id=6&withitems=1
```

### Параметры запроса

- **id** — Число. Ид документа. Если указан, ищется только этот документ
- **external_id** — Строка. Код документа во внешней системе (например, в 1С). Действует, если не указан `id`
- **last_id** — Число. Вернуть документы с ид больше указанного. Действует, если не указаны `id` и `external_id`
- **warehouse_id** — Число. Ид точки продаж. Если не указан, возвращаются документы всех точек
- **ext_warehouse_id** — Строка. Код точки продаж во внешней системе. Действует, если не указан `warehouse_id`. Если точки с таким кодом нет, возвращается пустой список
- **date** — Дата `ГГГГММДД`. Документы с этой датой документа
- **datefrom**, **dateto** — Дата `ГГГГММДД`. Документы с датой документа с указанной даты и по указанную включительно
- **cdatefrom**, **cdateto** — Дата `ГГГГММДД`. То же по дате создания документа в системе
- **days** — Число. Глубина поиска в днях от текущей даты по дате документа. По умолчанию **30**
- **withitems** — `1` — добавить строки документов. По умолчанию возвращаются только шапки
- **format** — `json` (по умолчанию) или `xml`

Условия объединяются по «и». Даты передаются строго в формате `ГГГГММДД`, иначе метод вернёт ошибку `Incorrect date format`. Документы возвращаются по убыванию `id`: новые первыми.

> **Важно:**
> **Ограничение `days` действует всегда.** По умолчанию отбираются только документы за последние 30 дней по дате документа, и это ограничение накладывается вместе со всеми остальными условиями, в том числе `id`, `external_id` и датами. Чтобы получить старые документы, добавьте `days` с достаточным значением, например `days=3650`. При `days=0` ограничение снимается, и метод пытается собрать в одном ответе все документы; на больших базах это может закончиться ошибкой сервера по памяти.

### Структура ответа

- **success** — `1` — данные получены
- **type** — Тип данных, всегда `writeoff`
- **days_limit** — Число дней глубины поиска: `30` по умолчанию или значение `days`
- **count** — Количество документов в ответе
- **writeoffs** — Список документов. Каждый обёрнут в объект `writeoff`

### Поля документа

Пустые значения в JSON приходят как `null`, в XML — как пустой элемент.

- **id** — Число. Ид документа
- **external_id** — Строка. Код документа во внешней системе
- **guid** — Строка. Уникальный идентификатор документа (GUID)
- **docnum** — Строка. Номер документа
- **docdate** — Строка. Дата документа, формат `гггг-мм-дд чч:мм:сс`
- **status**, **status_name** — Строка. Код и название статуса, см. раздел «Статусы документа»
- **type** — Строка. Тип списания: `G` — товары, `M` — материальные ценности
- **reason** — Строка. Название причины списания
- **comment** — Строка. Комментарий
- **amount** — Строка. Сумма списания по себестоимости
- **warehouse_id** — Число. Ид точки продаж
- **warehouse_external_id** — Строка. Код точки продаж во внешней системе
- **created_date**, **last_update_date** — Строка. Дата и время создания и последнего изменения
- **created_by**, **last_update_by** — Число. Ид пользователя, создавшего и изменившего документ
- **items** — Список строк; при `withitems=0` пустой. Каждая строка обёрнута в объект `item`

### Поля строки

- **line_id** — Число. Ид строки
- **guid** — Строка. Идентификатор строки (GUID); используется как код строки при обращении к строке по `external_id`
- **item_id** — Число. Ид товара
- **item_ext_id** — Строка. Код товара во внешней системе
- **item_name** — Строка. Название товара
- **quantity** — Строка. Количество
- **barcode** — Строка. Штрихкод
- **price** — Строка. Себестоимость единицы
- **amount** — Строка. Сумма по строке
- **lot_number** — Строка. Серия (партия)
- **manuf_date**, **expir_date** — Строка. Дата изготовления и срок годности

### Пример ответа

```json
{
  "success": 1,
  "type": "writeoff",
  "days_limit": 90,
  "count": 1,
  "writeoffs": [
    {
      "writeoff": {
        "id": 15125,
        "external_id": "WO-2026-08",
        "guid": "5A07A106-A1A8-ECBC-2BA7-113B8662F9AF",
        "warehouse_id": 8,
        "docnum": "15125",
        "docdate": "2026-08-31 00:00:00",
        "amount": "225.00",
        "status": "done",
        "status_name": "Списан",
        "comment": "Просрочка",
        "warehouse_external_id": "WH-8",
        "type": "G",
        "reason": "Истёк срок годности",
        "created_date": "2026-08-31 18:10:00",
        "created_by": 6,
        "last_update_date": "2026-08-31 18:15:00",
        "last_update_by": 6,
        "items": [
          {
            "item": {
              "line_id": 24900,
              "guid": "3A148213-7184-B497-9C31-566F439CED63",
              "item_id": 795,
              "item_ext_id": "SKU-795",
              "item_name": "Форма для наращивания",
              "quantity": "3.000",
              "barcode": null,
              "price": "75.0000",
              "amount": "225.00",
              "manuf_date": null,
              "expir_date": null,
              "lot_number": null
            }
          }
        ]
      }
    }
  ]
}
```

Тот же ответ при `format=xml` (сокращённо):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <success>1</success>
  <type>writeoff</type>
  <days_limit>90</days_limit>
  <count>1</count>
  <writeoffs>
    <writeoff>
      <id>15125</id>
      <status>done</status>
      <!-- остальные поля шапки -->
      <items>
        <item>
          <line_id>24900</line_id>
          <item_id>795</item_id>
          <quantity>3.000</quantity>
          <!-- остальные поля строки -->
        </item>
      </items>
    </writeoff>
  </writeoffs>
</root>
```

## Создание и изменение документа

```
POST https://[компания].myvirtualpos.ru/api/writeoff/update?apikey=MySecret&external_id=WO-2026-09&create_if_not_exist=1
warehouse_id=6&docnum=WO-1&docdate=2026-09-01&type=G&reason_id=2&comment=Просрочка
```

Документ ищется по `id`, а если он не указан — по `external_id`. Если документ не найден, а передан `create_if_not_exist=1`, создаётся новый. Изменяются только переданные параметры.

### Параметры

- **id** — Число. Ид документа. Только GET
- **external_id** — Строка. Код документа во внешней системе. Если `id` не указан, по нему ищется документ; одновременно это поле документа: при создании код сохраняется. Только GET
- **create_if_not_exist** — `1` — создать документ, если он не найден. Только GET
- **warehouse_id** — Число. Ид точки продаж. Обязателен при создании
- **warehouse_external_id** — Строка. Код точки продаж во внешней системе. Заменяет `warehouse_id`, если точка с таким кодом найдена; если не найдена, параметр молча игнорируется
- **docnum** — Строка, до 255 символов. Номер документа. Обязателен при создании
- **docdate** — Дата документа в формате `гггг-мм-дд`. Обязателен при создании
- **type** — `G` — списание товаров, `M` — материальных ценностей. Обязателен при создании
- **reason_id** — Число. Ид причины списания; причина должна существовать
- **comment** — Строка. Комментарий
- **guid** — Строка. Идентификатор документа. Если не указан, при создании через API остаётся пустым
- **status** — `done` — провести документ, `draft` — аннулировать проведение. Другие значения отклоняются
- **attribute1** … **attribute15** — Значения гибких полей документа

### Ответ

```json
{"success":1,"id":"15127","isnew":"1"}
```

- **success** — `1` — документ сохранён
- **id** — Ид документа. При создании приходит строкой, при изменении — числом
- **isnew** — `"1"` — документ создан, `"0"` — изменён существующий

> **Важно:**
> **Проведение списывает товар со склада.** При `status=done` количество каждой строки вычитается из остатка точки продаж (с учётом серии). Проведение невозможно, если в документе нет строк или остатка не хватает (кроме случая, когда в настройках разрешено списание в минус): тогда придёт ошибка `Cannot change status` с причиной, а документ останется черновиком. `status=draft` у проведённого документа возвращает остатки. Аннулировать документ без строк нельзя.

## Удаление документа

```
GET https://[компания].myvirtualpos.ru/api/writeoff/delete?apikey=MySecret&id=15127
```

- **id** — Число. Ид удаляемого документа. Только GET
- **external_id** — Строка. Код документа во внешней системе. Только GET

Удалить можно только документ в статусе `draft`. Чтобы удалить проведённый документ, сначала аннулируйте его (`status=draft`). Ответ: `{"success":1,"id":15127}`.

## Строки документа

Строки создаются и изменяются только у черновика: строки проведённого документа менять и удалять нельзя, иначе остатки на складе разошлись бы с документом.

### updateItems. Создать или изменить строку

```
POST https://[компания].myvirtualpos.ru/api/writeoff/updateItems?apikey=MySecret&create_if_not_exist=1
writeoff_id=15127&item_id=795&quantity=2&cogs=11.24
```

- **id** — Число. Ид строки. Только GET
- **external_id** — Строка. Идентификатор строки (`guid`). Только GET
- **create_if_not_exist** — `1` — добавить строку, если она не найдена. Только GET
- **writeoff_id** — Число. Ид документа. Обязателен при создании строки
- **item_id** — Число. Ид товара; товар должен существовать. Обязателен
- **quantity** — Число не меньше 0,001. Количество. Обязательно
- **cogs** — Число. Себестоимость единицы
- **retail_price** — Число. Розничная цена
- **lot_number** — Строка. Серия (партия)
- **barcode** — Строка. Штрихкод
- **manuf_date**, **expir_date** — Дата изготовления и срок годности
- **guid** — Строка. Идентификатор строки, по нему её можно найти параметром `external_id`. Если не указан, остаётся пустым
- **onhand_id** — Число. Ид остатка, с которого списывается товар. Если не указан, подбирается по товару и серии

Ответ: `{"success":1,"id":"24900","isnew":"1"}`.

### deleteItems. Удалить строку

```
GET https://[компания].myvirtualpos.ru/api/writeoff/deleteItems?apikey=MySecret&id=24900
```

- **id** — Число. Ид строки. Только GET
- **external_id** — Строка. Идентификатор строки (`guid`). Только GET

Ответ: `{"success":1,"id":24900}`.

## Примеры запросов

| Задача | Запрос |
| --- | --- |
| Списания за последние 30 дней (шапки) | `/api/writeoff?apikey=MySecret` |
| Списания точки за квартал со строками | `/api/writeoff?apikey=MySecret&days=90&warehouse_id=6&withitems=1` |
| Документ по коду из 1С | `/api/writeoff?apikey=MySecret&external_id=WO-2026-09&days=3650&withitems=1` |
| Создать документ | `/api/writeoff/update?apikey=MySecret&create_if_not_exist=1&external_id=WO-1&warehouse_id=6&docnum=1&docdate=2026-09-01&type=G` |
| Добавить строку | `/api/writeoff/updateItems?apikey=MySecret&create_if_not_exist=1&writeoff_id=15127&item_id=795&quantity=2` |
| Провести документ | `/api/writeoff/update?apikey=MySecret&id=15127&status=done` |
| Аннулировать проведение | `/api/writeoff/update?apikey=MySecret&id=15127&status=draft` |

## Ошибки

Ошибка авторизации и общие ошибки описаны в статье [Общие сведения](https://wiki.virtualpos.ru/hc/api/overview). Ошибки методов приходят с кодом HTTP 200 и `success` равным `0`:

| Сообщение | Метод | Причина | Что делать |
| --- | --- | --- | --- |
| Incorrect date format '…'. Valid format is: YYYYMMDD | получение | Дата не в формате `ГГГГММДД` | Передайте дату как `20260901` |
| You have to specify [id] or [external_id] to update record | update, updateItems | Нет идентификатора и `create_if_not_exist` | Передайте идентификатор или `create_if_not_exist=1` |
| You have to specify [id] or [external_id] to delete record | delete, deleteItems | Нет идентификатора | Передайте `id` или `external_id` |
| Record not found | update, delete, updateItems, deleteItems | Документ или строка не найдены | Проверьте идентификатор |
| Data validation failed. … | update, updateItems | Не заполнены обязательные поля, несуществующие причина или товар, количество меньше 0,001 | Исправьте указанные поля |
| Unknown [status]. Use one of: [draft,done] | update | Недопустимый статус | Передайте `draft` или `done` |
| Cannot change status. … | update | Провести или аннулировать документ нельзя: нет строк, не хватает остатка | Текст после точки поясняет причину |
| Writeoff status is not draft | delete, updateItems, deleteItems | Документ проведён | Аннулируйте документ (`status=draft`) |
| Cannot save data. … | update, updateItems | Ошибка сохранения | Текст после точки поясняет причину |
| Cannot delete data. … | delete, deleteItems | Ошибка удаления | Текст после точки поясняет причину |

Если по условиям ничего не найдено, метод получения возвращает успешный ответ с `count` равным `0` и пустым списком `writeoffs`.

## Связанные разделы

- [Общие сведения](https://wiki.virtualpos.ru/hc/api/overview) — Ключ доступа, вызов методов, форматы ответов и ошибки
- [Списание товара](https://wiki.virtualpos.ru/hc/stock/writeoff) — Работа со списаниями в панели управления
- [Item. Номенклатура](https://wiki.virtualpos.ru/hc/api/item) — Товары в документе
- [Warehouse. Точки продаж](https://wiki.virtualpos.ru/hc/api/warehouse) — Справочник точек продаж
