API склада MarketApp

API нужен, если у вас своя WMS, 1С или МойСклад и вы не хотите вести учёт дважды. Ваша система сама передаёт нам остатки, приёмки и статусы заказов FBS, а мы сообщаем ей о новых сделках и заказах. Клиенты-селлеры видят товар в своём кабинете сразу, без Excel и переписки.

API работает и для селлера, который ведёт «Свой склад» в своей системе.

Как подключить

  1. Войдите в кабинет владельцем компании и откройте «Склад (WMS)» → «API и вебхуки».
  2. Создайте ключ. Он показывается один раз — сохраните его в настройках вашей системы.
  3. Передавайте ключ в каждом запросе в заголовке 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" }

Вебхуки

Вебхук — адрес вашей системы, на который мы отправляем события. Его добавляют в кабинете: «Склад (WMS)» → «API и вебхуки». Адрес должен быть на https и доступен из интернета.

Запрос — 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.