Подключение по схеме FBS

Особенности работы с заказами, отгрузками и складами витрины.

FBS (Fulfillment by Seller) – схема, при которой продавец собирает клиентские заказы на своем складе и передаёт их на склады маркетплейса для дальнейшей доставки. Маркетплейс предоставляет список своих складов (фулфилмент-центров), доступных для приёмки товаров.

Введение

Участники

МерчантПродавец — хранит товары на своём складе, собирает заказы, упаковывает их в грузоместа и передаёт на склад витрины (FBS).
APIFBS Seller API — REST-интерфейс (POST JSON).
ВитринаБэкенд маркетплейса — назначает склад витрины для сдачи, обрабатывает статусы отгрузок и заказов, управляет логикой приёмки.

Константы примеров

Склад мерчантаmerchant_location_id: "wh-msk-01"
Склад витриныmarket_location_id: "koledino" (Коледино)
Отгрузкаshipment_id: SHP-FBS-2026-101
ЗаказыORD-FBS-2026-001, ORD-FBS-2026-002
Дата отгрузки2026-07-15

В FBS заказы собираются на складе мерчанта и передаются отгрузками на склад витрины. Отгрузка всегда едет целиком в одной машине, не разделяется на несколько транспортных средств. В составе отгрузки — грузоместа (короба или паллеты), в каждом грузоместе — один или несколько заказов. Заказы без грузомест не отгружаются. Важно: один заказ всегда соответствует одному товару; несколько товаров в одном заказе не допускаются.

Сценарий 0: Подготовка инфраструктуры FBS

До поступления заказов мерчант настраивает свой склад, подключает его к складу витрины, загружает остатки и цены.

Пошаговое описание

  1. Создание склада мерчанта. POST /v1/merchant/location/create — локация типа WAREHOUSE. В ответе — location_id. Статус отслеживается через merchant/location/list.
  2. Получение списка складов витрины. POST /v1/market/location/list — выбираем доступный фулфилмент-центр (например, koledino).
  3. Привязка склада мерчанта к складу витрины. При создании склада мерчанта или обновлении через merchant/location/update передаётся массив market_location_id — указываем, к каким складам витрины будет подключаться склад мерчанта.
  4. Загрузка остатков. POST /v1/product/stock/update — актуальное количество товаров на складе мерчанта. Текущие остатки — POST /v1/product/stock/info.
  5. Загрузка цен. POST /v1/product/price/update — цены товаров. Текущие цены — POST /v1/product/price/info.

После привязки склада мерчанта к складу витрины на витрине появляется возможность оформлять заказы FBS с указанием этого склада мерчанта. Склад можно архивировать через POST /v1/merchant/location/archive.

JSON-примеры

Шаг 1 — POST /v1/merchant/location/create

{
  "locations": [{
    "merchant_location_id": "wh-msk-01",
    "location_types": "WAREHOUSE",
    "name": "Склад мерчанта Москва",
    "address_tail": "125009, г. Москва, ул. Тверская, д. 1",
    "latitude": 55.7558,
    "longitude": 37.6173,
    "working_schedule": [
      { "day": "MONDAY", "schedule": { "time_start": "09:00", "time_end": "18:00" } }
    ],
    "market_location_id": ["koledino"]
  }]
}
{
  "locations": [
    {
      "location_id": "loc-123",
      "merchant_location_id": "wh-msk-01",
      "name": "Склад мерчанта Москва",
      "status": "PENDING"
    }
  ]
}

Шаг 2 — POST /v1/market/location/list

{
  "filter": { "is_active": true },
  "cursor": "",
  "limit": 100
}
{
  "locations": [{
    "market_location_id": "koledino",
    "name": "Коледино",
    "city": "Москва",
    "is_active": true,
    "shipment_limits": { "accepts_standard": true }
  }]
}

Шаг 4 — POST /v1/product/stock/update

{
  "items": [
    { "offer_id": "PHONE-001", "product_id": "PRD-PHONE-01", "location_id": "wh-msk-01", "count": 50 }
  ]
}
{
  "failed": []
}

Шаг 5 — POST /v1/product/price/update

{
  "items": [
    { "offer_id": "PHONE-001", "product_id": "PRD-PHONE-01", "price": 1999900, "old_price": 2499900, "vat": "VAT_22" }
  ],
  "currency": "RUB"
}
{
  "failed": []
}

Сценарий 1: Полный happy path (сборка и отгрузка на склад витрины)

