ПерфектПак · API v1.1
openapi.yaml ↗

Заявить привоз товара (v1.1)

POST /receipts
Адрес
POST https://api.perfektpak.ru/v1/receipts

Тот же адрес и в песочнице — режим выбирает ключ: pp_live_… отвечает боевыми данными, pp_test_…данными песочницы.

Описание метода

Ваша система сообщает нам, что везёт: позиции, количество, признак маркировки. Заявка появляется у нас в статусе PENDING_CONFIRMATION и не видна складу, пока наш менеджер не нажмёт «Подтвердить» — после этого она становится обычной приёмкой (EXPECTEDRECEIVINGRECEIVED / RECEIVED_WITH_DISCREPANCY). Ответственность за товар возникает с фактической приёмки, не с заявки.

Правила: 1–500 позиций; honest_mark обязателен у каждой позиции и одинаков у всех (склад принимает задание либо целиком по кодам маркировки, либо целиком по штрихкодам — смешанную заявку отклоняем кодом mixed_marking, разделите на две); cabinet_id обязателен, если у вас больше одного кабинета (см. GET /me).

Идемпотентность: повтор с тем же external_ref, пока заявка в PENDING_CONFIRMATION, возвращает её же с кодом 200 — вторая не создаётся. Каждая заявка пишется в неизменяемый журнал (что, когда, каким ключом) — это доказательная база при расхождениях.

Авторизация

Authorization: Bearer <ключ> Ключ выдаёт менеджер (боевой) или песочница (тестовый).

Тело запроса обязательно

Схема: ReceiptDraft

  • cabinet_id строка
    Кабинет из GET /me. Необязателен, если кабинет один.
  • external_ref строка
    Ваш номер документа. Вернём как есть; повтор с тем же номером, пока заявка ждёт подтверждения, не создаёт вторую.
    до 64 симв.
  • comment строка
    до 500 симв.
  • planned_date строка
    Плановая дата привоза, ГГГГ-ММ-ДД (МСК).
  • items массив обязательно
    1…500 элементов
    поля элемента — ReceiptDraftItem
    • barcode строка обязательно
      Штрихкод товара — по нему склад считает единицы. Один штрихкод — одна позиция.
      до 64 симв.
    • name строка
      Название, как его видит кладовщик. Необязательно, если товар нам уже известен.
    • article строка
    • qty целое число обязательно
      1…100000
    • honest_mark логическое обязательно
      Подлежит маркировке «Честный знак». Обязателен и одинаков у всех позиций одной заявки.

Ответы

201 Заявка создана.

Схема: Receipt

  • id строка обязательно
  • number строка обязательно
    Номер приёмки, как он подписан у нас.
  • status строка ReceiptStatus обязательно
    Статус приёмки — привоза товара селлером на склад ПерфектПак. PENDING_CONFIRMATION — заявлена через API из вашей системы и ждёт подтверждения нашим менеджером (склад её ещё не видит); EXPECTED — заявлена, ещё не началась; RECEIVING — идёт пересчёт прямо сейчас; RECEIVED — завершена, количество сошлось; RECEIVED_WITH_DISCREPANCY — завершена, количество не сошлось (см. discrepancy_qty и items[].shortage_reason).
    Значения: PENDING_CONFIRMATION EXPECTED RECEIVING RECEIVED RECEIVED_WITH_DISCREPANCY
  • status_label строка обязательно
  • expected_qty целое число обязательно
    Сколько единиц всего заявлено по накладной.
  • accepted_qty целое число обязательно
    Сколько единиц всего фактически приняли.
  • discrepancy_qty целое число обязательно
    expected_qty минус accepted_qty, никогда не отрицательное.
    не меньше 0
  • created_at строка обязательно
    Когда приёмку завели. RFC 3339, +03:00 (МСК).
  • completed_at строка или null обязательно
    Когда приёмку закрыли, или null, пока она ещё идёт. RFC 3339, +03:00 (МСК).
  • source строка
    Кто заявил товар: api — ваша система через POST /v1/receipts, file — наш менеджер по вашей выгрузке, manual — наш менеджер вручную. Пусто у приёмок, заведённых до v1.1.
    Значения: api file manual
  • external_ref строка
    Ваш номер документа из POST /v1/receipts, как есть. Только у source: api.
  • comment строка
  • planned_date строка или null
    Плановая дата привоза (полночь МСК) или null.
  • confirmed_at строка или null
    Когда наш менеджер подтвердил заявку из API; null до подтверждения и у приёмок не из API.
  • items массив
    Состав приёмки по SKU. Поле присутствует только в ответе GET /receipts/{id} — в списке GET /receipts его нет.
    поля элемента — ReceiptItem
    • barcode строка обязательно
    • article строка
      Артикул продавца. Поле опущено, если у товара нет артикула.
    • name строка обязательно
    • honest_mark логическое
      Позиция подлежит маркировке «Честный знак» — каждая единица принимается по коду маркировки, а не по штрихкоду товара.
    • expected_qty целое число обязательно
      Сколько единиц этого SKU заявлено по накладной.
    • accepted_qty целое число обязательно
      Сколько единиц этого SKU фактически приняли и посчитали.
    • discrepancy_qty целое число обязательно
      expected_qty минус accepted_qty, никогда не отрицательное.
      не меньше 0
    • shortage_reason строка
      Причина расхождения по этой позиции, по-русски, из курируемого нами списка (не фиксированный enum — список может пополняться; пример ниже не исчерпывающий). Поле опущено, когда расхождения нет.
