API: загрузка закупочных цен из вашей программы
Обновлено · Команда «В плюсе»
Закупочные цены — единственные данные, которые маркетплейс о вас не знает: их вводите вы. Если закупки уже живут в вашей учётной системе — МойСклад, 1С, таблица со скриптом, — присылать их к нам можно программой, а не выгружать файл руками каждую неделю.
Для этого есть API: вы выпускаете ключ в кабинете, ваша программа шлёт с ним запросы. Всё, что делает API, вы можете сделать и руками в разделе «Цены» — API просто избавляет от ручной работы.
Кому это нужно
Только тем, у кого закупочные цены уже ведутся в другой программе. Если вы заводите цены руками или загружаете файл — API вам не нужен, ничего нового он не покажет.API входит в подписку, а не в бесплатный доступ
Ключ можно выпустить и на демо, и на подписке. На бесплатном доступе запросы к API отвечают402: это единственная часть сервиса, которая в него не входит. Всё остальное — на тех же условиях, что у всех.Как выпустить ключ
- 1
Профиль → «Ключи API» → «Настроить»
Или сразу по адресу «Ключи API». - 2
Назовите ключ и нажмите «Выпустить»
Название — по программе, которая будет им пользоваться: «МойСклад», «1С». Когда ключей несколько, только по названию и понятно, какой можно отозвать. - 3
Скопируйте ключ сразу
Мы храним не сам ключ, а его отпечаток, поэтому показать значение второй раз не сможем. Потеряли — выпустите новый, а старый отзовите.
Ключ — это доступ к вашим данным
Ключ работает вместо логина и пароля: кто им владеет, тот может читать и менять ваши закупочные цены. Не выкладывайте его в переписку, в публичный репозиторий и в скриншоты настроек. Если ключ мог утечь — отзовите его в кабинете, это действует сразу же.Как устроен запрос
Адрес — https://sellervpluse.ru/api/v1/…, ключ передаётся заголовком Authorization. Тело запросов и ответов — JSON.
curl https://sellervpluse.ru/api/v1/ping \
-H "Authorization: Bearer ВАШ_КЛЮЧ"{
"ok": true,
"account": { "email": "you@example.com" },
"key": { "name": "МойСклад" }
}Если вместо этого пришла ошибка — дальше идти незачем: сначала разберитесь с ключом, иначе ошибку загрузки цен не отличить от ошибки доступа.
Загрузка закупочных цен
POST /api/v1/prices — присылаете список артикулов с ценами и дату, с которой они действуют.
curl -X POST https://sellervpluse.ru/api/v1/prices \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"validFrom": "2026-08-01",
"prices": [
{ "article": "SHIRT-RED-M", "price": 450 },
{ "article": "SHIRT-BLUE-L", "price": 480.50 }
]
}'{
"created": 2,
"updated": 0,
"unchanged": 0,
"duplicates": 0,
"errors": []
}| Поле | Что означает |
|---|---|
validFrom | Дата в формате ГГГГ-ММ-ДД, с которой действуют присланные цены. Необязательное поле, но почти всегда его надо указывать — см. следующий раздел. Одна дата на весь запрос. |
prices[].article | Ваш артикул продавца — тот, под которым товар приходит в заказах. |
prices[].price | Закупочная цена за штуку, в рублях. Число, а не строка. Ноль не принимается: «ноль» — это не цена, а незаполненное поле. |
created / updated | Сколько цен добавлено и сколько исправлено. |
unchanged | Сколько артикулов пропущено: цена по ним уже такая же. Это нормальный результат ежедневной заливки всего прайса — записывается только то, что изменилось. |
errors | Строки, которые не удалось принять: артикул и причина. Остальные цены при этом записаны. |
За один запрос принимается до 50 000 цен, а тело запроса — до 10 МБ (прайс на 50 000 позиций весит около 2 МБ, так что упереться в мегабайты раньше, чем в строки, трудно). Запись целиком либо проходит, либо не проходит: половины не бывает, поэтому при ошибке достаточно повторить тот же запрос.
Главное про дату «действует с»
Не оставляйте validFrom пустым, если цены нужны к прошлым продажам
Без этого поля цены начинают действовать с сегодняшнего дня. Продажи прошлой недели останутся без себестоимости и не попадут в чистую прибыль вовсе — при этом в кабинете всё будет выглядеть так, будто цены загружены.Цены у нас хранятся с историей: у каждой есть период действия, и к продаже применяется та, что действовала в день продажи. Поэтому дата — это не формальность, а то, к каким продажам присланные цифры относятся.
Если вы поднимаете цены с сегодняшнего дня — поле можно не заполнять. Если загружаете закупки задним числом (первый раз или чтобы закрыть пробелы) — укажите дату, с которой они действовали на самом деле.
Каких цен не хватает
GET /api/v1/prices/missing отвечает на вопрос «по каким товарам вы продаёте, а закупки не знаете». Это тот же список, что в кабинете по кнопке «Товары без себестоимости».
curl "https://sellervpluse.ru/api/v1/prices/missing" \
-H "Authorization: Bearer ВАШ_КЛЮЧ"
{
"articles": [
{
"article": "SHIRT-RED-M",
"orders": 12,
"firstOrderAt": "2026-07-01T00:00:00.000Z",
"lastOrderAt": "2026-08-10T00:00:00.000Z",
"costArticle": null
}
],
"total": 1,
"windowDays": 90
}firstOrderAt — дата самой ранней продажи, которая осталась без цены. Именно её (самую раннюю по всей пачке) и стоит поставить в validFrom, когда вы дозаливаете недостающие цены: иначе цена «с сегодня» эти продажи не закроет и товар из списка не исчезнет.
Список считается за последние 90 дней — столько же, сколько мы храним подробности заказов. Пустой ответ означает «за 90 дней всё заполнено».
costArticle: куда заводить цену у товаров Авито
У Авито в поле article стоит номер объявления: своего артикула площадка не отдаёт вовсе. Если вы связали объявления со своими артикулами в кабинете (кнопка «Артикулы Авито» в разделе «Цены»), в ответе придёт ещё и costArticle — тот самый ваш артикул.
Цену заводите на costArticle, когда он не пуст, и на article, когда там null. Иначе у товара окажется две закупочные цены: одна из вашего прайса, другая заведённая скриптом на номер объявления, — и правка прайса на вторую влиять перестанет. У трёх других площадок поле всегда null: артикул продавца там приходит сам.
Выгрузка цен
GET /api/v1/prices отдаёт то, что у нас записано, — например, чтобы сверить с прайсом в своей системе.
curl "https://sellervpluse.ru/api/v1/prices?limit=500&page=1" \
-H "Authorization: Bearer ВАШ_КЛЮЧ"
{
"prices": [
{
"article": "SHIRT-RED-M",
"price": "450.00",
"validFrom": "2026-08-01T00:00:00.000Z",
"validUntil": null
}
],
"total": 1, "page": 1, "pageCount": 1, "limit": 500
}| Параметр | Что делает |
|---|---|
article | Поиск по части артикула. |
history=1 | Добавить прошлые цены. По умолчанию отдаются только действующие (validUntil: null). |
limit, page | Страница: по умолчанию 500 строк, максимум 1000. Сколько всего страниц — в поле pageCount. Вглубь листание идёт до миллиона строк: номер страницы за этой границей отдаёт последнюю доступную, а не ошибку. |
Ошибки и ограничения
У ошибки всегда есть HTTP-код, текст в поле error и машинный код в поле code. Ветвиться в своём скрипте нужно по code: текст мы можем переформулировать.
| Код | Что случилось | Что делать |
|---|---|---|
| 401 | Ключ не передан, недействителен или отозван. | Проверьте заголовок; при необходимости выпустите новый ключ. |
| 402 | Демо-доступ закончился, подписки нет — либо доступ бесплатный. | Оплатите подписку: в бесплатный доступ API не входит. |
| 400 | Тело запроса не прошло проверку. | Подробности — в поле details. |
| 413 | Тело запроса больше 10 МБ. В поле code — BODY_TOO_LARGE. | Разбейте загрузку на части — например, по 10 000 цен, — и присылайте их по очереди с одной и той же датой validFrom. |
| 408 | Запрос к данным не уложился в отведённое время и был прерван. В поле code — DB_TIMEOUT. | Запросите период короче или один магазин за раз: потолок стоит на один запрос, а не на их число. |
| 429 | Слишком много запросов. В поле code — RATE_LIMIT, если исчерпан лимит этого ключа, и RATE_LIMIT_ACCOUNT, если общий лимит аккаунта. | Подождите столько секунд, сколько указано в заголовке Retry-After, и повторите. При RATE_LIMIT_ACCOUNT смотрите и на расписание остальных своих интеграций: квоту израсходовали они. |
| 500 | Ошибка на нашей стороне. | При загрузке цен это означает, что не записалось ничего, — просто повторите запрос. |
Сколько запросов можно слать
- Чтение (
ping, выгрузка цен, список без себестоимости) — 120 запросов в минуту на ключ, 240 в минуту на аккаунт. - Загрузка цен — 60 запросов в час на ключ, 120 в час на аккаунт.
Счётчиков два, и они работают вместе: первый — на каждый ключ отдельно, второй — общий потолок на все ключи аккаунта. Ключей можно выпустить до пяти, но суммарная скорость от их числа не растёт: две интеграции, работающие одновременно на полной скорости, в общий лимит укладываются, дальше они делят его между собой.
Регулярной заливке прайса — хоть раз в час — этого хватает с запасом: весь прайс уезжает одним запросом, разбивать его по товарам не нужно и вредно.
Как это обычно настраивают
- 1
Первая заливка — задним числом
Спросите/api/v1/prices/missing, возьмите самую раннююfirstOrderAtи загрузите весь прайс с этой датой вvalidFrom. Так закроются уже накопленные продажи. - 2
Дальше — по расписанию
Раз в сутки (или как часто меняются закупки) шлите весь прайс безvalidFrom. Записываться будет только изменившееся: в ответе это видно поcreatedиupdated. - 3
Проверяйте, что пробелов не осталось
Тем же/api/v1/prices/missing: пустой список означает, что прибыль считается по всем продажам.
Если что-то не сходится — загляните в раздел «Цены»: там видно то же самое глазами. А как история цен влияет на прибыль, разобрано в статье «Себестоимость и история цен».
Читайте также
- Раздел «Дашборд»: общая картина бизнеса
- Рука на пульсе: заказы по дням и ожидаемая прибыль
- План-факт: план на месяц и прогноз закрытия
- Раздел «Товары по площадкам»: где выгоднее продавать этот товар
- Раздел «Остатки»: склад и замороженные деньги
- Раздел «Безубыточность»: сколько нужно продать, чтобы выйти в ноль
- Раздел «Деньги»: движение денег и остаток на счёте
- Раздел «Расходы»: затраты мимо маркетплейса
- Раздел «Цены»: закупочная стоимость товаров
- Группы товаров: прибыль по своей линейке, поставщику или коллекции
- Раздел «Магазины»: подключение и синхронизация
- Раздел «Уведомления»: сообщения сервиса
- Раздел «Профиль»: налоговый режим и данные аккаунта
Посмотрите на своих цифрах
Прикиньте прибыль по своему товару прямо на калькуляторе — без регистрации и карты.