Мерчант получает заказы ORD-FBS-2026-001 и ORD-FBS-2026-002 в статусе NEW на складе мерчанта wh-msk-01. Склад витрины для сдачи — koledino, дата отгрузки 2026-07-15. Мерчант подтверждает, собирает, упаковывает, печатает этикетки, оформляет пропуск и передаёт отгрузку.

Диаграмма последовательности

Пошаговое описание (1–12)

  1. Опрос обновлений заказов. POST /v1/order/fbs/status/list — получаем новые заказы в статусе NEW.
  2. Карточка заказа. POST /v1/order/fbs/list — детали: состав, адрес доставки, requirements (требования к маркировке), market_location_id (склад витрины для сдачи).
  3. Подтверждение заказа. POST /v1/order/fbs/status/update → CONFIRMED, changed_by: "MERCHANT".
  4. Передача экземпляров. POST /v1/order/fbs/exemplar/set — для каждого заказа передаём массив exemplars с маркировкой (IMEI, «Честный знак», ГТД и т.д.) согласно requirements.
  5. Готовность к отгрузке. POST /v1/order/fbs/status/update → READY_TO_SHIP. Заказ собран и упакован (на уровне товаров).
  6. Создание отгрузки. POST /v1/shipment/create — указываем market_location_id (куда везём), shipment_date и packages (список грузомест с merchant_order_ids). Метод не учитывает внутрискладские процессы; он используется после фактической сборки заказов и формирования грузомест. Передаётся весь набор заказов, уже рассортированных по грузоместам. Можно создать отгрузку без грузомест, а затем добавить их через package/add.
  7. Этикетки заказов. POST /v1/order/fbs/labels/get — файл с этикетками для каждого заказа (стикеры на товары). Формат может быть любым (PDF, ZPL, PNG и т.д.) в зависимости от настроек. Печатаем и наклеиваем на товары.
  8. Этикетки грузомест. POST /v1/label/fbs/packages/get — этикетки для указанных package_id. Наклеиваем на короба/паллеты.
  9. Пропуск. POST /v1/shipment/pass/update — передаём данные водителя и ТС для въезда на склад витрины. Можно указать несколько shipment_ids для одной машины.
  10. Статус отгрузки READY. POST /v1/shipment/fbs/status/updateREADY — отгрузка готова к отправке.
  11. Статус IN_TRANSIT. POST /v1/shipment/fbs/status/updateIN_TRANSIT — машина выехала на склад витрины.
  12. Мониторинг приёмки. POST /v1/shipment/get или shipment/list — отслеживаем статусы ACCEPTED_AT_GATE (принята на воротах), PARTIALLY_ACCEPTED (частично) и ACCEPTED (полностью). Витрина автоматически меняет статусы по мере приёмки.

Отгрузка может быть создана и без грузомест (пустая), затем грузоместа добавляются через package/add. Статус отгрузки CANCELLED устанавливается только через shipment/cancel, не через shipment/fbs/status/update. Отмена доступна только из статусов DRAFT или READY (до отправки в путь). Отмена не расформировывает грузоместа и не меняет их статус.

Порядок маркировки и сборки на складе

┌─────────────────────────────────────────────────────────────┐
│  1. Заказы подтверждены (CONFIRMED)                         │
│  2. API: exemplar/set — передать IMEI/маркировку на каждый │
│  3. API: status/update → READY_TO_SHIP                      │
│  4. API: order/fbs/labels/get → стикеры на товары          │
│  5. НАКЛЕИТЬ стикер на каждый товар (или на его упаковку)   │
│  6. Рассортировать товары по грузоместам (короба/паллеты)   │
│  7. API: shipment/create или package/add — создать ГМ       │
│  8. API: label/fbs/packages/get → этикетки на ГМ           │
│  9. НАКЛЕИТЬ этикетку на каждое грузоместо                  │
│ 10. (опц.) API: label/fbs/shipment/get → документ отгрузки  │
│ 11. API: pass/update — пропуск на водителя                 │
│ 12. API: status/update → READY → IN_TRANSIT                │
│ 13. Ожидать приёмки на складе витрины                      │
└─────────────────────────────────────────────────────────────┘

Порядок действий может варьироваться в зависимости от типа товара (крупный/мелкий) и внутренних процессов склада. Главное — этикетка заказа должна быть на товаре (или его упаковке) до того, как он попадёт в грузоместо.

JSON-примеры

Шаг 1 — POST /v1/order/fbs/status/list

