API склада MarketApp
API нужен, если у вас своя WMS, 1С или МойСклад и вы не хотите вести учёт дважды. Ваша система сама передаёт нам остатки, приёмки и статусы заказов FBS, а мы сообщаем ей о новых сделках и заказах. Клиенты-селлеры видят товар в своём кабинете сразу, без Excel и переписки.
API работает и для селлера, который ведёт «Свой склад» в своей системе.
Как подключить
- Войдите в кабинет владельцем компании и откройте «Склад (WMS)» → «API и вебхуки».
- Создайте ключ. Он показывается один раз — сохраните его в настройках вашей системы.
- Передавайте ключ в каждом запросе в заголовке Authorization.
GET https://market-app.ru/api/v1/me
Authorization: Bearer mk_ваш_ключКлюч открывает только склад компании: остатки, приёмки и заказы FBS. Кабинет, деньги и сделки ключом не открыть. Потеряли ключ — отзовите его в кабинете и создайте новый. Ключей у компании может быть до 5.
Места хранения
Каждый запрос к складу указывает место хранения — параметр place. У фулфилмента место хранения — это клиент-селлер, у селлера — фулфилмент или свой склад. Список мест отдаёт запрос places.
GET /api/v1/places
{ "places": [ { "id": "3f0c…", "name": "ИП Смирнов А.", "own": false } ] }Права те же, что в кабинете. Остатки и заказы FBS правит тот, кто ведёт склад: фулфилмент — у своих клиентов, селлер — на своём складе. Чужое место отвечает 404.
Остатки
Получить остатки места хранения:
GET /api/v1/stocks?place=3f0c…
{ "items": [ { "id": "…", "sku": "KR-50", "name": "Крем 50 мл", "qty": 40, "defectQty": 2, "updatedAt": "2026-10-27T12:00:00.000Z" } ] }Передать остатки из вашей системы. Значения по артикулам ставятся как есть, поэтому повтор запроса безопасен. Разница с прежним остатком записывается движением «Из учётной системы (API)». Артикулы, которых нет в запросе, не меняются. В одном запросе — до 2000 строк.
PUT /api/v1/stocks
Content-Type: application/json
{
"place": "3f0c…",
"items": [
{ "sku": "KR-50", "name": "Крем 50 мл", "qty": 38, "defectQty": 2 },
{ "sku": "MS-10", "name": "Маска", "qty": 120 }
]
}
{ "rows": 2, "changed": 1 }Приёмки по сделкам
Когда селлер принял итог приёмки по сделке, товар нужно разнести по артикулам. Если в партии один артикул, мы делаем это сами. Остальные приёмки ждут разнесения.
GET /api/v1/receipts?place=3f0c…
{ "receipts": [ { "dealId": "D-1042", "product": "Косметика", "qty": 200, "items": [ { "sku": "KR-50", "name": "Крем 50 мл", "qty": 150 } ] } ] }Разнести приёмку. Сумма строк должна совпасть с принятым количеством.
POST /api/v1/receipts/D-1042
{ "place": "3f0c…", "lines": [ { "sku": "KR-50", "name": "Крем 50 мл", "qty": 150 }, { "sku": "MS-10", "name": "Маска", "qty": 50 } ] }Заказы FBS
Заказы приходят из кабинетов селлеров на маркетплейсах сами. Ваша система забирает их и возвращает статус сборки.
GET /api/v1/fbs-orders?place=3f0c…&period=all&updatedSince=2026-10-27T09:00:00ZПараметр period принимает today, week или all. Параметр updatedSince отдаёт только заказы, изменённые после этого времени. За раз — до 500 заказов.
Сменить статус заказа:
POST /api/v1/fbs-orders/{id}/status
{ "status": "packed" }Статусы: new — поступил, assembling — собирается, packed — упакован, shipped — отгружен, problem — проблема (нужно поле problem с причиной), cancelled — отменён. Отгруженный и отменённый заказ больше не меняется.
Добавить заказ вручную, если он пришёл не из кабинета маркетплейса:
POST /api/v1/fbs-orders
{ "place": "3f0c…", "marketplace": "wb", "externalId": "4512378", "product": "Крем 50 мл", "qty": 1, "shipBy": "2026-10-28T10:00:00Z" }Ошибки и лимиты
Ошибка приходит с HTTP-кодом и машинным кодом в теле.
{ "code": "api.key_invalid" }| Код | Когда |
|---|---|
| 400 validation.failed | Поля запроса заполнены неверно, в details — какие |
| 401 api.key_required | Нет заголовка Authorization |
| 401 api.key_invalid | Ключ неверный или отозван |
| 403 partner.fulfillment_only | Склад ведёт другая сторона |
| 404 partner.not_found | Чужое место хранения |
| 409 partner.fbs_closed | Заказ уже отгружен или отменён |
| 429 api.rate_limited | Больше 600 запросов в минуту с одного ключа |
Вебхуки
Вебхук — адрес вашей системы, на который мы отправляем события. Его добавляют в кабинете: «Склад (WMS)» → «API и вебхуки». Адрес должен быть на https и доступен из интернета.
| Событие | Когда приходит |
|---|---|
| deal.created | Селлер выбрал вас, создана сделка: что и сколько к вам едет |
| deal.updated | Сделка перешла в следующий статус |
| stock.changed | Изменились остатки: приёмка, отгрузка, правка, загрузка |
| fbs_order.created | Новый заказ FBS |
| fbs_order.updated | Статус заказа FBS изменился |
Запрос — POST с телом JSON:
{
"id": "1842",
"event": "stock.changed",
"createdAt": "2026-10-27T12:00:00.000Z",
"data": {
"fulfillmentId": "…",
"sellerId": "…",
"items": [ { "sku": "KR-50", "name": "Крем 50 мл", "qty": 38, "defectQty": 2, "change": -2, "defectChange": 0, "reason": "api", "dealId": null } ]
}
}Поле id — номер события. Если событие пришло дважды, обработайте его один раз. В stock.changed поле reason показывает источник изменения. Значение api — это ваша собственная выгрузка, такое событие можно пропустить.
Подпись запроса
Каждый запрос подписан секретом вебхука. Секрет показан при создании, его можно посмотреть или сменить в кабинете. Заголовки запроса:
X-MarketApp-Event: stock.changed
X-MarketApp-Delivery: 1842
X-MarketApp-Timestamp: 1793102400
X-MarketApp-Signature: sha256=…Подпись — HMAC-SHA256 от строки «timestamp.тело запроса» с секретом вебхука, в шестнадцатеричном виде. Проверяйте подпись на тело в том виде, в каком оно пришло. Запросы старше 5 минут лучше отклонять.
// Node.js
const crypto = require('node:crypto');
function verify(secret, timestamp, rawBody, header) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
return header.length === expected.length && crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}# Python
import hmac, hashlib
def verify(secret: str, timestamp: str, raw_body: bytes, header: str) -> bool:
expected = 'sha256=' + hmac.new(secret.encode(), f'{timestamp}.'.encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)Повторы
Доставкой считается ответ 2xx за 10 секунд. Редиректы мы не выполняем. Если ваша система не ответила, повторим через 1 минуту, 5 минут, 30 минут, 2 часа, 6 часов и сутки. После этого событие помечается «Не доставлено», и его можно отправить заново из журнала в кабинете. Кнопка «Проверить» в кабинете сразу отправляет событие ping.