Вебхуки: уведомления о статусах заявок
Вебхуки — это уведомления, которые МПФИТ сам отправляет в вашу систему, когда с заявкой что-то происходит. Не нужно опрашивать наш API по кругу и ждать, пока изменения обнаружатся: как только заявка создана или у неё сменился статус, мы делаем запрос на ваш адрес.
Вебхуки пригодятся, если вы уже создаёте заявки в МПФИТ из своей учётной системы — МойСклад, Битрикс24, 1С или собственной разработки — и хотите видеть в ней актуальные статусы.
Настройка вебхуков — работа для разработчика: нужен адрес, который принимает запросы, и код, который их обрабатывает.
О чём приходят уведомления
Заголовок раздела «О чём приходят уведомления»| Событие | Когда приходит |
|---|---|
| `arrival.created` | создана заявка на приёмку |
| `arrival.status_changed` | у заявки на приёмку сменился статус |
| `shipment.created` | создана заявка на отгрузку или заказ |
| `shipment.status_changed` | у заявки на отгрузку или заказа сменился статус |
| `ping` | проверочное сообщение, отправляем по запросу |
Вы подписываетесь на все события или только на нужные.
Заявки на приёмку и отгрузку по ФБО приходят сразу, в момент события.
Заказы ФБС приходят пачкой, раз в полчаса. Их слишком много для мгновенной отправки: за это время статус заказа успевает смениться несколько раз, поэтому вы получите одно уведомление с последним статусом на момент отправки. Промежуточные состояния в него не попадут.
Как подключить
Заголовок раздела «Как подключить»- Подготовьте на своей стороне адрес, который будет принимать запросы. Требования к нему — в разделе ниже.
- Напишите в поддержку МПФИТ: укажите адрес и события, на которые подписываетесь.
- В ответ вы получите секрет — строку, которой подписываются все сообщения. Храните её как пароль: не публикуйте в репозитории и не передавайте в переписке третьим лицам.
- Попросите отправить проверочное сообщение
pingи убедитесь, что оно дошло и ваш обработчик ответил успешно.
Если нужно сузить поток — например получать смену статуса приёмки только на «завершена» — скажите об этом при подключении: подписку можно ограничить конкретными статусами.
Как выглядит сообщение
Заголовок раздела «Как выглядит сообщение»Мы отправляем POST с телом в формате JSON:
{ "id": "evt_0198c202-c4ca-7791-9216-4b727c947175", "type": "shipment.status_changed", "version": 1, "created_at": "2026-08-03T12:34:56+03:00", "data": { "object_type": "shipment", "event": "status_changed", "object_id": 845213, "number": "WMS-845213", "seller_company_id": 11986, "ff_company_id": 1772, "direction": "external", "marketplace_id": 1, "source": "api", "status": "SHIPPED", "previous_status": "READY_TO_SHIP" }}Общие поля любого сообщения:
| Поле | Значение |
|---|---|
| `id` | уникальный номер события. По нему отсеивайте повторы |
| `type` | тип события из таблицы выше |
| `version` | версия формата |
| `created_at` | момент события |
| `data` | подробности события |
Уведомление о приёмке устроено так же:
{ "id": "evt_0198c202-c4d5-7cc9-9a4c-8dcf4400b74e", "type": "arrival.status_changed", "version": 1, "created_at": "2026-08-03T09:15:02+03:00", "data": { "object_type": "arrival", "event": "status_changed", "object_id": 51204, "seller_company_id": 11986, "ff_company_id": 1772, "source": "api", "status": "COMPLETED", "previous_status": "NEW" }}Поля блока data
Заголовок раздела «Поля блока data»| Поле | Есть у | Значение |
|---|---|---|
| `object_type` | всех | `shipment` — отгрузка или заказ, `arrival` — приёмка |
| `event` | всех | `created` — заявка создана, `status_changed` — сменился статус |
| `object_id` | всех | номер заявки в МПФИТ. По нему запрашивайте подробности через API |
| `seller_company_id` | всех | компания-продавец, которой адресовано событие |
| `ff_company_id` | всех | фулфилмент, который обслуживает заявку |
| `source` | всех | `api` — заявка создана через API, `internal` — создана в интерфейсе МПФИТ или пришла с маркетплейса |
| `status` | всех | текущий статус |
| `previous_status` | всех | статус до изменения. У события создания — `null` |
| `number` | отгрузки | номер заказа |
| `direction` | отгрузки | `fbs` — заказ отгружается по ФБС, `external` — поставка ФБО и другие типы |
| `marketplace_id` | отгрузки | маркетплейс заказа |
В уведомлении намеренно нет позиций, товаров и остатков: состав заявки запрашивайте через наш API по object_id — там он всегда актуален. Ссылка на документацию — mpfit.ru/api.
Одна заявка на приёмку может содержать товары нескольких продавцов. Каждому продавцу уходит своё уведомление, в котором указан только его seller_company_id.
Статусы
Заголовок раздела «Статусы»Статусы отгрузок и заказов:
| Значение | Что означает |
|---|---|
| `NEW` | новый |
| `ALL_PRODUCTS_RESERVED` | товар забронирован |
| `PROCESSING` | комплектация |
| `READY_TO_SHIP` | готов к отгрузке |
| `DELIVERING` | в доставке |
| `COMPLETED` | выполнен |
| `REJECT` | отказ клиента |
| `CANCEL` | отмена поставщиком |
| `SHIPPED` | отгружен |
| `ARCHIVE` | архив |
Статусы приёмки:
| Значение | Что означает |
|---|---|
| `NEW` | заявка создана, товар ещё принимается |
| `COMPLETED` | приёмка завершена |
| `ARCHIVED` | заявка закрыта без приёмки: груз или товар не прибыл, либо заявка отправлена в архив |
Внутренних статусов приёмки больше, но наружу они сведены к этим трём. Переходы, которые не меняют статус из таблицы, мы не отправляем — лишних уведомлений не будет.
Проверка подписи
Заголовок раздела «Проверка подписи»Каждый запрос содержит три заголовка:
X-MPFIT-Event-Id: evt_0198c202-c4ca-7791-9216-4b727c947175X-MPFIT-Event-Type: shipment.status_changedX-MPFIT-Signature: t=1754212496,v1=9f2c1d...t — время отправки, v1 — подпись: HMAC-SHA256 от строки «t.тело запроса» на вашем секрете.
Проверяйте подпись до того, как доверять содержимому:
- возьмите сырое тело запроса, до разбора JSON;
- посчитайте
HMAC-SHA256(секрет, t + "." + тело); - сравните с
v1функцией сравнения в постоянном времени; - отбросьте запрос, если
tстарше 5 минут.
Пример на PHP:
[$t, $v1] = sscanf($_SERVER['HTTP_X_MPFIT_SIGNATURE'], 't=%d,v1=%s');$body = file_get_contents('php://input');$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
if (!hash_equals($expected, $v1) || abs(time() - $t) > 300) { http_response_code(403); exit;}Пример на Python:
import hmac, hashlib, time
raw = request.get_data()parts = dict(p.split("=", 1) for p in request.headers["X-MPFIT-Signature"].split(","))expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, parts["v1"]) or abs(time.time() - int(parts["t"])) > 300: abort(403)Как отвечать
Заголовок раздела «Как отвечать»Ответьте любым кодом 2xx — этого достаточно, тело ответа мы не читаем. На ответ есть 5 секунд, поэтому обработку выносите в свою очередь: приняли, поставили в очередь, ответили.
Что происходит при других ответах:
| Ваш ответ | Что делаем |
|---|---|
| `2xx` | считаем доставленным |
| `429`, `408`, `5xx`, таймаут | повторяем: через 1 минуту, 5 минут, полчаса, 2 часа, 6 часов, 12 часов. Всего 7 попыток |
| остальные `4xx`, редиректы `3xx` | считаем ошибкой настройки и не повторяем |
Если приёмник перестал отвечать, мы на время приостановим отправку на него и продолжим, когда он оживёт. Накопившиеся уведомления при этом не теряются, пока не исчерпаны попытки.
Что учесть при разработке
Заголовок раздела «Что учесть при разработке»Повторы возможны. Если ваш ответ до нас не дошёл, мы отправим уведомление ещё раз. Сохраняйте id события и игнорируйте те, что уже обработаны.
Порядок не гарантирован. После повторных попыток более раннее событие может прийти позже более позднего. Считайте уведомление сигналом «сходи проверь», а действительное состояние заявки берите из API по object_id.
Статусы могут перескакивать. Особенно у ФБС-заказов, где за полчаса заказ проходит несколько состояний. Не стройте логику на том, что вы увидите каждый промежуточный статус.
Незнакомые типы событий не должны ломать обработчик. Мы добавляем события, и приёмник должен спокойно пропускать то, чего пока не понимает.
Требования к адресу
Заголовок раздела «Требования к адресу»- Только
https://и стандартный порт 443. - Адрес должен быть доступен из интернета — на локальные и внутренние адреса сети мы не отправляем.
- Без логина и пароля в самом адресе.
- Без редиректов: отвечайте на указанный адрес сами, а не перенаправляйте запрос.
- Сертификат должен быть действующим.
Частые вопросы
Заголовок раздела «Частые вопросы»Можно ли получать уведомления на несколько адресов? Да, подписок может быть несколько — например рабочая и тестовая.
Придут ли уведомления по заявкам, созданным не через API? Да. Заявки, созданные в интерфейсе МПФИТ или пришедшие с маркетплейса, тоже попадают в поток — отличить их можно по полю source.
Что делать, если уведомления перестали приходить? Проверьте, что ваш адрес отвечает 2xx и укладывается в 5 секунд, а затем напишите в поддержку — мы посмотрим журнал доставки по вашей подписке.
Как сменить адрес или список событий? Напишите в поддержку, подписку изменят.