Сверка недостач по приёмке
Зачем
«Я отправил 600, вы приняли 480 — где 120?» — самый частый спор между
селлером и оператором фулфилмента. API отвечает на него числами, а не
перепиской: discrepancy_qty общей суммой и по каждой позиции
отдельно, плюс машиночитаемая причина там, где она известна.
Узнать о расхождении
Подпишитесь на receipt.completed — событие приходит один раз, когда приёмка закрыта, независимо от того, сошлось количество или нет:
{
"id": "evt_7c1b2a",
"type": "receipt.completed",
"occurred_at": "2026-08-12T16:45:00+03:00",
"data": {
"id": "r_2026_0812_04", "number": "ПР-2026-0812-04",
"status": "RECEIVED_WITH_DISCREPANCY", "status_label": "Принята с расхождением",
"expected_qty": 600, "accepted_qty": 480, "discrepancy_qty": 120,
"created_at": "2026-08-12T08:00:00+03:00", "completed_at": "2026-08-12T16:45:00+03:00"
}
}
def handle_receipt_completed(event):
receipt = event["data"]
if receipt["discrepancy_qty"] > 0:
fetch_and_report_discrepancy(receipt["id"])
Без вебхука — переберите приёмки за нужный период и отфильтруйте по статусу:
curl "https://api.perfektpak.ru/v1/receipts?status=RECEIVED_WITH_DISCREPANCY" \
-H "Authorization: Bearer $PP_KEY"
Расхождение по каждой позиции
Общая сумма — в списке; состав по SKU с причиной — в карточке приёмки:
curl https://api.perfektpak.ru/v1/receipts/r_2026_0812_04 \
-H "Authorization: Bearer $PP_KEY"
{
"id": "r_2026_0812_04", "number": "ПР-2026-0812-04",
"status": "RECEIVED_WITH_DISCREPANCY", "status_label": "Принята с расхождением",
"expected_qty": 600, "accepted_qty": 480, "discrepancy_qty": 120,
"created_at": "2026-08-12T08:00:00+03:00", "completed_at": "2026-08-12T16:45:00+03:00",
"items": [
{ "barcode": "4680012340015", "article": "COFFEE-1KG-BRIZ", "name": "Кофе в зёрнах «Утренний Бриз» 1 кг",
"expected_qty": 400, "accepted_qty": 280, "discrepancy_qty": 120, "shortage_reason": "Недовложение поставщика" },
{ "barcode": "4680012340022", "article": "CREAM-HAND-SILK-75", "name": "Крем для рук «Шёлковые ладони» 75 мл",
"expected_qty": 200, "accepted_qty": 200, "discrepancy_qty": 0 }
]
}
shortage_reason — русский текст из курируемого нами списка
(не фиксированный enum: список пополняется), присутствует только у позиций
с расхождением. Ветвитесь в коде по discrepancy_qty > 0, а
не по наличию поля — используйте shortage_reason только для
текста, который увидит человек.
Что делать с расхождением
Расхождение уже отражено в остатке — accepted_qty, а не
expected_qty, попадает в приход, и ровно эта же цифра видна в
GET /v1/stock и в GET /v1/metrics
(receiving.discrepancy_units,
receiving.shortages_by_reason — та же разбивка по причинам,
но агрегированная за период, для дашборда). Дальнейший разбор — по договору
с ПерфектПак — ведётся через менеджера с номером приёмки и позициями из
ответа выше на руках, не через API: v1.1 не вводит отдельной ручки для
претензии по недостаче.
Что дальше
Если расхождение всплыло в заявке, которую вы сами создали через API — см.
статус RECEIVED_WITH_DISCREPANCY в общей цепочке в гайде
«Заявка на приёмку из 1С».