{
  "filter": {
    "status": ["NEW"],
    "updated_since": "2026-07-14T00:00:00+03:00"
  },
  "cursor": "",
  "limit": 100
}
{
  "order_updates": [
    {
      "merchant_order_id": "ORD-FBS-2026-001",
      "client_order_id": "CLT-1001",
      "status": "NEW",
      "updated_at": "2026-07-14T10:00:00+03:00"
    }
  ],
  "next_cursor": ""
}

Шаг 2 — POST /v1/order/fbs/list

{
  "filter": {
    "merchant_order_id": ["ORD-FBS-2026-001"]
  },
  "cursor": "",
  "limit": 100
}
{
  "orders": [{
    "merchant_order_id": "ORD-FBS-2026-001",
    "client_order_id": "CLT-1001",
    "merchant_location_id": "wh-msk-01",
    "market_location_id": "koledino",
    "shipment_date": "2026-07-15",
    "status": "NEW",
    "delivery": { "delivery_type": "COURIER", "address_tail": "..." },
    "product_id": "PRD-PHONE-01",
    "offer_id": "PHONE-001",
    "requirements": { "requires_imei": true }
  }]
}

Шаг 3 — POST /v1/order/fbs/status/update (CONFIRMED)

{
  "merchant_order_id": "ORD-FBS-2026-001",
  "status": "CONFIRMED",
  "changed_at": "2026-07-14T10:05:00+03:00",
  "changed_by": "MERCHANT",
  "comment": "Принят в работу"
}
{}

Шаг 4 — POST /v1/order/fbs/exemplar/set

{
  "merchant_order_id": "ORD-FBS-2026-001",
  "product_id": "PRD-PHONE-01",
  "offer_id": "PHONE-001",
  "exemplars": [{
    "exemplar_id": 1,
    "marks": [{ "mark": "35693803564341", "mark_type": "imei" }],
    "weight": 0.22
  }]
}
{}

Шаг 5 — POST /v1/order/fbs/status/update (READY_TO_SHIP)

{
  "merchant_order_id": "ORD-FBS-2026-001",
  "status": "READY_TO_SHIP",
  "changed_at": "2026-07-14T11:00:00+03:00",
  "changed_by": "MERCHANT"
}
{}

Шаг 6 — POST /v1/shipment/create

{
  "market_location_id": "koledino",
  "shipment_date": "2026-07-15",
  "packages": [
    {
      "package_number": 1,
      "type": "BOX",
      "merchant_order_ids": ["ORD-FBS-2026-001", "ORD-FBS-2026-002"]
    },
    {
      "package_number": 2,
      "type": "PALLET",
      "merchant_order_ids": ["ORD-FBS-2026-003"]
    }
  ],
  "idempotency_key": "create-shp-2026-07-15-001"
}
{
  "shipment_id": "SHP-FBS-2026-101",
  "packages": [
    { "package_id": "PKG-001", "package_number": 1, "type": "BOX", "merchant_order_ids": ["ORD-FBS-2026-001", "ORD-FBS-2026-002"] },
    { "package_id": "PKG-002", "package_number": 2, "type": "PALLET", "merchant_order_ids": ["ORD-FBS-2026-003"] }
  ]
}

Шаг 7 — POST /v1/order/fbs/labels/get

{
  "merchant_order_id": ["ORD-FBS-2026-001", "ORD-FBS-2026-002"],
  "format": "PDF"
}
{
  "labels": [
    {
      "merchant_order_id": "ORD-FBS-2026-001",
      "client_order_id": "CLT-1001",
      "file_name": "label_ORD-FBS-2026-001.pdf",
      "content_base64": "JVBERi0xLjQK...",
      "content_type": "application/pdf"
    }
  ],
  "failed": []
}

Шаг 8 — POST /v1/label/fbs/packages/get

{
  "shipment_id": "SHP-FBS-2026-101",
  "package_ids": ["PKG-001", "PKG-002"],
  "format": "PDF",
  "size": "SIZE_100x150"
}
{
  "labels": [
    {
      "package_id": "PKG-001",
      "label": { "format": "PDF", "content_base64": "..." }
    }
  ],
  "failed": []
}

Шаг 9 — POST /v1/shipment/pass/update

{
  "shipment_ids": ["SHP-FBS-2026-101"],
  "vehicle": {
    "driver_name": "Иванов Иван Иванович",
    "driver_phone": "+79001234567",
    "vehicle_model": "ГАЗель NEXT",
    "vehicle_plate": "А123ВС777"
  },
  "idempotency_key": "pass-2026-07-15-001"
}
{}