200 Такая заявка (тот же external_ref) уже ждёт подтверждения — возвращена она.

Схема: Receipt

  • id строка обязательно
  • number строка обязательно
    Номер приёмки, как он подписан у нас.
  • status строка ReceiptStatus обязательно
    Статус приёмки — привоза товара селлером на склад ПерфектПак. PENDING_CONFIRMATION — заявлена через API из вашей системы и ждёт подтверждения нашим менеджером (склад её ещё не видит); EXPECTED — заявлена, ещё не началась; RECEIVING — идёт пересчёт прямо сейчас; RECEIVED — завершена, количество сошлось; RECEIVED_WITH_DISCREPANCY — завершена, количество не сошлось (см. discrepancy_qty и items[].shortage_reason).
    Значения: PENDING_CONFIRMATION EXPECTED RECEIVING RECEIVED RECEIVED_WITH_DISCREPANCY
  • status_label строка обязательно
  • expected_qty целое число обязательно
    Сколько единиц всего заявлено по накладной.
  • accepted_qty целое число обязательно
    Сколько единиц всего фактически приняли.
  • discrepancy_qty целое число обязательно
    expected_qty минус accepted_qty, никогда не отрицательное.
    не меньше 0
  • created_at строка обязательно
    Когда приёмку завели. RFC 3339, +03:00 (МСК).
  • completed_at строка или null обязательно
    Когда приёмку закрыли, или null, пока она ещё идёт. RFC 3339, +03:00 (МСК).
  • source строка
    Кто заявил товар: api — ваша система через POST /v1/receipts, file — наш менеджер по вашей выгрузке, manual — наш менеджер вручную. Пусто у приёмок, заведённых до v1.1.
    Значения: api file manual
  • external_ref строка
    Ваш номер документа из POST /v1/receipts, как есть. Только у source: api.
  • comment строка
  • planned_date строка или null
    Плановая дата привоза (полночь МСК) или null.
  • confirmed_at строка или null
    Когда наш менеджер подтвердил заявку из API; null до подтверждения и у приёмок не из API.
  • items массив
    Состав приёмки по SKU. Поле присутствует только в ответе GET /receipts/{id} — в списке GET /receipts его нет.
    поля элемента — ReceiptItem
    • barcode строка обязательно
    • article строка
      Артикул продавца. Поле опущено, если у товара нет артикула.
    • name строка обязательно
    • honest_mark логическое
      Позиция подлежит маркировке «Честный знак» — каждая единица принимается по коду маркировки, а не по штрихкоду товара.
    • expected_qty целое число обязательно
      Сколько единиц этого SKU заявлено по накладной.
    • accepted_qty целое число обязательно
      Сколько единиц этого SKU фактически приняли и посчитали.
    • discrepancy_qty целое число обязательно
      expected_qty минус accepted_qty, никогда не отрицательное.
      не меньше 0
    • shortage_reason строка
      Причина расхождения по этой позиции, по-русски, из курируемого нами списка (не фиксированный enum — список может пополняться; пример ниже не исчерпывающий). Поле опущено, когда расхождения нет.
400 Тело не прошло проверку: validation_error (поле — в message), cabinet_required, mixed_marking, bad_request (не JSON или неизвестное поле).

