Store. Остатки товара
Методы для работы с остатками товаров на точках продаж: получение остатков по точкам продаж и по товарам, установка остатков одиночно и пачкой, обнуление остатков, которые не были обновлены при полной загрузке.
Как получить ключ, как формируются запросы и какие бывают ответы и ошибки — в статье Общие сведения. Здесь описаны только особенности методов раздела store.
Методы
| Метод | Адрес | Что делает |
|---|---|---|
| Остатки по точкам | /api/store | Возвращает остатки по одной или всем точкам продаж |
| Остатки товара | /api/store/stock | Возвращает остатки одного товара по всем точкам |
| Остатки всех товаров | /api/store/byItem | Возвращает остатки товаров по всем точкам продаж в сжатом виде |
| Установить остаток | /api/store/updateOnhand | Устанавливает остаток одного товара на точке продаж |
| Массовая установка остатков | /api/store/multipleUpdateOnhand | Устанавливает остатки пачкой |
| Версия остатков | /api/store/getOnhandVersion | Возвращает версию данных об остатках точки |
| Обнулить неизменённые | /api/store/setZeroOnhand | Обнуляет остатки, не обновлённые с указанной версии |
Где передавать параметры. Ключ apikey и формат format принимаются и в адресной строке, и в теле POST-запроса. Параметры, которые указаны в описании методов как «Только GET» (это warehouseid, itemid, article, itemname, stockonly, from в методе store, параметры точки и товара в updateOnhand, getOnhandVersion, setZeroOnhand и version в setZeroOnhand), читаются только из адресной строки. Остальные параметры можно передавать и в адресной строке, и в теле POST. Значения с кириллицей и пробелами кодируйте.
Остатки по точкам продаж
GET https://[компания].myvirtualpos.ru/api/store?apikey=MySecret&warehouseid=6&limit=1000&fields=itemname:price
Параметры запроса
| warehouseid | Число. Ид точки продаж. Если не указан, возвращаются остатки всех точек. Только GET |
| itemid | Число. Ид товара. Только GET |
| article | Строка. Артикул товара. Только GET |
| itemname | Строка. Точное название товара. Только GET |
| stockonly | Значение по умолчанию — только товары с остатком больше нуля. Чтобы получить и нулевые остатки, передайте stockonly=0. Только GET |
| from | Дата и время (например, 2026-09-20 10:00:00). Остатки, изменившиеся или изменившие количество зарезервированного товара после этого момента. Только GET |
| from_id | Число. Вернуть остатки с ид записи остатка больше указанного. Служит для порционной выдачи |
| limit | Число, не более 1000. Максимальное количество остатков в ответе (для одной точки продаж). Без ограничения остатки собираются все |
| fields | Дополнительные поля через двоеточие, например itemname:price. Допустимые значения ниже |
| format | json (по умолчанию) или xml |
Остатки возвращаются по возрастанию ид записи остатка. Если точка продаж с указанным warehouseid не найдена, вернётся ошибка Data not found. Точки продаж без подходящих остатков в ответ не попадают.
Выгружайте порциями. Без limit метод собирает остатки по всем товарам в одном ответе; у точки продаж их могут быть десятки тысяч. Указывайте warehouseid, limit (например, 1000) и from_id: возьмите из ответа last_id и передайте его как from_id в следующем запросе, пока record_count меньше limit. Порционная выдача работает по одной точке продаж; без warehouseid поля total и last_id относятся к последней точке в ответе.
Дополнительные поля (''fields'')
| itemname | Название товара (name) |
| article | Артикул товара |
| cogs | Закупочная цена остатка |
| expdate | Срок годности остатка. Если не задан, приходит 0000-00-00 |
| price | Цена товара в основном прайс-листе точки продаж |
| optionalprices | Цены товара во всех прайс-листах: список prices с pricelistid и price |
| attributes | Список значений характеристик остатка: attribute с name и value |
| turnovercalc | Расчётная оборачиваемость товара на точке |
Если указано неизвестное поле, метод вернёт ошибку со списком допустимых значений.
Структура ответа
| success | 1 — данные получены |
| type | Тип данных, всегда store |
| stockonly | Значение параметра stockonly: true по умолчанию |
| total | Число. Сколько остатков подходит под условия, без учёта limit (по последней обработанной точке) |
| record_count | Число. Сколько остатков в ответе |
| count | Число. Количество точек продаж в ответе |
| last_id | Число. Ид записи последнего остатка в ответе. Используйте как from_id |
| warehouses | Список точек продаж. Каждая обёрнута в объект warehouse с полями id, name, count и списком items |
Остаток (item)
| id | Число. Ид товара |
| quantity | Строка. Количество на точке продаж |
| available_quantity | Число. Доступное количество: количество за вычетом зарезервированного в заказах |
| lot_number | Строка. Серия (партия). Для товара без серии — пустая строка |
| name, article, cogs, expdate, price, prices, attributes, turnovercalc | Дополнительные поля, если они запрошены в fields |
Пример ответа
{
"success": 1,
"type": "store",
"stockonly": true,
"total": 6034,
"record_count": 2,
"count": 1,
"last_id": 13027,
"warehouses": [
{
"warehouse": {
"id": 6,
"name": "Точка на Тверской",
"count": 2,
"items": [
{ "item": { "id": 1084, "quantity": "2.000", "lot_number": "", "available_quantity": 2, "name": "Форма для наращивания", "price": "499.00" } },
{ "item": { "id": 795, "quantity": "65.000", "lot_number": "", "available_quantity": 65, "name": "Форма многоразовая", "price": "100.00" } }
]
}
}
]
}
Тот же ответ при format=xml (сокращённо):
<?xml version="1.0" encoding="UTF-8"?> <root> <success>1</success> <type>store</type> <stockonly>1</stockonly> <total>6034</total> <record_count>2</record_count> <count>1</count> <last_id>13027</last_id> <warehouses> <warehouse> <id>6</id> <name>Точка на Тверской</name> <count>2</count> <items> <item><id>1084</id><quantity>2.000</quantity><lot_number/><available_quantity>2</available_quantity></item> </items> </warehouse> </warehouses> </root>
Остатки одного товара
GET https://[компания].myvirtualpos.ru/api/store/stock?apikey=MySecret&id=795
| id | Число. Ид товара |
| external_id | Строка. Код товара во внешней системе. Используется, если не указан id |
Ответ содержит:
| item | Все поля товара (название, артикул, тип, ставка НДС, гибкие поля и другие) |
| warehouses | Точки продаж, где у товара есть остаток. Каждая содержит поля точки продаж (ид, название, адрес, телефон, часы работы, код во внешней системе, гибкие поля) и список stocks с stock: quantity, available_quantity, lot_number |
Возвращаются только положительные остатки. Если товар не найден, придёт ошибка Item not found.
Остатки всех товаров по точкам
GET https://[компания].myvirtualpos.ru/api/store/byItem?apikey=MySecret&limit=1000&from_id=0&total=1
Компактная выгрузка «товар — остатки по всем точкам»: одна запись на товар.
| id | Число. Ид товара: вернуть только этот товар |
| from_id | Число. Вернуть товары с ид больше указанного |
| limit | Число. Максимальное количество товаров в ответе |
| total | 1 — посчитать и вернуть общее количество товаров (total). Иначе total равно null |
{
"success": 1,
"type": "store_by_item",
"last_id": 54,
"count": 3,
"total": 27168,
"items": [
{ "id": 52, "quantities": "2=1;3=0;4=0;6=0" },
{ "id": 53, "quantities": "2=1;3=1;4=0;6=0" }
]
}
Поле quantities содержит остатки по точкам продаж в виде ид_точки=количество через точку с запятой: от количества вычтено зарезервированное. Товары возвращаются по возрастанию ид; last_id используйте как from_id в следующем запросе.
Установка остатка
GET https://[компания].myvirtualpos.ru/api/store/updateOnhand?apikey=MySecret&warehouseid=6&itemid=52&quantity=20&cogs=125.5&lot_number=L1
Параметры
| warehouseid | Число. Ид точки продаж. Нужно указать warehouseid или ext_warehouseid. Только GET |
| ext_warehouseid | Строка. Код точки продаж во внешней системе. Только GET |
| itemid | Число. Ид товара. Нужно указать itemid или ext_itemid. Только GET |
| ext_itemid | Строка. Код товара во внешней системе. Только GET |
| quantity | Число. Новое количество на точке продаж. Ноль допустим. Значение заменяет прежнее, а не прибавляется |
| cogs | Число. Закупочная цена остатка. Для нового остатка без cogs цена равна нулю |
| lot_number | Строка. Серия (партия). Остаток определяется парой «товар + серия» |
| manuf_date, expir_date | Дата изготовления и срок годности остатка в формате гггг-мм-дд |
| attributes | Массив характеристик остатка вида [{«id»:1,«value»:«XL»}] или [{«ext_id»:«size»,«value»:«XL»}]. Учитывается при поиске остатка и при его создании |
Если остатка для такой пары нет, он создаётся. Остатки комплектов через API менять нельзя.
{"success":1,"id":"171587","itemid":38334,"lot_number":"L1","warehouseid":15,"isnew":"1","quantity_before":0}
| success | 1 — остаток сохранён |
| id | Ид записи остатка. При создании приходит строкой, при изменении — числом |
| itemid, warehouseid, lot_number | Ид товара, ид точки продаж и серия |
| isnew | «1» — остаток создан, «0» — изменён существующий |
| quantity_before | Количество до изменения |
Массовая установка остатков
POST https://[компания].myvirtualpos.ru/api/store/multipleUpdateOnhand?apikey=MySecret
data=[{"warehouseid":6,"itemid":52,"quantity":20},{"ext_warehouseid":"WH-6","ext_itemid":"SKU-53","quantity":5,"lot_number":"L1"}]
Параметр data — JSON-массив. Каждый элемент содержит warehouseid или ext_warehouseid, itemid или ext_itemid и поля остатка, как в методе updateOnhand. Элементы обрабатываются независимо.
| success | 1 — запрос обработан (даже если часть остатков не сохранена) |
| success_count | Количество сохранённых остатков |
| fails_count | Количество остатков с ошибками |
| problem_ids | Остатки, заданные по itemid, которые не удалось сохранить: объект problem_item с ид товара, без текста ошибки |
| problem_external_ids | То же для остатков, заданных по ext_itemid: problem_item с полями id (код) и message (текст ошибки) |
Для остатков, заданных по itemid, текст ошибки не возвращается. Если нужно понять причину, повторите запрос для этого товара методом updateOnhand: он вернёт сообщение.
Обнуление неизменённых остатков
Пара методов позволяет выгружать остатки «полным срезом»: после загрузки всех остатков точки нулевыми становятся те, которых в срезе не было.
- Перед загрузкой запросите версию остатков точки продаж методом
getOnhandVersion. - Загрузите остатки методами
updateOnhandилиmultipleUpdateOnhand. - Вызовите
setZeroOnhandс сохранённой версией: остатки точки, которые не обновлялись после этой версии, будут обнулены.
GET https://[компания].myvirtualpos.ru/api/store/getOnhandVersion?apikey=MySecret&warehouseid=6 GET https://[компания].myvirtualpos.ru/api/store/setZeroOnhand?apikey=MySecret&warehouseid=6&version=1790417774.000000
| warehouseid | Число. Ид точки продаж. Нужно указать warehouseid или ext_warehouseid. Только GET |
| ext_warehouseid | Строка. Код точки продаж во внешней системе. Только GET |
| version | Строка. Версия остатков из ответа getOnhandVersion (только для setZeroOnhand). Только GET |
Ответы: {«success»:1,«version»:«1790417774.000000»} для getOnhandVersion и {«success»:1,«affected»:4} для setZeroOnhand, где affected — количество обнулённых остатков.
Обнуление необратимо и затрагивает все остатки точки продаж. Метод обнуляет все остатки точки, изменённые до указанной версии: при неверной версии (например, 0) под обнуление попадёт весь склад. Вызывайте setZeroOnhand только после полной загрузки среза и только с версией, полученной перед загрузкой.
Примеры запросов
| Задача | Запрос |
|---|---|
| Первые 1000 остатков точки | /api/store?apikey=MySecret&warehouseid=6&limit=1000 |
| Следующие 1000 остатков | /api/store?apikey=MySecret&warehouseid=6&limit=1000&from_id=13027 |
| Остатки с ценой и названием | /api/store?apikey=MySecret&warehouseid=6&limit=1000&fields=itemname:price |
| Остатки, изменившиеся за сутки | /api/store?apikey=MySecret&warehouseid=6&from=2026-09-25%2010:00:00 |
| Остатки товара по артикулу | /api/store?apikey=MySecret&warehouseid=6&article=SH-1000&stockonly=0 |
| Остатки товара на всех точках | /api/store/stock?apikey=MySecret&id=795 |
| Установить остаток | /api/store/updateOnhand?apikey=MySecret&ext_warehouseid=WH-6&ext_itemid=SKU-52&quantity=20 |
Ошибки
Ошибка авторизации и общие ошибки описаны в статье Общие сведения. Ошибки приходят с кодом HTTP 200 и success равным 0:
| Сообщение | Метод | Причина | Что делать |
|---|---|---|---|
| Data not found | store | Точка продаж с таким warehouseid не найдена | Проверьте ид |
| Field '…' not found. Use combination of: […] | store | Неизвестное поле в fields | Используйте поля из списка |
| Item not found | stock, updateOnhand | Товар не найден | Проверьте ид или код |
| Warehouse not found | updateOnhand, getOnhandVersion, setZeroOnhand | Точка продаж не найдена | Проверьте ид или код |
| Can't update store data for kit ID=… | updateOnhand | Остатки комплектов менять нельзя | Меняйте остатки составляющих |
| Data validation failed. … | updateOnhand | Количество или другие значения не прошли проверку | Исправьте указанные поля |
| Cannot save data: … | updateOnhand | Ошибка сохранения | Текст после двоеточия поясняет причину |
| Could not create attribute: invalid format | updateOnhand | Характеристика без id или ext_id либо без value | Проверьте массив attributes |
| Invalid input format | multipleUpdateOnhand | data не JSON-массив | Передайте корректный JSON |
| Version parameter not specified | setZeroOnhand | Не передана version | Передайте версию из getOnhandVersion |