{"openapi":"3.1.0","info":{"title":"Well Pay API","description":"\nПриём платежей по СБП. Схема работы: вы создаёте счёт, отправляете покупателя\nна `checkout_url`, получаете уведомление об оплате на свой адрес.\n\n**Деньги — целые копейки.** `15000` это 150,00 ₽. Дробных сумм в API нет\nнигде: строки с рублями на стороне мерчанта регулярно разбирают через float\nи теряют копейку.\n\n**Повтор безопасен.** Создание счёта с уже использованным `order_id` вернёт\nсуществующий счёт и код 200 вместо 201. Ретрай при таймауте не создаст\nвторой счёт и не спишет деньги дважды.\n\n**Уведомлению нельзя доверять на слово.** Проверяйте подпись —\nсм. раздел про webhooks. Без проверки любой, кто узнал ваш адрес, сможет\nобъявить счёт оплаченным.\n","version":"1.0.0"},"paths":{"/v1/invoices":{"post":{"tags":["invoices"],"summary":"Create Invoice","description":"Создаёт счёт и возвращает ссылку на оплату.\n\nПовторный вызов с тем же `order_id` вернёт существующий счёт и код 200\nвместо 201 — так ретрай при таймауте не создаёт второй счёт.","operationId":"create_invoice_v1_invoices_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Ключ не передан, неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Касса на паузе, компания не прошла модерацию или адрес не разрешён","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Объект не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Слишком часто — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Провайдер недоступен — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/invoices/{invoice_id}":{"get":{"tags":["invoices"],"summary":"Get Invoice","operationId":"get_invoice_v1_invoices__invoice_id__get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Ключ не передан, неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Касса на паузе, компания не прошла модерацию или адрес не разрешён","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Объект не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Слишком часто — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Провайдер недоступен — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orders/{order_id}":{"get":{"tags":["invoices"],"summary":"Get Invoice By Order","description":"Счёт по вашему идентификатору заказа.\n\nНужен, когда ответ на создание потерялся: вместо повторного создания\nмерчант может просто спросить, что стало с заказом.","operationId":"get_invoice_by_order_v1_orders__order_id__get","parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Ключ не передан, неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Касса на паузе, компания не прошла модерацию или адрес не разрешён","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Объект не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Слишком часто — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Провайдер недоступен — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/invoices/{invoice_id}/cancel":{"post":{"tags":["invoices"],"summary":"Cancel Invoice","operationId":"cancel_invoice_v1_invoices__invoice_id__cancel_post","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Ключ не передан, неверен или отозван","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Касса на паузе, компания не прошла модерацию или адрес не разрешён","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Объект не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Слишком часто — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Провайдер недоступен — повторите позже","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InvoiceRequest":{"properties":{"amount":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount","description":"Сумма заказа в копейках","examples":[150000]},"order_id":{"type":"string","maxLength":120,"minLength":1,"title":"Order Id","description":"Ваш идентификатор заказа. Повтор вернёт уже созданный счёт.","examples":["order-10241"]},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"success_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Success Url"},"fail_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Fail Url"},"payer_email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Payer Email"},"payer_phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Payer Phone"},"ttl_minutes":{"anyOf":[{"type":"integer","maximum":7200.0,"minimum":5.0},{"type":"null"}],"title":"Ttl Minutes","description":"Сколько живёт счёт: от 5 минут до 5 суток"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Method","description":"Способ оплаты. Не указан — покупатель выберет сам на странице оплаты.","examples":["sbp","crypto"]}},"type":"object","required":["amount","order_id"],"title":"InvoiceRequest","description":"Запрос на создание счёта.\n\nСуммы — в копейках: целыми числами их невозможно испортить округлением,\nв отличие от строк с рублями, которые на стороне мерчанта обычно проходят\nчерез float."},"InvoiceResponse":{"properties":{"id":{"type":"string","title":"Id"},"order_id":{"type":"string","title":"Order Id"},"status":{"type":"string","title":"Status"},"status_label":{"type":"string","title":"Status Label"},"mode":{"type":"string","title":"Mode"},"amount":{"type":"integer","title":"Amount"},"charged_amount":{"type":"integer","title":"Charged Amount"},"fee":{"type":"integer","title":"Fee"},"net":{"type":"integer","title":"Net"},"currency":{"type":"string","title":"Currency"},"checkout_url":{"type":"string","title":"Checkout Url"},"method":{"type":"string","title":"Method"},"qr_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qr Text"},"expires_at":{"type":"string","title":"Expires At"},"paid_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paid At"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["id","order_id","status","status_label","mode","amount","charged_amount","fee","net","currency","checkout_url","method","qr_text","expires_at","paid_at","metadata"],"title":"InvoiceResponse"},"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"},"Error":{"type":"object","required":["status","error_message"],"properties":{"status":{"type":"string","enum":["failed"]},"error_message":{"type":"string","description":"Текст на русском языке, пригодный для показа покупателю или в лог.","examples":["Минимальная сумма платежа — 10,00 ₽"]}}}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Ключ кассы из кабинета: Кассы → касса → Ключи API. Режим определяет ключ, а не касса: `wp_test_…` создаёт только тестовые счета, `wp_live_…` — только боевые."}}},"servers":[{"url":"https://api.well-pay.pro","description":"Боевой контур"}],"security":[{"ApiKeyAuth":[]}],"webhooks":{"payment":{"post":{"summary":"Уведомление об изменении статуса счёта","description":"\nМы отправляем `POST` на адрес, указанный в настройках кассы, и ждём любой\nответ 2xx. Не получили — повторим по расписанию 0, 1, 5, 30, 120, 360 минут.\n\n**Проверка подписи обязательна.** Считайте её по сырому телу запроса,\nдо разбора JSON: если сначала распарсить и собрать обратно, порядок ключей\nи пробелы изменятся, и подпись не сойдётся.\n\n```python\nimport hmac, hashlib\n\ndef verify(secret: str, signature: str, timestamp: str, raw_body: bytes) -> bool:\n    expected = \"sha256=\" + hmac.new(\n        secret.encode(), f\"{timestamp}.\".encode() + raw_body, hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, signature)\n```\n\nОтклоняйте запрос, если метка времени старше пяти минут: это защита от\nповторной отправки перехваченного уведомления.\n","operationId":"wellPayWebhook","security":[],"parameters":[{"in":"header","name":"X-WellPay-Signature","schema":{"type":"string","examples":["sha256=6f1c…"]},"description":"HMAC-SHA256 от строки «{timestamp}.{сырое тело}» на секрете подписки.","required":true},{"in":"header","name":"X-WellPay-Timestamp","schema":{"type":"string"},"description":"Unix-время отправки. Старше пяти минут — отклоняйте.","required":true},{"in":"header","name":"X-WellPay-Event","schema":{"type":"string"},"description":"Тип события."},{"in":"header","name":"X-WellPay-Delivery","schema":{"type":"string"},"description":"Идентификатор попытки доставки. Пригодится при обращении в поддержку."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","event","created_at","mode","data"],"properties":{"id":{"type":"string","description":"Идентификатор события. По нему дедуплицируйте: одно и то же уведомление приходит повторно, пока мы не получим 2xx.","examples":["evt_3F8KQ2M1N7XBZ0RTVCWD9E"]},"event":{"type":"string","enum":["payment.succeeded","payment.failed","payment.pending","invoice.expired","invoice.canceled","refund.succeeded","payout.paid","payout.rejected"]},"created_at":{"type":"string","format":"date-time"},"mode":{"type":"string","enum":["test","live"],"description":"Тестовые события деньгами не являются — не отгружайте по ним товар."},"data":{"type":"object","required":["invoice_id","order_id","status","amount","currency"],"properties":{"invoice_id":{"type":"string"},"order_id":{"type":"string","description":"Ваш номер заказа."},"status":{"type":"string","enum":["pending","paid","expired","canceled"]},"amount":{"type":"integer","description":"Сумма заказа в копейках."},"charged_amount":{"type":"integer","description":"Сколько заплатил покупатель."},"fee":{"type":"integer","description":"Удержанная комиссия."},"net":{"type":"integer","description":"Сколько зачислено вам."},"currency":{"type":"string","examples":["RUB"]},"description":{"type":["string","null"]},"paid_at":{"type":["string","null"],"format":"date-time"},"payment_id":{"type":["string","null"]},"metadata":{"type":["object","null"],"description":"То, что вы передали при создании счёта, без изменений."}}}}}}}},"responses":{"200":{"description":"Уведомление принято. Подойдёт любой код 2xx."}}}}}}