Схема: ErrorResponse

  • error объект Error обязательно
    поля Error
    • code строка ErrorCode обязательно
      Машинный, стабильный код ошибки — ветвитесь в коде по нему, а не по тексту message (он на русском и может измениться). unauthorized — ключ не передан или не существует; key_revoked — ключ существует, но отозван; bad_request — параметры запроса не прошли валидацию; bad_cursor — курсор не наш или испорчен (в отличие от обычного bad_request, здесь нужно перезапросить страницу заново, а не повторять тот же курсор); not_found — ресурса нет либо он принадлежит не вашему client_id (специально неразличимо); rate_limited — превышен лимит запросов; internal — ошибка на нашей стороне. С v1.1: validation_error — поле тела запроса не прошло проверку (поле названо в message); cabinet_required — у вас несколько кабинетов, укажите cabinet_id; mixed_marking — в одной заявке позиции и с маркировкой, и без, разделите на две; write_disabled — заявки через API ещё не включены для вашего ключа; warehouse_unavailable — склад временно не принял заявку, повторите через минуту (заявка не создана); webhook_url_unverified — адрес не ответил 2xx на проверочное событие; webhook_limit — больше 10 подписок; webhooks_unavailable — вебхуки временно выключены; sandbox_only — операция только для тестового ключа.
      Значения: unauthorized key_revoked rate_limited not_found bad_request bad_cursor internal validation_error cabinet_required mixed_marking write_disabled warehouse_unavailable webhook_url_unverified webhook_limit webhooks_unavailable sandbox_only
    • message строка обязательно
      Текст ошибки на русском для лога и для человека — не для ветвления в коде.
    • request_id строка обязательно
      Тот же идентификатор, что и в заголовке X-Request-Id. Присылайте его в поддержку, чтобы нашли конкретный вызов.
401 Ключ не передан или не существует (unauthorized), либо существует, но отозван (key_revoked). Этот ответ единственный, где нет заголовков X-RateLimit-* — они появляются только после того, как ключ прошёл проверку.

Схема: ErrorResponse

  • error объект Error обязательно
    поля Error
    • code строка ErrorCode обязательно
      Машинный, стабильный код ошибки — ветвитесь в коде по нему, а не по тексту message (он на русском и может измениться). unauthorized — ключ не передан или не существует; key_revoked — ключ существует, но отозван; bad_request — параметры запроса не прошли валидацию; bad_cursor — курсор не наш или испорчен (в отличие от обычного bad_request, здесь нужно перезапросить страницу заново, а не повторять тот же курсор); not_found — ресурса нет либо он принадлежит не вашему client_id (специально неразличимо); rate_limited — превышен лимит запросов; internal — ошибка на нашей стороне. С v1.1: validation_error — поле тела запроса не прошло проверку (поле названо в message); cabinet_required — у вас несколько кабинетов, укажите cabinet_id; mixed_marking — в одной заявке позиции и с маркировкой, и без, разделите на две; write_disabled — заявки через API ещё не включены для вашего ключа; warehouse_unavailable — склад временно не принял заявку, повторите через минуту (заявка не создана); webhook_url_unverified — адрес не ответил 2xx на проверочное событие; webhook_limit — больше 10 подписок; webhooks_unavailable — вебхуки временно выключены; sandbox_only — операция только для тестового ключа.
      Значения: unauthorized key_revoked rate_limited not_found bad_request bad_cursor internal validation_error cabinet_required mixed_marking write_disabled warehouse_unavailable webhook_url_unverified webhook_limit webhooks_unavailable sandbox_only
    • message строка обязательно
      Текст ошибки на русском для лога и для человека — не для ветвления в коде.
    • request_id строка обязательно
      Тот же идентификатор, что и в заголовке X-Request-Id. Присылайте его в поддержку, чтобы нашли конкретный вызов.
429 Превышен лимит запросов — 60 в минуту на ключ, с всплеском до 20.

Схема: ErrorResponse

  • error объект Error обязательно
    поля Error
    • code строка ErrorCode обязательно
      Машинный, стабильный код ошибки — ветвитесь в коде по нему, а не по тексту message (он на русском и может измениться). unauthorized — ключ не передан или не существует; key_revoked — ключ существует, но отозван; bad_request — параметры запроса не прошли валидацию; bad_cursor — курсор не наш или испорчен (в отличие от обычного bad_request, здесь нужно перезапросить страницу заново, а не повторять тот же курсор); not_found — ресурса нет либо он принадлежит не вашему client_id (специально неразличимо); rate_limited — превышен лимит запросов; internal — ошибка на нашей стороне. С v1.1: validation_error — поле тела запроса не прошло проверку (поле названо в message); cabinet_required — у вас несколько кабинетов, укажите cabinet_id; mixed_marking — в одной заявке позиции и с маркировкой, и без, разделите на две; write_disabled — заявки через API ещё не включены для вашего ключа; warehouse_unavailable — склад временно не принял заявку, повторите через минуту (заявка не создана); webhook_url_unverified — адрес не ответил 2xx на проверочное событие; webhook_limit — больше 10 подписок; webhooks_unavailable — вебхуки временно выключены; sandbox_only — операция только для тестового ключа.
      Значения: unauthorized key_revoked rate_limited not_found bad_request bad_cursor internal validation_error cabinet_required mixed_marking write_disabled warehouse_unavailable webhook_url_unverified webhook_limit webhooks_unavailable sandbox_only
    • message строка обязательно
      Текст ошибки на русском для лога и для человека — не для ветвления в коде.
    • request_id строка обязательно
      Тот же идентификатор, что и в заголовке X-Request-Id. Присылайте его в поддержку, чтобы нашли конкретный вызов.