Шаг 10–11 — POST /v1/shipment/fbs/status/update (READY → IN_TRANSIT)

{
  "shipment_id": "SHP-FBS-2026-101",
  "status": "READY",
  "changed_at": "2026-07-15T08:00:00+03:00",
  "changed_by": "MERCHANT"
}
{}
{
  "shipment_id": "SHP-FBS-2026-101",
  "status": "IN_TRANSIT",
  "changed_at": "2026-07-15T09:00:00+03:00",
  "changed_by": "MERCHANT"
}
{}

Шаг 12 — POST /v1/shipment/get (мониторинг)

{
  "shipment_id": "SHP-FBS-2026-101"
}
{
  "shipment_id": "SHP-FBS-2026-101",
  "market_location_id": "koledino",
  "status": "ACCEPTED",
  "accepted_qty_packages": 2,
  "planned_qty_packages": 2
}

Сценарий 2: Отмена отгрузки

Отгрузку можно отменить только в статусах DRAFT или READY через POST /v1/shipment/cancel. После перехода в IN_TRANSIT и далее отмена недоступна.

  1. Мерчант создал отгрузку (DRAFT) или перевёл в READY.
  2. По каким-то причинам отгрузка не состоится.
  3. POST /v1/shipment/cancel с обязательными полями: shipment_id, reason, cancelled_by, idempotency_key.
  4. Статус отгрузки становится CANCELLED.

Отмена отгрузки не отменяет автоматически заказы внутри неё. Заказы остаются в статусе READY_TO_SHIP или CONFIRMED и могут быть включены в другую отгрузку. Грузоместа при отмене не расформировываются и не меняют свой статус — они просто остаются в отменённой отгрузке.

JSON — POST /v1/shipment/cancel

{
  "shipment_id": "SHP-FBS-2026-101",
  "reason": "Невозможно отправить в указанную дату",
  "cancelled_by": "MERCHANT",
  "idempotency_key": "cancel-shp-101-001"
}
{}

Сценарий 3: Отмена заказа продавцом

Мерчант может отменить заказ вручную через POST /v1/order/fbs/cancel до тех пор, пока заказ не перешёл в статус SHIPPED (отгружен).

  1. Заказ в статусе NEW, CONFIRMED или READY_TO_SHIP.
  2. Мерчант отправляет запрос с merchant_order_id, reason_code, reason_comment, changed_at.
  3. Статус заказа меняется на CANCELLED.

JSON — POST /v1/order/fbs/cancel

{
  "merchant_order_id": "ORD-FBS-2026-001",
  "reason_code": "OUT_OF_STOCK",
  "reason_comment": "Товар закончился на складе",
  "changed_at": "2026-07-14T12:00:00+03:00"
}
{ "success": true }

Статусы и ключевые правила

Статусы заказа FBS

NEWНовый заказ, ожидает подтверждения
CONFIRMEDПодтверждён продавцом, можно собирать
READY_TO_SHIPСобран и упакован, готов к включению в отгрузку
SHIPPEDОтгружен (включён в отгрузку, которая перешла в статус READY или выше)
ACCEPTED_AT_WAREHOUSEПринят на складе витрины
DELIVEREDДоставлен покупателю
CANCELLEDОтменён (через order/fbs/cancel)

Статусы отгрузки FBS

DRAFTЧерновик, можно изменять состав, добавлять/удалять грузоместа, отменить
READYГотова к отправке, можно изменить пропуск, перевести в IN_TRANSIT или отменить
IN_TRANSITВ пути на склад витрины, отмена недоступна
ACCEPTED_AT_GATEПринята на воротах склада (автоматически от витрины)
PARTIALLY_ACCEPTEDЧастично принята (принято меньше грузомест, чем заявлено)
ACCEPTEDПолностью принята
CANCELLEDОтменена (только через shipment/cancel из DRAFT или READY)

State machine отгрузки FBS

ИзВКто инициируетМетод
DRAFTMERCHANTshipment/create
DRAFTDRAFT (обновление)MERCHANTshipment/update, package/add, package/remove, pass/update
DRAFTREADYMERCHANTshipment/fbs/status/update
DRAFTCANCELLEDMERCHANTshipment/cancel
READYIN_TRANSITMERCHANTshipment/fbs/status/update
READYCANCELLEDMERCHANTshipment/cancel
IN_TRANSITACCEPTED_AT_GATEВитрина(автоматически)
ACCEPTED_AT_GATEPARTIALLY_ACCEPTEDВитрина(автоматически)
ACCEPTED_AT_GATEACCEPTEDВитрина(автоматически)
PARTIALLY_ACCEPTEDACCEPTEDВитрина(при дозачёте)
CANCELLEDТерминальный статус
ACCEPTEDТерминальный статус

