{"openapi":"3.1.0","info":{"title":"fnfd API","summary":"Проверка кассовых чеков для промо-акций (RU ФНС / UZ ОФД ГНК).","description":"Приём и проверка кассовых чеков для промо-акций. Контракт совместим с legacy\nAPMcheck — все поля в camelCase, существующие интеграции переносятся без правок.\n\n## Авторизация\nКаждый запрос приёма/статуса — с заголовком `api-key`. Ключи выпускаются\nper-promo (вид `pk_…`) в админке, раздел «API-ключи». Если `promoId` в запросе\nне передан — чек привязывается к промо ключа.\n\n## Жизненный цикл чека\n`ARRIVED` (принят) → `INSPECTED` (получены данные ФНС) → `REVIEWED` (финал:\n`approved` + причина/баллы). Числовой дубликат статуса — `checkingStatus`:\n0 / 1 / 2 (legacy). Чек, ушедший на ручную модерацию, остаётся `INSPECTED`\nс `needsReview: true` до решения Проверятора.\n\n## Идемпотентность и дубли\nПовторная отправка того же чека тем же `userUuid` возвращает уже созданный чек\n(тот же `uuid`). Тот же чек от ДРУГОГО участника создаёт новый чек, который\nотклоняется с `rejectKey: DUPLICATE`. Флаг `dupCheck: false` отключает проверку\nдля отладки (тест-полигон).\n\n## Основные rejectKey\n`FORMAT` (кривой QR) · `OUT_OF_PERIOD` / `FUTURE_DATE` / `EXPIRED` (даты) ·\n`MIN_SUM` · `DUPLICATE` / `DUPLICATE_PHOTO` / `LINKED_DUPLICATE` / `COPYCAT` ·\n`NO_MATCH` (нет товаров акции) · `PRODUCTS_COUNT_MIN` / `PRODUCTS_TOTAL_MIN` ·\n`INN_NOT_ALLOWED` / `INN_BLACKLISTED` / `GEO_CITY` / `GEO_STORE` ·\n`USER_BLOCKED` · `ONLINE_RETAILER` / `NON_PAID` · `RECEIPT_TYPE_NOT_ALLOWED` ·\n`FEW_RECEIPTS` (несколько разных QR на фото) · `FNS_SHORT_CHECK_FAILED` /\n`FNS_NOT_FOUND_TIMEOUT` (ФНС) · `MATCHED_IN_OTHER_PROMO` · `REJECTED` (прочее).\n\n## Callbacks (пуши бренду)\nНа каждый переход статуса FNFD POST-ит на callback-URL промо (настраивается в\nконфиге промо: `{\"url\", \"method\", \"headers\"}`) payload `ReceiptResult` + поле\n`state`. Ретраи: до 3 попыток с экспоненциальным бэкоффом; **400/409/424 не\nретраятся**; на **404** сначала переотправляется `ARRIVED` (бренд «не знает»\nчек), затем исходное событие. Ответ бренда разбирается: `externalId`/`meta`\nсохраняются в чек, `status: \"BLOCKED_USER\"` блокирует участника в промо и\nотклоняет его открытые чеки. Полная схема — в разделе Callbacks операции\n`POST /api/receipts/qr`.\n\n## Страны\nПромо бывают RU (чеки ФНС, QR `t=…&s=…&fn=…&i=…&fp=…`) и UZ (чеки ОФД ГНК,\nQR-ссылка `https://ofd.soliq.uz/check?…`). Дверь проверки выбирается по стране\nпромо автоматически.\n","contact":{"name":"fnfd","url":"https://fnfd.ru/"},"version":"0.1.0"},"servers":[{"url":"https://api.fnfd.ru","description":"production"},{"url":"https://dev.fnfd.ru","description":"dev-полигон"}],"paths":{"/health":{"get":{"tags":["health"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Health Get"}}}}}}},"/ready":{"get":{"tags":["health"],"summary":"Ready","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Ready Ready Get"}}}}}}},"/api/receipts/qr":{"post":{"tags":["receipts"],"summary":"Принять чек QR-строкой (основной метод)","description":"Принимает фискальный QR чека (`qrStr`) от участника `userUuid`. Чек проходит полный пайплайн: пречеки (формат/период/сумма/дубль) → ФНС → вердикт. Повтор того же чека тем же участником идемпотентен (вернётся тот же `uuid`). `dupCheck: false` отключает дедуп (отладка).","operationId":"intake_qr_api_receipts_qr_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrIntakeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeResponse"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"409":{"description":"`externalId` уже использован в этом промо (флаг промо `external_id_unique_constraint`) либо дубликат фото."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"callbacks":{"_receipt_status_callback":{"{$callback.url}":{"post":{"summary":"Пуш статуса чека бренду","description":"FNFD отправляет это уведомление на callback-URL промо при каждом переходе статуса (ARRIVED → INSPECTED → REVIEWED). Метод/заголовки — из конфига промо. Ответ 2xx останавливает ретраи; 400/409/424 не ретраятся; 404 запускает переотправку ARRIVED.","operationId":"_receipt_status_callback__callback_url__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandAck"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/widgets/receipts":{"post":{"tags":["receipts"],"summary":"Приём из виджета (QR-строка или фото)","description":"Эндпоинт встраиваемого виджета: form-data `qrAsString` ИЛИ `photos[]` (QR распознаётся из фото на сервере; не распознан → чек на ручную проверку). Доп. поля: `source`, `channel`, `meta` (JSON, виджет кладёт fingerprint в `meta.hash`), `dupCheck`. Несколько РАЗНЫХ QR на фото → reject `FEW_RECEIPTS`.","operationId":"intake_widget_qr_api_widgets_receipts_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_intake_widget_qr_api_widgets_receipts_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeResponse"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"callbacks":{"_receipt_status_callback":{"{$callback.url}":{"post":{"summary":"Пуш статуса чека бренду","description":"FNFD отправляет это уведомление на callback-URL промо при каждом переходе статуса (ARRIVED → INSPECTED → REVIEWED). Метод/заголовки — из конфига промо. Ответ 2xx останавливает ретраи; 400/409/424 не ретраятся; 404 запускает переотправку ARRIVED.","operationId":"_receipt_status_callback__callback_url__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandAck"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/receipts":{"post":{"tags":["receipts"],"summary":"Принять фото чека (multipart)","description":"До 5 фото ≤20 МБ (jpeg/png/webp/heic). Чек создаётся в `ARRIVED` и уходит на ручную модерацию. Байтовый дубль фото в промо → 409. Рядом с оригиналом сохраняется `-min` превью.","operationId":"intake_photos_api_receipts_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_intake_photos_api_receipts_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeResponse"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"409":{"description":"`externalId` уже использован в этом промо (флаг промо `external_id_unique_constraint`) либо дубликат фото."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"callbacks":{"_receipt_status_callback":{"{$callback.url}":{"post":{"summary":"Пуш статуса чека бренду","description":"FNFD отправляет это уведомление на callback-URL промо при каждом переходе статуса (ARRIVED → INSPECTED → REVIEWED). Метод/заголовки — из конфига промо. Ответ 2xx останавливает ретраи; 400/409/424 не ретраятся; 404 запускает переотправку ARRIVED.","operationId":"_receipt_status_callback__callback_url__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandAck"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/receipts/url":{"post":{"tags":["receipts"],"summary":"Принять фото чека по ссылкам","description":"Для ботов: фото уже лежит в их хранилище — передаются `urls[]`, FNFD скачивает сам. Дальше — как обычный фото-чек.","operationId":"intake_url_api_receipts_url_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeResponse"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"callbacks":{"_receipt_status_callback":{"{$callback.url}":{"post":{"summary":"Пуш статуса чека бренду","description":"FNFD отправляет это уведомление на callback-URL промо при каждом переходе статуса (ARRIVED → INSPECTED → REVIEWED). Метод/заголовки — из конфига промо. Ответ 2xx останавливает ретраи; 400/409/424 не ретраятся; 404 запускает переотправку ARRIVED.","operationId":"_receipt_status_callback__callback_url__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandAck"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/receipts/{receipt_uuid}/photos":{"post":{"tags":["receipts"],"summary":"Append Photos","description":"Append photos to an existing receipt (legacy /api/receipts/{id}/photos).","operationId":"append_photos_api_receipts__receipt_uuid__photos_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"receipt_uuid","in":"path","required":true,"schema":{"type":"string","title":"Receipt Uuid"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_append_photos_api_receipts__receipt_uuid__photos_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/qr":{"post":{"tags":["receipts"],"summary":"Синхронный разбор QR (без создания чека)","description":"Валидация на стороне бренда: принимает `qrAsString` или фото, возвращает разобранные фискальные реквизиты (ФН/ФД/ФП/сумма/дата). Чек НЕ создаётся.","operationId":"parse_qr_endpoint_api_qr_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_qr_endpoint_api_qr_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Parse Qr Endpoint Api Qr Post"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/receipts/{receipt_uuid}/dispute":{"post":{"tags":["receipts"],"summary":"Открыть диспут по отклонённому чеку","description":"Участник не согласен с отказом. Диспут попадает в админку (раздел «Диспуты»); решение «пересмотреть» возвращает чек в Проверятор.","operationId":"dispute_api_receipts__receipt_uuid__dispute_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"receipt_uuid","in":"path","required":true,"schema":{"type":"string","title":"Receipt Uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dispute Api Receipts  Receipt Uuid  Dispute Post"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"409":{"description":"Диспут возможен только по отклонённому чеку."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/receipts/{receipt_uuid}":{"get":{"tags":["receipts"],"summary":"Полный статус чека","description":"Вся информация о чеке: state/checkingStatus, вердикт (approved, rejectReason/rejectKey, совпавшие товары, баллы), реквизиты из ФНС (`fnsReceipt`), retailer/total/answers (legacy REVIEWED-поля), `matchedPromos`, `delivered` (статус доставки callback'а), `needsReview` (чек у модераторов). Поля заполняются по мере прохождения пайплайна.","operationId":"get_receipt_api_receipts__receipt_uuid__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"receipt_uuid","in":"path","required":true,"schema":{"type":"string","title":"Receipt Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptResult"}}}},"401":{"description":"Нет/неверный `api-key`."},"400":{"description":"Невалидный запрос (формат фото, размер >20 МБ, >5 фото…)."},"404":{"description":"Чек не найден."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/promos":{"get":{"tags":["public"],"summary":"Public Promos","description":"Список активных промо (id + имя + страна) — для тест-ЛК полигона: выбор промо,\nв которое слать чек. country — страновой фильтр (RU/UZ не пересекаются). Без\nсекретов (имена кампаний публичны).","operationId":"public_promos_api_public_promos_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Promos Api Public Promos Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reference":{"get":{"tags":["public"],"summary":"Scalar — интерактивный API-справочник","description":"Современный интерактивный справочник (Scalar) поверх /openapi.json: схемы, примеры, генератор клиентского кода, выполнение запросов из браузера.","operationId":"scalar_reference_reference_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/integration":{"get":{"tags":["public"],"summary":"Руководство по интеграции (для разработчика бренда)","description":"Сквозной гайд подключения: ключи, виджет, приём чека, статусы, callback, rejectKey, чек-лист запуска. Источник — docs/INTEGRATION.md, страница собирается утилитой tools/render_integration_doc.py.","operationId":"integration_guide_integration_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api-docs":{"get":{"tags":["public"],"summary":"Api Docs","operationId":"api_docs_api_docs_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/r/{uuid}.json":{"get":{"tags":["public"],"summary":"Receipt Status Json","operationId":"receipt_status_json_r__uuid__json_get","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","title":"Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Receipt Status Json R  Uuid  Json Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/r/{uuid}":{"get":{"tags":["public"],"summary":"Receipt Status Page","operationId":"receipt_status_page_r__uuid__get","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","title":"Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/widget/fnfd-widget.js":{"get":{"tags":["public"],"summary":"Widget Js","description":"Serve the embeddable widget (camera QR scan + photo upload) from disk.","operationId":"widget_js_widget_fnfd_widget_js_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/widget/demo":{"get":{"tags":["public"],"summary":"Widget Demo","operationId":"widget_demo_widget_demo_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/checkeast/check":{"post":{"tags":["checkeast"],"summary":"Checkeast Check","description":"Проверить один чек по всем промо-витрины ЧЕКист (read-only). Один запрос в\nФНС (кэш ров навсегда). state=REVIEWED + promos[] при синхронном подтверждении;\nstate=ARRIVED + uuid, если ФНС ещё не отдала чек (ЧЕКист поллит GET /check/{uuid}).","operationId":"checkeast_check_api_checkeast_check_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckeastCheckRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Checkeast Check Api Checkeast Check Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/checkeast/check/{scan_uuid}":{"get":{"tags":["checkeast"],"summary":"Checkeast Check Status","description":"Поллинг результата проверки. ARRIVED → пробуем дотянуть чек из ФНС (ров кэширует,\nповторно ФНС не дёргается после подтверждения). REVIEWED → пересобираем promos[]\nиз закэшированного чека (свежий alreadyRegistered).","operationId":"checkeast_check_status_api_checkeast_check__scan_uuid__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"scan_uuid","in":"path","required":true,"schema":{"type":"string","title":"Scan Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Checkeast Check Status Api Checkeast Check  Scan Uuid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkeast/promos":{"get":{"tags":["checkeast"],"summary":"Checkeast Promos","description":"Каталог промо-витрины: активные промо с share_to_checkeast=true + display-поля.","operationId":"checkeast_promos_api_checkeast_promos_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Checkeast Promos Api Checkeast Promos Get"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/lk.html":{"get":{"tags":["lk"],"summary":"Lk Page","operationId":"lk_page_lk_html_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}},"security":[{"HTTPBasic":[]}]}},"/api/lk/users":{"get":{"tags":["lk"],"summary":"Lk Users","description":"Участники с чеками + следующий свободный id. country — страновой скоуп: в\nUZ-сегменте видны только UZ-участники, новый id из UZ-диапазона (2001+); RU — 1001+.\nДанные RU/UZ не пересекаются.","operationId":"lk_users_api_lk_users_get","security":[{"HTTPBasic":[]}],"parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Lk Users Api Lk Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lk/receipts":{"get":{"tags":["lk"],"summary":"Lk Receipts","description":"Чеки участника (server-side) для списка в ЛК. country — страновой скоуп.","operationId":"lk_receipts_api_lk_receipts_get","security":[{"HTTPBasic":[]}],"parameters":[{"name":"userUuid","in":"query","required":true,"schema":{"type":"string","title":"Useruuid"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Lk Receipts Api Lk Receipts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lk/r/{uuid}":{"get":{"tags":["lk"],"summary":"Lk Receipt Detail","operationId":"lk_receipt_detail_lk_r__uuid__get","security":[{"HTTPBasic":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","title":"Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lk/r/{uuid}/edit":{"post":{"tags":["lk"],"summary":"Lk Receipt Edit","operationId":"lk_receipt_edit_lk_r__uuid__edit_post","security":[{"HTTPBasic":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","title":"Uuid"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_lk_receipt_edit_lk_r__uuid__edit_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AnswerProduct":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"count":{"type":"number","title":"Count","default":0},"subtotal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subtotal"}},"type":"object","required":["id","name"],"title":"AnswerProduct"},"Answers":{"properties":{"productsWithCountAndSubtotals":{"items":{"$ref":"#/components/schemas/AnswerProduct"},"type":"array","title":"Productswithcountandsubtotals"},"products":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Products"}},"type":"object","title":"Answers"},"Body_append_photos_api_receipts__receipt_uuid__photos_post":{"properties":{"photos":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Photos"}},"type":"object","required":["photos"],"title":"Body_append_photos_api_receipts__receipt_uuid__photos_post"},"Body_intake_photos_api_receipts_post":{"properties":{"photos":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Photos"},"userUuid":{"type":"string","title":"Useruuid"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"}},"type":"object","required":["photos","userUuid"],"title":"Body_intake_photos_api_receipts_post"},"Body_intake_widget_qr_api_widgets_receipts_post":{"properties":{"qrAsString":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qrasstring"},"userUuid":{"type":"string","title":"Useruuid"},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","default":"widget-qr-scan"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel","default":"web"},"meta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta"},"dupCheck":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dupcheck"},"photos":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Photos"}},"type":"object","required":["userUuid"],"title":"Body_intake_widget_qr_api_widgets_receipts_post"},"Body_lk_receipt_edit_lk_r__uuid__edit_post":{"properties":{"action":{"type":"string","title":"Action"},"reason":{"type":"string","title":"Reason","default":""},"external":{"type":"string","title":"External","default":""}},"type":"object","required":["action"],"title":"Body_lk_receipt_edit_lk_r__uuid__edit_post"},"Body_parse_qr_endpoint_api_qr_post":{"properties":{"qrAsString":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qrasstring"},"photo":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Photo"}},"type":"object","title":"Body_parse_qr_endpoint_api_qr_post"},"BrandAck":{"properties":{"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid","description":"Внешний номер чека на стороне бренда — сохранится в чек."},"meta":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Meta","description":"Произвольные данные бренда — сохранятся в meta чека."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"`BLOCKED_USER` — заблокировать участника в промо и отклонить его открытые чеки."}},"type":"object","title":"BrandAck","description":"Необязательный ответ бренда на callback (разбирается FNFD)."},"CallbackEvent":{"properties":{"state":{"$ref":"#/components/schemas/ReceiptState"},"uuid":{"type":"string","title":"Uuid"},"userUuid":{"type":"string","title":"Useruuid"},"approved":{"type":"boolean","title":"Approved","default":false},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"},"country":{"type":"string","title":"Country","default":"ru"},"receiptId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Receiptid"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"},"receiptDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiptdate"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"photos":{"items":{"type":"string"},"type":"array","title":"Photos"},"duplicate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duplicate"},"rejectReason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectreason"},"rejectKey":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectkey"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"qrString":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qrstring"},"fnsReceipt":{"anyOf":[{"$ref":"#/components/schemas/FiscalReceipt"},{"type":"null"}]},"verdict":{"anyOf":[{"$ref":"#/components/schemas/Verdict"},{"type":"null"}]},"retailer":{"anyOf":[{"$ref":"#/components/schemas/Retailer"},{"type":"null"}]},"total":{"anyOf":[{"$ref":"#/components/schemas/Total"},{"type":"null"}]},"answers":{"anyOf":[{"$ref":"#/components/schemas/Answers"},{"type":"null"}]},"city":{"anyOf":[{"$ref":"#/components/schemas/City"},{"type":"null"}]},"rules":{"items":{"type":"string"},"type":"array","title":"Rules"},"rulesCount":{"type":"integer","title":"Rulescount","default":0},"rulesPoints":{"type":"integer","title":"Rulespoints","default":0},"promoPoints":{"type":"integer","title":"Promopoints","default":0},"reviewers":{"items":{"type":"string"},"type":"array","title":"Reviewers"},"matchedPromos":{"items":{"type":"integer"},"type":"array","title":"Matchedpromos"},"delivered":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delivered"},"needsReview":{"type":"boolean","title":"Needsreview","default":false},"priority":{"type":"integer","title":"Priority","default":0},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["state","uuid","userUuid"],"title":"CallbackEvent","description":"Payload пуша бренду: тот же объект, что `GET /api/receipts/{uuid}`,\n`state` указывает событие (ARRIVED / INSPECTED / REVIEWED)."},"CheckeastCheckRequest":{"properties":{"qrStr":{"type":"string","title":"Qrstr"},"userUuid":{"type":"string","title":"Useruuid"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"}},"type":"object","required":["qrStr","userUuid"],"title":"CheckeastCheckRequest"},"City":{"properties":{"id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"}},"type":"object","title":"City"},"FiscalItem":{"properties":{"name":{"type":"string","title":"Name"},"price":{"type":"integer","title":"Price","description":"price per unit, kopeks"},"quantity":{"type":"number","title":"Quantity","default":1},"sum":{"type":"integer","title":"Sum","description":"line sum, kopeks"},"nds":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nds"}},"type":"object","required":["name","price","sum"],"title":"FiscalItem"},"FiscalReceipt":{"properties":{"fn":{"type":"string","title":"Fn"},"fd":{"type":"string","title":"Fd"},"fp":{"type":"string","title":"Fp"},"receiptDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiptdate"},"receiptTime":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receipttime"},"totalSum":{"type":"integer","title":"Totalsum","description":"total, kopeks"},"retailerInn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retailerinn"},"retailerName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retailername"},"retailerAddress":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retaileraddress"},"taxSystem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taxsystem"},"isOnline":{"type":"boolean","title":"Isonline","default":false},"isPaid":{"type":"boolean","title":"Ispaid","default":true},"items":{"items":{"$ref":"#/components/schemas/FiscalItem"},"type":"array","title":"Items"}},"type":"object","required":["fn","fd","fp","totalSum"],"title":"FiscalReceipt"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IntakeResponse":{"properties":{"status":{"type":"string","title":"Status","default":"success"},"uuid":{"type":"string","title":"Uuid"},"receiptId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Receiptid"},"requestUuid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requestuuid"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"replayed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Replayed"}},"type":"object","required":["uuid"],"title":"IntakeResponse"},"QrIntakeRequest":{"properties":{"qrStr":{"type":"string","title":"Qrstr"},"userUuid":{"type":"string","title":"Useruuid"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"},"dupCheck":{"type":"boolean","title":"Dupcheck","default":true}},"type":"object","required":["qrStr","userUuid"],"title":"QrIntakeRequest","description":"Body of ``POST /api/receipts/qr``."},"ReceiptResult":{"properties":{"state":{"$ref":"#/components/schemas/ReceiptState"},"uuid":{"type":"string","title":"Uuid"},"userUuid":{"type":"string","title":"Useruuid"},"approved":{"type":"boolean","title":"Approved","default":false},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"},"country":{"type":"string","title":"Country","default":"ru"},"receiptId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Receiptid"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"},"receiptDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiptdate"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"photos":{"items":{"type":"string"},"type":"array","title":"Photos"},"duplicate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duplicate"},"rejectReason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectreason"},"rejectKey":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectkey"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"qrString":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qrstring"},"fnsReceipt":{"anyOf":[{"$ref":"#/components/schemas/FiscalReceipt"},{"type":"null"}]},"verdict":{"anyOf":[{"$ref":"#/components/schemas/Verdict"},{"type":"null"}]},"retailer":{"anyOf":[{"$ref":"#/components/schemas/Retailer"},{"type":"null"}]},"total":{"anyOf":[{"$ref":"#/components/schemas/Total"},{"type":"null"}]},"answers":{"anyOf":[{"$ref":"#/components/schemas/Answers"},{"type":"null"}]},"city":{"anyOf":[{"$ref":"#/components/schemas/City"},{"type":"null"}]},"rules":{"items":{"type":"string"},"type":"array","title":"Rules"},"rulesCount":{"type":"integer","title":"Rulescount","default":0},"rulesPoints":{"type":"integer","title":"Rulespoints","default":0},"promoPoints":{"type":"integer","title":"Promopoints","default":0},"reviewers":{"items":{"type":"string"},"type":"array","title":"Reviewers"},"matchedPromos":{"items":{"type":"integer"},"type":"array","title":"Matchedpromos"},"delivered":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delivered"},"needsReview":{"type":"boolean","title":"Needsreview","default":false},"priority":{"type":"integer","title":"Priority","default":0},"meta":{"additionalProperties":true,"type":"object","title":"Meta"},"checkingStatus":{"type":"integer","title":"Checkingstatus","description":"Legacy 0/1/2: ARRIVED=0 (queued), INSPECTED=1 (checked), REVIEWED=2.","readOnly":true}},"type":"object","required":["state","uuid","userUuid","checkingStatus"],"title":"ReceiptResult","description":"``GET /api/receipts/{uuid}`` — superset across states; nulls per state."},"ReceiptState":{"type":"string","enum":["ARRIVED","INSPECTED","REVIEWED"],"title":"ReceiptState"},"Retailer":{"properties":{"id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"inn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inn"},"store":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Store"}},"type":"object","title":"Retailer"},"Total":{"properties":{"sum":{"type":"integer","title":"Sum","default":0},"count":{"type":"number","title":"Count","default":0},"sumSubtotal":{"type":"integer","title":"Sumsubtotal","default":0}},"type":"object","title":"Total"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"Verdict":{"properties":{"approved":{"type":"boolean","title":"Approved"},"promoId":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promoid"},"matchedProducts":{"items":{"$ref":"#/components/schemas/VerdictProduct"},"type":"array","title":"Matchedproducts"},"totalPoints":{"type":"integer","title":"Totalpoints","default":0},"rewardKind":{"type":"string","title":"Rewardkind","default":"points"},"qualifyLabel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualifylabel"},"rejectReason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectreason"},"rejectKey":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejectkey"},"antifraudViolations":{"items":{"type":"string"},"type":"array","title":"Antifraudviolations"},"needsManualReview":{"type":"boolean","title":"Needsmanualreview","default":false}},"type":"object","required":["approved"],"title":"Verdict"},"VerdictProduct":{"properties":{"productId":{"type":"integer","title":"Productid"},"name":{"type":"string","title":"Name"},"count":{"type":"number","title":"Count"},"subtotalKopeks":{"type":"integer","title":"Subtotalkopeks"},"points":{"type":"integer","title":"Points"}},"type":"object","required":["productId","name","count","subtotalKopeks","points"],"title":"VerdictProduct"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","description":"Per-promo ключ (`pk_…`) — админка → «API-ключи». Если promoId в запросе не передан, чек привязывается к промо ключа.","in":"header","name":"api-key"},"HTTPBasic":{"type":"http","scheme":"basic"}}},"tags":[{"name":"receipts","description":"Приём чеков (QR / фото / URL / виджет) и статус по api-key."},{"name":"public","description":"Публичные ручки без api-key: лёгкий статус участника, список промо, документация."},{"name":"lk","description":"Тест-полигон (Имитатор промо-сайта) — отдельный basic-auth, не для брендов."}]}