502 Склад временно не принял заявку (warehouse_unavailable). Заявка не создана — повторите через минуту.

Схема: ErrorResponse

  • error объект Error обязательно
    поля Error
    • code строка ErrorCode обязательно
      Машинный, стабильный код ошибки — ветвитесь в коде по нему, а не по тексту message (он на русском и может измениться). unauthorized — ключ не передан или не существует; key_revoked — ключ существует, но отозван; bad_request — параметры запроса не прошли валидацию; bad_cursor — курсор не наш или испорчен (в отличие от обычного bad_request, здесь нужно перезапросить страницу заново, а не повторять тот же курсор); not_found — ресурса нет либо он принадлежит не вашему client_id (специально неразличимо); rate_limited — превышен лимит запросов; internal — ошибка на нашей стороне. С v1.1: validation_error — поле тела запроса не прошло проверку (поле названо в message); cabinet_required — у вас несколько кабинетов, укажите cabinet_id; mixed_marking — в одной заявке позиции и с маркировкой, и без, разделите на две; write_disabled — заявки через API ещё не включены для вашего ключа; warehouse_unavailable — склад временно не принял заявку, повторите через минуту (заявка не создана); webhook_url_unverified — адрес не ответил 2xx на проверочное событие; webhook_limit — больше 10 подписок; webhooks_unavailable — вебхуки временно выключены; sandbox_only — операция только для тестового ключа.
      Значения: unauthorized key_revoked rate_limited not_found bad_request bad_cursor internal validation_error cabinet_required mixed_marking write_disabled warehouse_unavailable webhook_url_unverified webhook_limit webhooks_unavailable sandbox_only
    • message строка обязательно
      Текст ошибки на русском для лога и для человека — не для ветвления в коде.
    • request_id строка обязательно
      Тот же идентификатор, что и в заголовке X-Request-Id. Присылайте его в поддержку, чтобы нашли конкретный вызов.
503 Заявки через API не включены для вашего ключа (write_disabled).

Схема: ErrorResponse

  • error объект Error обязательно
    поля Error
    • code строка ErrorCode обязательно
      Машинный, стабильный код ошибки — ветвитесь в коде по нему, а не по тексту message (он на русском и может измениться). unauthorized — ключ не передан или не существует; key_revoked — ключ существует, но отозван; bad_request — параметры запроса не прошли валидацию; bad_cursor — курсор не наш или испорчен (в отличие от обычного bad_request, здесь нужно перезапросить страницу заново, а не повторять тот же курсор); not_found — ресурса нет либо он принадлежит не вашему client_id (специально неразличимо); rate_limited — превышен лимит запросов; internal — ошибка на нашей стороне. С v1.1: validation_error — поле тела запроса не прошло проверку (поле названо в message); cabinet_required — у вас несколько кабинетов, укажите cabinet_id; mixed_marking — в одной заявке позиции и с маркировкой, и без, разделите на две; write_disabled — заявки через API ещё не включены для вашего ключа; warehouse_unavailable — склад временно не принял заявку, повторите через минуту (заявка не создана); webhook_url_unverified — адрес не ответил 2xx на проверочное событие; webhook_limit — больше 10 подписок; webhooks_unavailable — вебхуки временно выключены; sandbox_only — операция только для тестового ключа.
      Значения: unauthorized key_revoked rate_limited not_found bad_request bad_cursor internal validation_error cabinet_required mixed_marking write_disabled warehouse_unavailable webhook_url_unverified webhook_limit webhooks_unavailable sandbox_only
    • message строка обязательно
      Текст ошибки на русском для лога и для человека — не для ветвления в коде.
    • request_id строка обязательно
      Тот же идентификатор, что и в заголовке X-Request-Id. Присылайте его в поддержку, чтобы нашли конкретный вызов.