Статус CANCELLED не может быть установлен через shipment/fbs/status/update, только через shipment/cancel.

Сценарии приёмки на складе витрины

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

1. Отгрузка прибыла на ворота

СущностьСтатус
ОтгрузкаACCEPTED_AT_GATE
ГрузоместаPLANNED (ожидают осмотра)
ЗаказыSHIPPED (уже отгружены)

2. Часть грузомест принята, часть отклонена

СущностьСтатус
ОтгрузкаPARTIALLY_ACCEPTED (если принято хотя бы одно грузоместо)
Принятые грузоместаACCEPTED
Отклонённые грузоместаREJECTED
Ненайденные грузоместаPLANNED
Заказы в принятых грузоместахSHIPPED (позже станут ACCEPTED_AT_WAREHOUSE после вскрытия грузомест)
Заказы в отклонённых/ненайденных грузоместахSHIPPED (остаются в этом статусе, возвращаются мерчанту)

3. Ни одного грузоместа не принято

СущностьСтатус
ОтгрузкаIN_TRANSIT (остаётся, но фактически возвращается)
ГрузоместаREJECTED или PLANNED
ЗаказыSHIPPED

4. После вскрытия грузомест (внутренняя приёмка)

СущностьСтатус
Товары, принятые витринойACCEPTED_AT_WAREHOUSE
Товары, не принятые или не найденныеSHIPPED
Отгрузка (если не все заказы приняты)PARTIALLY_ACCEPTED
Отгрузка (если все заказы приняты)ACCEPTED

5. Особые случаи

  • Заказы, которые сразу возвращаются (не приняты на воротах): отгрузка остаётся PARTIALLY_ACCEPTED, ACCEPTED_AT_GATE или IN_TRANSIT, грузоместа — REJECTED, заказы — SHIPPED.
  • Заказы, возвращаемые со склада после внутренней приёмки: отгрузка — PARTIALLY_ACCEPTED, грузоместа — ACCEPTED, заказы — SHIPPED.

Витрина автоматически обновляет статусы; мерчант отслеживает их через shipment/get и order/fbs/list.

Ключевые правила интеграции FBS

СкладыДва типа: merchant/location (склад мерчанта) и market/location (склад витрины). Привязка через market_location_id при создании/обновлении склада мерчанта. Архивация — merchant/location/archive.
Остатки и ценыЗапись: product/stock/update, product/price/update. Чтение: product/stock/info, product/price/info.
ЗаказыОдин заказ = один товар. Заказы собираются в грузоместа (короба/паллеты), в одном грузоместе может быть несколько заказов.
ОтгрузкаСоздаётся в DRAFT, содержит грузоместа (packages) с типом BOX/PALLET. Состав изменяется только в DRAFT (shipment/update, package/add, package/remove). Отгрузка всегда едет целиком в одной машине, не разделяется.
ГрузоместаВ отгрузку обязательно должны входить грузоместа, в каждом грузоместе — один или несколько заказов. Заказы без грузомест не отгружаются.
Валидация витринойПри создании и обновлении отгрузки витрина проверяет, что заказы не привязаны более чем к одному грузоместу и одной отгрузке, а грузоместа не привязаны более чем к одной отгрузке.
ЭтикеткиТри вида: на заказы (order/fbs/labels/get), на грузоместа (label/fbs/packages/get), на всю отгрузку (label/fbs/shipment/get). Формат может быть любым (PDF, ZPL, PNG и т.д.).
ПропускОбновляется через shipment/pass/update для одной или нескольких отгрузок, статус отгрузки должен быть DRAFT, READY или IN_TRANSIT.
Статус заказаМерчант может менять через order/fbs/status/update на CONFIRMED, READY_TO_SHIP, SHIPPED, CANCELLED (но CANCELLED лучше через отдельный метод order/fbs/cancel).
Отмена заказаorder/fbs/cancel — обязательны reason_code и reason_comment.
Отмена отгрузкиТолько из DRAFT или READY, не расформировывает грузоместа.
ИдемпотентностьМетоды shipment/create, shipment/cancel, pass/update поддерживают idempotency_key.

Полный справочник методов FBS

Все методы FBS с детальными параметрами и ответами доступны в разделе API Reference FBS.