{"openapi":"3.1.0","info":{"title":"RUBREK API","version":"1.0.0","description":"API для интеграции с платёжной платформой RUBREK.\n\nЧисловые значения в примерах (суммы, курсы, комиссии) — иллюстративные и не являются публичной офертой: фактические условия подключения согласуются индивидуально.\n\n## Авторизация\n\nВсе запросы требуют заголовок `Authorization: Bearer <api_key>`.\n\n- **Live-ключ** (`rbk_...`) — работает с реальными данными\n- **Test-ключ** (`rbk_test_...`) — тестовый режим, см. раздел «Ограничения тестового режима»\n\n## Формат ошибок\n\nОшибки возвращаются JSON-объектом с полем `message`:\n\n```json\n{ \"message\": \"Resource not found.\" }\n```\n\n| Код | Когда | Тело |\n|-----|-------|------|\n| `401` | Нет/неверный API-ключ | `{\"error\": \"...\", \"message\": \"...\"}` (поле `error` — историческое, дублирует `message`; используйте `message`) |\n| `403` | Функция недоступна вашему аккаунту (см. `GET /v1/capabilities`) | `{\"error\": \"...\"}` или `{\"message\": \"...\"}` |\n| `404` | Ресурс не найден | `{\"message\": \"Resource not found.\"}` |\n| `422` | Ошибка валидации | `{\"message\": \"...\", \"errors\": {\"field\": [\"...\"]}}` |\n| `429` | Превышение лимитов (зарезервировано; жёсткие лимиты сейчас не применяются) | `{\"message\": \"Too Many Requests\"}` |\n\n## Статусы заказа и жизненный цикл\n\n| Статус | Описание |\n|--------|----------|\n| `pending` | Создан, ожидает оплаты |\n| `processing` | Оплата обрабатывается провайдером |\n| `paid` | Оплачен, средства зачислены мерчанту |\n| `cancelled` | Отменён или истёк |\n\n**Переходы статусов:**\n\n```\npending → processing → paid\npending → cancelled          (истечение срока или отмена)\nprocessing → cancelled       (ошибка/истечение на стороне провайдера)\ncancelled → paid             (поздняя оплата — см. ниже)\n```\n\n`paid` — терминальный статус: из него заказ не переходит ни в какой другой.\n\n**Срок жизни заказа (TTL).** Заказ в `pending` автоматически отменяется:\n\n- если клиенту **ещё не выданы** платёжные реквизиты (QR/ссылка) — через персональный срок мерчанта `order_ttl_minutes` (по умолчанию 30 минут с момента создания);\n- если реквизиты **выданы** — через фиксированные 15 минут с момента выдачи.\n\n`payment_url` после истечения открывается, но показывает «ссылка аннулирована» — оплатить по нему нельзя инициировать заново.\n\n**Поздняя оплата.** Если клиент оплатил после истечения (успел отсканировать QR до отмены, а платёж подтвердился позже) — деньги принимаются: заказ переходит `cancelled → paid`, зачисление мерчанту выполняется, и **вебхук `order.paid` придёт после `order.cancelled`**. Ваша интеграция обязана корректно обрабатывать этот порядок: не считайте `cancelled` терминальным.\n\n## Рекомендованный флоу финализации\n\nВебхук — **триггер**, а не источник истины. После получения `order.paid`:\n\n1. Проверьте подпись `X-Webhook-Signature`.\n2. Выполните readback: `GET /v1/orders/{id}` (или `by-reference/{reference}`).\n3. Выдавайте товар/услугу **только если readback вернул `status=paid`**.\n\nЭто защищает от рассинхронов, replay-атак и двойных выдач.\n\n## Идемпотентность создания и таймауты\n\n`POST /v1/orders` защищён от дублей на двух независимых уровнях. Рекомендуем использовать оба:\n\n```\nPOST /v1/orders\nIdempotency-Key: 7f9c24e5-a1b2-4c3d-9e8f-0a1b2c3d4e5f   ← техключ этого POST (UUID)\n\n{ \"external_id\": \"attempt-58317\", \"point_id\": 233, \"amount_rub\": 1500 }\n```\n\n**Уровень 1 — заголовок `Idempotency-Key`** (opaque UUID, новый на каждую create-операцию):\n\n- повтор с тем же ключом и **тем же payload** (таймаут, 500, обрыв соединения) возвращает исходный заказ: HTTP `200`, заголовок `Idempotent-Replayed: true`, те же `payment_url` и `payment_reference`;\n- тот же ключ с **другим payload** — `409` `{\"error\": \"idempotency_key_conflict\"}`;\n- повтор, пока исходный запрос **ещё выполняется**, — `409` `{\"error\": \"idempotency_in_flight\"}` + `Retry-After: 5`: подождите пару секунд и повторите;\n- ключ хранится 24 часа; действует и в песочнице (`rbk_test_`).\n\n**Уровень 2 — поле `external_id`** (до 64 символов): идентификатор **платёжной попытки** в вашей системе. Семантика:\n\n- один `external_id` = одна платёжная попытка, навсегда. Новый QR/ссылка на тот же заказ вашей системы = **новый** `external_id` (например, `order-123-try-2`);\n- повтор с тем же `external_id` и теми же параметрами — replay (HTTP `200`, `idempotent_replay: true`), дубль не создаётся;\n- тот же `external_id` с другими `amount_rub`/`point_id` — `409` `{\"error\": \"idempotency_conflict\", \"existing_order_id\": …}`;\n- recovery после таймаута/падения клиента: `GET /v1/orders/by-external-id/{external_id}` — `200` значит заказ был создан (в ответе готовый `payment_url`), `404` — не был, создавайте заново.\n\n**Гарантия атомарности:** `external_id` — это колонка самой строки заказа (пишется тем же INSERT, что и заказ, под unique-индексом `merchant+external_id`), поэтому ситуация «заказ создан, а ключ не сохранён» невозможна. Заголовочный ключ фиксируется после создания заказа; если запрос упал между этими моментами, ретрай перехватывается уровнем `external_id`.\n\nВсе эндпоинты чтения заказа (`GET /orders/{id}`, `by-reference`, `by-external-id`, список) возвращают `payment_url` — собирать ссылку из `payment_reference` самостоятельно не нужно.\n\n## Вебхуки\n\nПри изменении статуса заказа на ваш webhook URL отправляется POST с телом:\n\n```json\n{ \"event\": \"order.paid\", \"timestamp\": \"2026-07-10T12:00:00+00:00\", \"order\": { ... } }\n```\n\nСобытия заказа: `order.processing`, `order.paid`, `order.cancelled`.\nОбъект `order` в теле имеет **ту же схему, что и ответ `GET /v1/orders/{id}`**.\n\n**Несколько подписок (проектов).** В кабинете (раздел API → Вебхуки) можно добавить **несколько webhook-URL**; у каждой подписки — свой набор событий и переключатель вкл/выкл. Каждое событие отправляется на **все активные подписки**, подписанные на него (подписка без выбранных событий получает все). Секрет подписи один на аккаунт.\n\n**Требования к вашему endpoint:**\n\n- **Критерий успешной доставки** — любой HTTP-ответ `2xx`. Тело ответа не проверяется (можете отвечать пустым `200`).\n- Отвечайте быстро (таймаут запроса — 15 секунд): сначала `2xx`, потом обработка.\n\n**Ретраи и гарантии доставки:**\n\n- 3 попытки доставки с задержками **0с / 60с / 300с** от предыдущей неудачи.\n- После 3 неудачных попыток автоматические ретраи прекращаются. Повторную отправку можно запустить вручную: **кнопка «Переотправить» в кабинете** (раздел API → журнал вебхуков) — переотправка идёт на актуальный URL из настроек. Плюс используйте readback-опрос `GET /v1/orders/{id}` как страховку.\n- Семантика **at-least-once**: дубликаты возможны (например, если ваш endpoint обработал событие, но ответил не-2xx; а также при ручной переотправке). Обрабатывайте идемпотентно — по ключу `event + order.id`.\n- **Порядок не гарантируется**: `order.paid` может прийти без предшествующего `order.processing`, а при поздней оплате — после `order.cancelled`.\n\n**Подпись:**\n\n- `X-Webhook-Signature-V2` — **рекомендуемая**: HMAC-SHA256 от строки `\"{timestamp}.{body}\"`, где `timestamp` — значение заголовка `X-Webhook-Timestamp` (unix-секунды отправки), `body` — точное сырое тело запроса. Ключ — ваш webhook-секрет, вывод — hex в нижнем регистре.\n- `X-Webhook-Signature` — легаси (сохраняется навсегда): HMAC-SHA256 только от тела.\n- `X-Webhook-Timestamp` — unix-время отправки (секунды).\n- `X-Webhook-Event` — дублирует имя события.\n- Сверяйте подпись сравнением, устойчивым к таймингу (`hash_equals` и аналоги), от **сырого** тела (до JSON-декодирования).\n\n**Worked example** (для unit-теста):\n\n```\nsecret:    whsec_c8f2a1d94b7e\nbody:      {\"event\":\"order.paid\",\"timestamp\":\"2026-07-10T12:00:00+00:00\",\"order\":{\"id\":12345,\"status\":\"paid\"}}\nV1 hex:    hash_hmac('sha256', body, secret)\n           = 6c842550be4d8b86db3d406bef9b3144861df83c103b17fbf3283020f8be1ca3\nV2 (при X-Webhook-Timestamp: 1783512000):\n           hash_hmac('sha256', '1783512000.' . body, secret)\n           = 184848b18eea23ce4d9c276f9cf56619fdd38e803037aa0ae42fa71ee850e308\n```\n\n```php\n// V2 (рекомендуется):\n$expected = hash_hmac('sha256', $timestampHeader . '.' . $rawBody, $secret);\nhash_equals($expected, strtolower($signatureV2Header));\n```\n\n**Защита от replay.** Проверяйте V2-подпись и отклоняйте события, у которых `X-Webhook-Timestamp` старше 5 минут — перехваченное тело нельзя переиграть позже. И всегда выполняйте readback перед финализацией (см. выше) — readback полностью нейтрализует replay даже без проверки времени.\n\n**Исходящие IP.** Диапазон адресов, с которых уходят вебхуки, выдаётся по запросу — если вам нужен allowlist, напишите в поддержку.\n\n### События по клиентам\n\nДля аккаунтов с флоу **Registered Clients** (процессинг ведёт собственную верификацию — регистрация через `POST /api/v1/clients`) дополнительно отправляется событие `client.updated`, когда у клиента меняется идентификация, блокировка или `account_number`. Тело:\n\n```json\n{\n  \"event\": \"client.updated\",\n  \"timestamp\": \"2026-04-24T12:00:00Z\",\n  \"changes\": [\"identification_level\", \"passport_state\"],\n  \"client\": {\n    \"id\": 1, \"phone\": \"+79001234567\",\n    \"account_number\": \"40817810000000000001\",\n    \"identification_level\": 1,\n    \"passport_state\": \"approved\", \"address_state\": \"approved\",\n    \"is_blocked\": false, \"identification_error\": null\n  }\n}\n```\n\nМассив `changes` перечисляет имена полей, значения которых поменялись в этом событии — удобно, если нужно реагировать только на конкретный переход (например, `identification_level` с 0 на 1).\n\n## Проверенные клиенты (KYC): документы загружаются один раз\n\nЕсли вы создаёте заказы с `kyc_type=verified`, привяжите заказ к клиенту **ключом** — и KYC-документы понадобятся только при первом заказе:\n\n- `client_external_id` — ваш собственный идентификатор клиента (рекомендуется), или\n- `client_phone` — телефон клиента.\n\n**Первый заказ клиента** — ключ + документы (`multipart/form-data`):\n\n```\nPOST /api/v1/orders\npoint_id=1&amount_rub=5000&kyc_type=verified&client_external_id=usr-8123\nfile_document=@passport.jpg&file_selfie=@selfie.jpg\n```\n\n**Все следующие заказы** — только ключ, без файлов:\n\n```\nPOST /api/v1/orders\npoint_id=1&amount_rub=3000&kyc_type=verified&client_external_id=usr-8123\n```\n\nЗаказ автоматически привяжется к клиенту и его документам. Сверка данных клиента с фактическим плательщиком выполняется на нашей стороне автоматически; после первого подтверждения последующие заказы клиента проходят KYC без вашего участия. До подтверждения KYC средства по заказу находятся в HOLD — это штатно.\n\nПроверить клиента заранее: `GET /api/v1/clients/{key}` (ключ — external_id или телефон; `status=verified` → файлы не нужны). Список всей базы: `GET /api/v1/clients`.\n\nЕсли ключ не передавать, документы к базе клиентов не привязываются и каждый заказ проверяется отдельно.\n\n## Тестовый режим (`rbk_test_...`): stateful-песочница\n\nТестовый ключ работает с **песочницей**: заказы живут в отдельном хранилище 48 часов и никогда не касаются боевых данных (балансов, статистики, заказов). При этом доступен **полный end-to-end цикл**:\n\n1. `POST /v1/orders` — заказ создаётся с реальным тестовым `id` (диапазон 90 000 000+), `is_test: true`, поле `_sandbox` в ответе. Идемпотентность по `external_id` работает.\n2. `GET /v1/orders/{id}`, `by-reference/{reference}`, `by-external-id/{externalId}`, список `GET /v1/orders` — readback тестовых заказов работает (тестовый ключ видит только песочницу, живой — только боевые заказы).\n3. `POST /v1/orders/{id}/simulate-payment` — заказ становится `paid` и на ваши активные вебхук-подписки уходит **настоящий** `order.paid`: боевой пайплайн доставки, реальные подписи V1/V2 вашими секретами, payload помечен `\"is_test\": true`. Повторная симуляция идемпотентна (вебхук не дублируется). В ответе `webhooks_queued` — сколько подписок получит событие (0 = добавьте подписку в ЛК → API → Вебхуки).\n4. Повторный readback — статус `paid`.\n\n**Тестовая страница оплаты:** `payment_url` тестового заказа открывает настоящую страницу оплаты в демо-режиме (баннер «Тестовый режим»): вместо QR провайдера — кнопка «Оплатить», которая симулирует оплату и отправляет тот же вебхук `order.paid`, что и `simulate-payment`. Удобно прогонять клиентский UX целиком.\n\n**Отличия от боевого режима:** провайдеры не вызываются, деньги и балансы не двигаются; заказы не видны в ЛК и исчезают через 48 часов; событие рассылается только `order.paid` по симуляции.\n\nВ обработчике вебхуков различайте тестовые события по полю `is_test: true` в корне payload.\n\n## Локальные валюты\n\nЕсли касса настроена на локальную валюту (например THB), в заказе будут заполнены поля:\n\n- `local_currency_code` — код валюты (THB, INR, ...)\n- `rate_local_per_usdt` — биржевой курс (напр. 32.97 THB за 1 USDT)\n- `rate_local` — курс ₽ за 1 единицу локальной валюты\n- `amount_local` — сумма в локальной валюте\n- `profit_local` — прибыль в локальной валюте\n\n## Примечания\n\n- **`commission`** — комиссия кассы: во всех запросах и ответах используйте `commission`. Легаси-написание `comission` (одна «m», историческая опечатка) продолжает приниматься и возвращаться для существующих интеграций, но в новых используйте `commission`.\n- **`amount_rub`** — число с максимум **2 знаками после точки**; значения с большей точностью округляются до 2 знаков. Рекомендуем на своей стороне хранить суммы в копейках (integer) и конвертировать на границе.\n- **Версионирование.** Обратно несовместимые изменения ответов/поведения не вносятся без смены версии API. Изменения документации отражаются в `info.version`.\n"},"servers":[{"url":"https://rubrek.com/api","description":"Production"}],"security":[{"http":[]}],"paths":{"/v1/acquiring/orders":{"post":{"operationId":"createAcquiringOrder","description":"Создаёт заказ на оплату через эквайринг и возвращает ссылку на страницу оплаты.\nУ мерчанта должен быть включён эквайринг и указан кошелёк TRC-20 для получения выплат.\n\n**Тестовый режим (`rbk_test_`):** заказ НЕ сохраняется в базу. Возвращается\nреалистичный ответ с полями `_sandbox`, `order.id = 0` и рассчитанной комиссией\n(`acquiring_commission_percent`, `acquiring_commission_rub`, `acquiring_net_rub`).\n\nПример ответа (201):\n```json\n{\n  \"order\": {\n    \"id\": 100,\n    \"order_number\": \"ACQ-AB12CD34\",\n    \"amount_rub\": 1500.00,\n    \"status\": \"pending\",\n    \"payment_reference\": \"550e8400-e29b-41d4-a716-446655440000\",\n    \"created_at\": \"2026-04-19T12:00:00.000000Z\"\n  },\n  \"payment_url\": \"https://pay.example.com/invoice/abc123\"\n}\n```\nОшибка 403: `{\"error\": \"Acquiring is not enabled for this merchant\"}`\nОшибка 422: `{\"error\": \"TRC-20 wallet address is required to create acquiring orders\"}`\nОшибка 500: `{\"error\": \"Payment creation failed: ...\"}`\n\nУспешный ответ приходит с HTTP-кодом **201** (в спецификации показан как 200 — ограничение генератора).","summary":"Создать заказ эквайринга","tags":["Acquiring","AcquiringExternalApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount_rub":{"type":"number","minimum":10,"maximum":999999.99},"description":{"type":["string","null"],"maxLength":255},"success_url":{"type":["string","null"],"format":"uri","maxLength":500},"fail_url":{"type":["string","null"],"format":"uri","maxLength":500}},"required":["amount_rub"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"order_number":{"type":"string"},"amount_rub":{"type":"number"},"status":{"type":"string"},"payment_reference":{"type":"string"},"created_at":{"type":"string"}},"required":["id","order_number","amount_rub","status","payment_reference","created_at"]},"payment_url":{"type":["string","null"]}},"required":["order","payment_url"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}},"get":{"operationId":"listAcquiringOrders","description":"Возвращает список заказов эквайринга мерчанта с пагинацией.\nВключает данные о комиссии и чистой сумме к зачислению.\n\nПример ответа (200):\n```json\n{\n  \"data\": [\n    {\n      \"id\": 100,\n      \"order_number\": \"ACQ-AB12CD34\",\n      \"status\": \"paid\",\n      \"amount_rub\": 1500.00,\n      \"acquiring_commission_percent\": 7.50,\n      \"acquiring_commission_rub\": 112.50,\n      \"acquiring_net_rub\": 1387.50,\n      \"payment_reference\": \"550e8400-e29b-41d4-a716-446655440000\",\n      \"created_at\": \"2026-04-19T12:00:00.000000Z\",\n      \"updated_at\": \"2026-04-19T12:05:00.000000Z\"\n    }\n  ],\n  \"pagination\": {\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"per_page\": 25,\n    \"total\": 1\n  }\n}\n```\nОшибка 403: `{\"error\": \"Acquiring is not enabled for this merchant\"}`","summary":"Список заказов эквайринга","tags":["Acquiring","AcquiringExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"payment_reference":{"type":"string"},"acquiring_commission_percent":{"type":["number","null"]},"acquiring_commission_rub":{"type":["number","null"]},"acquiring_net_rub":{"type":["number","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","global_id","order_number","status","amount_rub","payment_reference","acquiring_commission_percent","acquiring_commission_rub","acquiring_net_rub","created_at","updated_at"]}},"pagination":{"type":"object","properties":{"current_page":{"type":"integer"},"last_page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"required":["current_page","last_page","per_page","total"]}},"required":["data","pagination"]}}}}}}},"/v1/acquiring/orders/{id}":{"get":{"operationId":"showAcquiringOrder","description":"Возвращает полную информацию о заказе эквайринга по ID.\n\nПример ответа (200):\n```json\n{\n  \"order\": {\n    \"id\": 100,\n    \"order_number\": \"ACQ-AB12CD34\",\n    \"status\": \"paid\",\n    \"amount_rub\": 1500.00,\n    \"acquiring_commission_percent\": 7.50,\n    \"acquiring_commission_rub\": 112.50,\n    \"acquiring_net_rub\": 1387.50,\n    \"payment_reference\": \"550e8400-e29b-41d4-a716-446655440000\",\n    \"created_at\": \"2026-04-19T12:00:00.000000Z\",\n    \"updated_at\": \"2026-04-19T12:05:00.000000Z\"\n  }\n}\n```\nОшибка 403: `{\"error\": \"Acquiring is not enabled for this merchant\"}`\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Детали заказа эквайринга","tags":["Acquiring","AcquiringExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"payment_reference":{"type":"string"},"acquiring_commission_percent":{"type":["number","null"]},"acquiring_commission_rub":{"type":["number","null"]},"acquiring_net_rub":{"type":["number","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","global_id","order_number","status","amount_rub","payment_reference","acquiring_commission_percent","acquiring_commission_rub","acquiring_net_rub","created_at","updated_at"]}},"required":["order"]}}}}}}},"/v1/acquiring/balance":{"get":{"operationId":"getAcquiringBalance","description":"Возвращает текущий баланс эквайринга мерчанта в рублях.\n- `pending` — ожидает расчёта (T+N дней)\n- `available` — доступно для выплаты\n- `settlement_days` — расчётный период T+N\n\nПример ответа (200):\n```json\n{\n  \"balance\": {\n    \"pending\": 5000.00,\n    \"available\": 12500.00,\n    \"currency\": \"RUB\"\n  },\n  \"settlement_days\": 3\n}\n```\nОшибка 403: `{\"error\": \"Acquiring is not enabled for this merchant\"}`","summary":"Баланс эквайринга","tags":["Acquiring","AcquiringExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"balance":{"type":"object","properties":{"pending":{"type":"number"},"available":{"type":"number"},"currency":{"type":"string"}},"required":["pending","available","currency"]},"settlement_days":{"type":"integer"}},"required":["balance","settlement_days"]}}}}}}},"/v1/acquiring/payouts":{"get":{"operationId":"listAcquiringPayouts","description":"Возвращает список выплат в USDT (TRC-20) мерчанту.\nВыплаты создаются автоматически по расчётному периоду.\n\nПример ответа (200):\n```json\n{\n  \"data\": [\n    {\n      \"id\": 10,\n      \"status\": \"completed\",\n      \"amount_rub\": 12500.00,\n      \"amount_usdt\": 148.81,\n      \"rate\": 84.00,\n      \"tx_hash\": \"abc123def456...\",\n      \"usdt_network\": \"TRC-20\",\n      \"created_at\": \"2026-04-19T14:00:00.000000Z\",\n      \"processed_at\": \"2026-04-19T14:05:00.000000Z\"\n    }\n  ],\n  \"pagination\": {\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"per_page\": 25,\n    \"total\": 1\n  }\n}\n```\nОшибка 403: `{\"error\": \"Acquiring is not enabled for this merchant\"}`","summary":"История выплат","tags":["Acquiring","AcquiringExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":["number","null"]},"rate":{"type":["number","null"]},"tx_hash":{"type":["string","null"]},"usdt_network":{"type":["string","null"]},"created_at":{"type":"string"},"processed_at":{"type":["string","null"]}},"required":["id","status","amount_rub","amount_usdt","rate","tx_hash","usdt_network","created_at","processed_at"]}},"pagination":{"type":"object","properties":{"current_page":{"type":"integer"},"last_page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"required":["current_page","last_page","per_page","total"]}},"required":["data","pagination"]}}}}}}},"/v1/orders":{"get":{"operationId":"listOrders","description":"Возвращает список заказов мерчанта с пагинацией. Отсортирован по дате создания (новые первыми).\nМаксимум 100 записей на страницу. Тестовый ключ возвращает только тестовые заказы.\n\n\n\n\nПример ответа (200):\n```json\n{\n  \"data\": [\n    {\n      \"id\": 42,\n      \"global_id\": \"RB-000042\",\n      \"order_number\": \"RB-000042\",\n      \"status\": \"paid\",\n      \"amount_rub\": 5000.00,\n      \"amount_usdt\": 59.70,\n      \"rate_usdt\": 83.75,\n      \"local_currency_code\": \"THB\",\n      \"amount_local\": 1967.23,\n      \"rate_local\": 2.54,\n      \"rate_local_per_usdt\": 32.97,\n      \"profit_usdt\": 0.60,\n      \"profit_local\": 19.80,\n      \"payment_reference\": \"ABCDEF1234567890\",\n      \"client_name\": \"Иван Петров\",\n      \"kyc_type\": \"unverified\",\n      \"kyc_status\": \"pending\",\n      \"point_id\": 1,\n      \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n      \"updated_at\": \"2026-03-30T12:01:00.000000Z\",\n      \"point\": {\"id\": 1, \"name\": \"Основная\", \"account\": \"THB\"}\n}\n```\n  ],\n  \"pagination\": {\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"per_page\": 25,\n    \"total\": 1\n  }\n}","summary":"Список заказов","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":["number","null"]},"rate_usdt":{"type":["number","null"]},"base_rate_usdt":{"type":["number","null"]},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"external_id":{"type":["string","null"]},"client_name":{"type":["string","null"]},"kyc_type":{"type":"string"},"kyc_status":{"type":["string","null"]},"payment_qr":{"type":["string","null"]},"payment_qr_link":{"type":["string","null"]},"commission_override":{"type":["number","null"]},"point_id":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"point":{"type":["object","null"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]}},"required":["id","name","account","commission","commission_local"]},"payment_url":{"type":["string","null"]}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","rate_usdt","base_rate_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_usdt","profit_local","payment_reference","external_id","client_name","kyc_type","kyc_status","payment_qr","payment_qr_link","commission_override","point_id","created_at","updated_at","point","payment_url"]}},"pagination":{"type":"object","properties":{"current_page":{"type":"integer"},"last_page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"required":["current_page","last_page","per_page","total"]}},"required":["data","pagination"]}}}}}},"post":{"operationId":"createOrder","description":"Создаёт новый платёж. Возвращает данные заказа и ссылку на страницу оплаты (`payment_url`),\nкоторую нужно отправить клиенту. Курс фиксируется в момент создания.\n\n**KYC:** Параметр `kyc_type` определяет верификацию клиента:\n- `unverified` (по умолчанию) — клиент пройдет верификацию на странице оплаты.\n- `verified` — мерчант сам загружает KYC-документы клиента через multipart/form-data\n  (`file_selfie`, `file_document`, `file_address`). До проверки документов средства\n  будут в статусе HOLD.\n\n**Повторные клиенты — документы загружаются один раз.** Передайте ключ клиента:\n`client_external_id` (ваш идентификатор, рекомендуется) или `client_phone`.\nПервый заказ клиента — ключ + документы; все следующие — только ключ, без файлов:\nзаказ привяжется к клиенту и его документам автоматически. Проверить клиента заранее:\n`GET /api/v1/clients/{key}`. Без ключа документы к базе клиентов не привязываются,\nи каждый заказ проверяется отдельно.\n\nЕсли у мерчанта отключен KYC (`require_kyc = false`), значение `kyc_type` игнорируется.\n\n**Мерчанты с встроенной верификацией:** этот эндпоинт недоступен. Используйте\nотдельный раздел — `POST /api/v1/registered/orders` (см. Registered Clients).\n\n**Тестовый режим (rbk_test_):** заказ сохраняется в **песочницу** (жизнь — 48 часов,\nпрод-база не затрагивается) с реальным тестовым `id`. Доступен весь цикл:\nreadback (`GET /orders/{id}`, `by-reference`, `by-external-id`), симуляция оплаты\n(`POST /orders/{id}/simulate-payment`) с настоящим вебхуком `order.paid`\n(`is_test: true`) и повторный readback со статусом `paid`. Идемпотентность по\n`external_id` работает и в песочнице. В ответе — поле `_sandbox` и `is_test: true`.\n\nЕсли касса привязана к локальной валюте (например THB), в ответе будут заполнены поля\n`local_currency_code`, `amount_local`, `rate_local`, `rate_local_per_usdt`, `profit_local`.\n\n\n\nПример ответа (201):\n```json\n{\n  \"order\": {\n    \"id\": 42,\n    \"global_id\": \"RB-000042\",\n    \"order_number\": \"RB-000042\",\n    \"status\": \"pending\",\n    \"amount_rub\": 5000.00,\n    \"amount_usdt\": 59.70,\n    \"local_currency_code\": \"THB\",\n    \"amount_local\": 1967.23,\n    \"rate_local\": 2.54,\n    \"rate_local_per_usdt\": 32.97,\n    \"profit_local\": 19.80,\n    \"payment_reference\": \"ABCDEF1234567890\",\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\"\n  },\n  \"payment_url\": \"https://pay.rubrek.com/pay/ABCDEF1234567890\"\n}\n```\n**Идемпотентность (два уровня):**\n- Заголовок `Idempotency-Key` (рекомендуется UUID) — технический ключ одного POST create.\n  Повтор с тем же ключом и тем же payload возвращает исходный заказ: HTTP 200,\n  заголовок `Idempotent-Replayed: true`, тот же `payment_url` и `payment_reference`.\n  Тот же ключ с другим payload — 409 `idempotency_key_conflict`. Параллельный повтор,\n  пока первый запрос ещё выполняется, — 409 `idempotency_in_flight` (повторите через\n  пару секунд). Ключ хранится 24 часа.\n- Поле `external_id` — идентификатор платёжной попытки в вашей системе (см. описание поля).\n\nОшибка 404: `{\"message\": \"Not found.\"}`\nОшибка 409: `{\"error\": \"idempotency_conflict\", \"message\": \"…\", \"existing_order_id\": 123}` — external_id переиспользован с другими параметрами; `{\"error\": \"idempotency_key_conflict\"}` — Idempotency-Key переиспользован с другим payload; `{\"error\": \"idempotency_in_flight\"}` — исходный запрос ещё выполняется\nОшибка 422: `{\"message\": \"The point id field is required.\", \"errors\": {\"point_id\": [\"The point id field is required.\"]}}`\nОшибка 429: `{\"error\": \"Слишком много запросов, повторите позже\"}`\nОшибка 503: `{\"error\": \"Не удалось получить курс. Попробуйте позже.\"}`\n\nУспешный ответ приходит с HTTP-кодом **201** (в спецификации показан как 200 — ограничение генератора).","summary":"Создать платёж","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Технический ключ идемпотентности одного POST create (рекомендуется UUID). Повтор с тем же ключом и тем же payload вернёт исходный заказ (200 + заголовок Idempotent-Replayed: true); тот же ключ с другим payload — 409. Хранится 24 часа. Работает и с тестовым ключом rbk_test_.","schema":{"type":"string"},"example":"7f9c24e5-a1b2-4c3d-9e8f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"point_id":{"type":"integer"},"amount_rub":{"type":"number","minimum":1},"client_name":{"type":["string","null"],"maxLength":255},"kyc_type":{"type":["string","null"],"enum":["verified","unverified"]},"client_phone":{"type":["string","null"],"maxLength":50},"client_external_id":{"type":["string","null"],"description":"Ваш идентификатор клиента (уникален в рамках мерчанта). Альтернатива\nclient_phone: привязывает заказ к клиенту в вашей нумерации — документы\nдостаточно загрузить при первом заказе клиента.","maxLength":64},"external_id":{"type":["string","null"],"description":"Идентификатор ПЛАТЁЖНОЙ ПОПЫТКИ в вашей системе (уникален в рамках\nмерчанта; новый QR на тот же заказ = новый external_id). Идемпотентность:\nповтор с тем же external_id и теми же параметрами вернёт уже созданный\nзаказ (HTTP 200 + idempotent_replay: true) вместо дубля; тот же\nexternal_id с другой суммой/кассой — 409 idempotency_conflict.\nТехнический ключ ретрая одного POST — заголовок Idempotency-Key (см. описание метода).","maxLength":64},"commission_override":{"type":["number","null"],"description":"Переопределение наценки кассы для этого заказа, % (0–100).\nОпционально: если не передано — используется наценка кассы (comission).","minimum":0,"maximum":100}},"required":["point_id","amount_rub"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":"number"},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"external_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_local","payment_reference","external_id","created_at"]},"payment_url":{"type":"string"}},"required":["order","payment_url"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/orders/{id}":{"get":{"operationId":"showOrder","description":"Возвращает полную информацию о заказе по его числовому ID.\n\n\n\nПример ответа (200):\n```json\n{\n  \"order\": {\n    \"id\": 42,\n    \"global_id\": \"RB-000042\",\n    \"order_number\": \"RB-000042\",\n    \"status\": \"paid\",\n    \"amount_rub\": 5000.00,\n    \"amount_usdt\": 59.70,\n    \"rate_usdt\": 83.75,\n    \"local_currency_code\": \"THB\",\n    \"amount_local\": 1967.23,\n    \"rate_local\": 2.54,\n    \"rate_local_per_usdt\": 32.97,\n    \"profit_usdt\": 0.60,\n    \"profit_local\": 19.80,\n    \"payment_reference\": \"ABCDEF1234567890\",\n    \"client_name\": \"Иван Петров\",\n    \"kyc_type\": \"verified\",\n    \"kyc_status\": \"approved\",\n    \"point_id\": 1,\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n    \"updated_at\": \"2026-03-30T12:01:00.000000Z\",\n    \"point\": {\"id\": 1, \"name\": \"Основная\", \"account\": \"THB\"}\n}\n```\n}\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Детали заказа по ID","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":["number","null"]},"rate_usdt":{"type":["number","null"]},"base_rate_usdt":{"type":["number","null"]},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"external_id":{"type":["string","null"]},"client_name":{"type":["string","null"]},"kyc_type":{"type":"string"},"kyc_status":{"type":["string","null"]},"payment_qr":{"type":["string","null"]},"payment_qr_link":{"type":["string","null"]},"commission_override":{"type":["number","null"]},"point_id":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"point":{"type":["object","null"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]}},"required":["id","name","account","commission","commission_local"]}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","rate_usdt","base_rate_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_usdt","profit_local","payment_reference","external_id","client_name","kyc_type","kyc_status","payment_qr","payment_qr_link","commission_override","point_id","created_at","updated_at","point"]},"payment_url":{"type":["string","null"]}},"required":["order","payment_url"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"}}}},"/v1/orders/by-reference/{reference}":{"get":{"operationId":"showOrderByReference","description":"Поиск заказа по уникальному коду payment_reference. Удобно для проверки статуса оплаты по callback.\n\n\n\nПример ответа (200):\n```json\n{\n  \"order\": {\n    \"id\": 42,\n    \"global_id\": \"RB-000042\",\n    \"order_number\": \"RB-000042\",\n    \"status\": \"paid\",\n    \"amount_rub\": 5000.00,\n    \"amount_usdt\": 59.70,\n    \"rate_usdt\": 83.75,\n    \"local_currency_code\": \"THB\",\n    \"amount_local\": 1967.23,\n    \"rate_local\": 2.54,\n    \"rate_local_per_usdt\": 32.97,\n    \"profit_usdt\": 0.60,\n    \"profit_local\": 19.80,\n    \"payment_reference\": \"ABCDEF1234567890\",\n    \"client_name\": \"Иван Петров\",\n    \"kyc_type\": \"unverified\",\n    \"kyc_status\": \"pending\",\n    \"point_id\": 1,\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n    \"updated_at\": \"2026-03-30T12:01:00.000000Z\",\n    \"point\": {\"id\": 1, \"name\": \"Основная\", \"account\": \"THB\"}\n}\n```\n}\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Заказ по payment_reference","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"reference","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":["number","null"]},"rate_usdt":{"type":["number","null"]},"base_rate_usdt":{"type":["number","null"]},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"external_id":{"type":["string","null"]},"client_name":{"type":["string","null"]},"kyc_type":{"type":"string"},"kyc_status":{"type":["string","null"]},"payment_qr":{"type":["string","null"]},"payment_qr_link":{"type":["string","null"]},"commission_override":{"type":["number","null"]},"point_id":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"point":{"type":["object","null"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]}},"required":["id","name","account","commission","commission_local"]}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","rate_usdt","base_rate_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_usdt","profit_local","payment_reference","external_id","client_name","kyc_type","kyc_status","payment_qr","payment_qr_link","commission_override","point_id","created_at","updated_at","point"]},"payment_url":{"type":["string","null"]}},"required":["order","payment_url"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"}}}},"/v1/orders/by-external-id/{externalId}":{"get":{"operationId":"showOrderByExternalId","description":"Возвращает заказ по вашему merchant-side идентификатору (`external_id`,\nпереданному при создании). Используйте для поиска «потерянного» заказа,\nесли ответ на создание не дошёл (таймаут).\n\nОшибка 404: `{\"message\": \"Resource not found.\"}`","summary":"Получить заказ по external_id","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"externalId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":["number","null"]},"rate_usdt":{"type":["number","null"]},"base_rate_usdt":{"type":["number","null"]},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"external_id":{"type":["string","null"]},"client_name":{"type":["string","null"]},"kyc_type":{"type":"string"},"kyc_status":{"type":["string","null"]},"payment_qr":{"type":["string","null"]},"payment_qr_link":{"type":["string","null"]},"commission_override":{"type":["number","null"]},"point_id":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"point":{"type":["object","null"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]}},"required":["id","name","account","commission","commission_local"]}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","rate_usdt","base_rate_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_usdt","profit_local","payment_reference","external_id","client_name","kyc_type","kyc_status","payment_qr","payment_qr_link","commission_override","point_id","created_at","updated_at","point"]},"payment_url":{"type":["string","null"]}},"required":["order","payment_url"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"}}}},"/v1/points":{"get":{"operationId":"listPoints","description":"Возвращает все кассы мерчанта с их настройками.\nПоле `account` — валюта кассы (USDT, THB, INR и т.д.).\nПоле `comission` — наценка кассы в процентах.\n\n\n\nПример ответа (200):\n```json\n{\n  \"points\": [\n    {\"id\": 1, \"name\": \"Основная\", \"account\": \"USDT\", \"commission\": 0, \"type\": \"online\", \"is_active\": true, \"permanent_link\": false},\n    {\"id\": 2, \"name\": \"THB касса\", \"account\": \"THB\", \"commission\": 2, \"type\": \"online\", \"is_active\": true, \"permanent_link\": true}\n  ]\n}\n```","summary":"Список касс","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"points":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"type":{"type":"string"},"is_active":{"type":"boolean"},"is_offline":{"type":"boolean"},"permanent_link":{"type":"boolean"},"kyc_mode":{"type":"string"},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]},"color_scheme":{"type":["string","null"]},"logo_path":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"logo_size":{"type":["integer","null"]},"show_name":{"type":"boolean"},"hide_currency":{"type":"boolean"},"hide_rate":{"type":"boolean"},"traffic_type":{"type":["string","null"]},"address":{"type":["string","null"]},"min_balance_threshold":{"type":["number","null"]},"qr_code":{"type":["string","null"]},"enable_telegram":{"type":"boolean"},"notify_created":{"type":"boolean"},"notify_paid":{"type":"boolean"},"notify_expired":{"type":"boolean"},"notify_error":{"type":"boolean"},"require_email":{"type":"boolean"},"email_prompt_text":{"type":["string","null"]},"require_name":{"type":"boolean"},"name_prompt_text":{"type":["string","null"]},"fixed_amount_rub":{"type":["number","null"]},"fixed_amount_usdt":{"type":["number","null"]},"payment_reference":{"type":["string","null"]},"payment_url":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","account","type","is_active","is_offline","permanent_link","kyc_mode","commission","commission_local","color_scheme","logo_path","logo_url","logo_size","show_name","hide_currency","hide_rate","traffic_type","address","min_balance_threshold","qr_code","enable_telegram","notify_created","notify_paid","notify_expired","notify_error","require_email","email_prompt_text","require_name","name_prompt_text","fixed_amount_rub","fixed_amount_usdt","payment_reference","payment_url","created_at","updated_at"]}}},"required":["points"]}}}}}},"post":{"operationId":"createPoint","description":"Создаёт новую онлайн-кассу для мерчанта.\nПоле `account` определяет валюту расчёта: USDT (по умолчанию), THB, INR и т.д.\nПоле `comission` — наценка кассы в процентах (0-100).\n\n\n\nПример ответа (201):\n```json\n{\n  \"point\": {\n    \"id\": 3,\n    \"name\": \"Новая касса\",\n    \"account\": \"THB\",\n    \"type\": \"online\",\n    \"commission\": 2,\n    \"color_scheme\": \"#4e73df\",\n    \"logo_path\": null,\n    \"is_active\": true,\n    \"permanent_link\": false,\n    \"is_offline\": false,\n    \"show_name\": true,\n    \"hide_currency\": false,\n    \"hide_rate\": false,\n    \"traffic_type\": null,\n    \"payment_reference\": \"ABCDEF123456\",\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n    \"updated_at\": \"2026-03-30T12:00:00.000000Z\"\n}\n```\n}\nОшибка 422: `{\"message\": \"The name field is required.\", \"errors\": {\"name\": [\"The name field is required.\"]}}`\n\nУспешный ответ приходит с HTTP-кодом **201** (в спецификации показан как 200 — ограничение генератора).","summary":"Создать кассу","tags":["Merchant API","MerchantExternalApi"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"account":{"type":["string","null"],"maxLength":10},"commission":{"type":["number","null"],"description":"Комиссия кассы, % (0–100). Легаси-написание comission также принимается.","minimum":0,"maximum":100},"commission_local":{"type":["number","null"],"minimum":0,"maximum":100},"color_scheme":{"type":["string","null"],"maxLength":50},"logo":{"type":["string","null"],"format":"binary","contentMediaType":"application/octet-stream","maxLength":2048},"logo_size":{"type":["integer","null"],"minimum":20,"maximum":100},"show_name":{"type":["boolean","null"]},"hide_currency":{"type":["boolean","null"]},"hide_rate":{"type":["boolean","null"]},"is_offline":{"type":["boolean","null"]},"permanent_link":{"type":["boolean","null"]},"kyc_mode":{"type":["string","null"],"enum":["verified","unverified"]},"is_active":{"type":["boolean","null"]},"address":{"type":["string","null"],"maxLength":255},"min_balance_threshold":{"type":["number","null"],"minimum":0},"qr_code":{"type":["string","null"],"maxLength":255},"enable_telegram":{"type":["boolean","null"]},"notify_created":{"type":["boolean","null"]},"notify_paid":{"type":["boolean","null"]},"notify_expired":{"type":["boolean","null"]},"notify_error":{"type":["boolean","null"]},"traffic_type":{"type":"string"},"require_email":{"type":["boolean","null"],"description":"Поля постоянной ссылки (применяются, когда permanent_link=true)."},"email_prompt_text":{"type":["string","null"],"maxLength":500},"require_name":{"type":["boolean","null"]},"name_prompt_text":{"type":["string","null"],"maxLength":500},"fixed_amount_rub":{"type":["number","null"],"minimum":0},"fixed_amount_usdt":{"type":["number","null"],"minimum":0}},"required":["name"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"point":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"type":{"type":"string"},"is_active":{"type":"boolean"},"is_offline":{"type":"boolean"},"permanent_link":{"type":"boolean"},"kyc_mode":{"type":"string"},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]},"color_scheme":{"type":["string","null"]},"logo_path":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"logo_size":{"type":["integer","null"]},"show_name":{"type":"boolean"},"hide_currency":{"type":"boolean"},"hide_rate":{"type":"boolean"},"traffic_type":{"type":["string","null"]},"address":{"type":["string","null"]},"min_balance_threshold":{"type":["number","null"]},"qr_code":{"type":["string","null"]},"enable_telegram":{"type":"boolean"},"notify_created":{"type":"boolean"},"notify_paid":{"type":"boolean"},"notify_expired":{"type":"boolean"},"notify_error":{"type":"boolean"},"require_email":{"type":"boolean"},"email_prompt_text":{"type":["string","null"]},"require_name":{"type":"boolean"},"name_prompt_text":{"type":["string","null"]},"fixed_amount_rub":{"type":["number","null"]},"fixed_amount_usdt":{"type":["number","null"]},"payment_reference":{"type":["string","null"]},"payment_url":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","account","type","is_active","is_offline","permanent_link","kyc_mode","commission","commission_local","color_scheme","logo_path","logo_url","logo_size","show_name","hide_currency","hide_rate","traffic_type","address","min_balance_threshold","qr_code","enable_telegram","notify_created","notify_paid","notify_expired","notify_error","require_email","email_prompt_text","require_name","name_prompt_text","fixed_amount_rub","fixed_amount_usdt","payment_reference","payment_url","created_at","updated_at"]}},"required":["point"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/points/{id}":{"get":{"operationId":"showPoint","description":"Возвращает полные настройки кассы, включая абсолютную ссылку на логотип\n(`logo_url`), traffic_type, флаги отображения, KYC-режим и т.д.\n\n\n\nПример ответа (200):\n```json\n{\n  \"point\": {\n    \"id\": 3,\n    \"name\": \"Касса 1\",\n    \"account\": \"USDT\",\n    \"is_active\": true,\n    \"logo_url\": \"https://rubrek.com/storage/point-logos/abc.webp\",\n    \"commission\": 2.5,\n    \"payment_url\": \"https://rubrek.com/pay/ABC123\"\n}\n```\n}\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Получить кассу по ID","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"point":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"type":{"type":"string"},"is_active":{"type":"boolean"},"is_offline":{"type":"boolean"},"permanent_link":{"type":"boolean"},"kyc_mode":{"type":"string"},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]},"color_scheme":{"type":["string","null"]},"logo_path":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"logo_size":{"type":["integer","null"]},"show_name":{"type":"boolean"},"hide_currency":{"type":"boolean"},"hide_rate":{"type":"boolean"},"traffic_type":{"type":["string","null"]},"address":{"type":["string","null"]},"min_balance_threshold":{"type":["number","null"]},"qr_code":{"type":["string","null"]},"enable_telegram":{"type":"boolean"},"notify_created":{"type":"boolean"},"notify_paid":{"type":"boolean"},"notify_expired":{"type":"boolean"},"notify_error":{"type":"boolean"},"require_email":{"type":"boolean"},"email_prompt_text":{"type":["string","null"]},"require_name":{"type":"boolean"},"name_prompt_text":{"type":["string","null"]},"fixed_amount_rub":{"type":["number","null"]},"fixed_amount_usdt":{"type":["number","null"]},"payment_reference":{"type":["string","null"]},"payment_url":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","account","type","is_active","is_offline","permanent_link","kyc_mode","commission","commission_local","color_scheme","logo_path","logo_url","logo_size","show_name","hide_currency","hide_rate","traffic_type","address","min_balance_threshold","qr_code","enable_telegram","notify_created","notify_paid","notify_expired","notify_error","require_email","email_prompt_text","require_name","name_prompt_text","fixed_amount_rub","fixed_amount_usdt","payment_reference","payment_url","created_at","updated_at"]}},"required":["point"]}}}}}},"put":{"operationId":"updatePoint","description":"Обновляет настройки существующей кассы. Передайте только те поля, которые нужно изменить.\n\n\n\nПример ответа (200):\n```json\n{\n  \"point\": {\n    \"id\": 3,\n    \"name\": \"Обновлённая касса\",\n    \"account\": \"THB\",\n    \"type\": \"online\",\n    \"commission\": 5,\n    \"color_scheme\": \"#4e73df\",\n    \"logo_path\": null,\n    \"is_active\": true,\n    \"permanent_link\": false,\n    \"is_offline\": false,\n    \"show_name\": true,\n    \"hide_currency\": false,\n    \"hide_rate\": false,\n    \"traffic_type\": null,\n    \"payment_reference\": \"ABCDEF123456\",\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n    \"updated_at\": \"2026-03-30T12:05:00.000000Z\"\n}\n```\n}\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Обновить кассу","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":255},"account":{"type":["string","null"],"maxLength":10},"commission":{"type":["number","null"],"description":"Комиссия кассы, % (0–100). Легаси-написание comission также принимается.","minimum":0,"maximum":100},"commission_local":{"type":["number","null"],"minimum":0,"maximum":100},"color_scheme":{"type":["string","null"],"maxLength":50},"logo":{"type":["string","null"],"format":"binary","contentMediaType":"application/octet-stream","maxLength":2048},"logo_size":{"type":["integer","null"],"minimum":20,"maximum":100},"remove_logo":{"type":["boolean","null"]},"is_active":{"type":["boolean","null"]},"is_offline":{"type":["boolean","null"]},"permanent_link":{"type":["boolean","null"]},"kyc_mode":{"type":["string","null"],"enum":["verified","unverified"]},"show_name":{"type":["boolean","null"]},"hide_currency":{"type":["boolean","null"]},"hide_rate":{"type":["boolean","null"]},"address":{"type":["string","null"],"maxLength":255},"min_balance_threshold":{"type":["number","null"],"minimum":0},"qr_code":{"type":["string","null"],"maxLength":255},"enable_telegram":{"type":["boolean","null"]},"notify_created":{"type":["boolean","null"]},"notify_paid":{"type":["boolean","null"]},"notify_expired":{"type":["boolean","null"]},"notify_error":{"type":["boolean","null"]},"traffic_type":{"type":"string"},"require_email":{"type":["boolean","null"],"description":"Поля постоянной ссылки. Ключ не передан — значение не меняется;\nпередан null/false — значение сбрасывается."},"email_prompt_text":{"type":["string","null"],"maxLength":500},"require_name":{"type":["boolean","null"]},"name_prompt_text":{"type":["string","null"],"maxLength":500},"fixed_amount_rub":{"type":["number","null"],"minimum":0},"fixed_amount_usdt":{"type":["number","null"],"minimum":0},"comission":{"type":"string"},"comission_local":{"type":"string"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"point":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"account":{"type":["string","null"]},"type":{"type":"string"},"is_active":{"type":"boolean"},"is_offline":{"type":"boolean"},"permanent_link":{"type":"boolean"},"kyc_mode":{"type":"string"},"commission":{"type":["number","null"]},"commission_local":{"type":["number","null"]},"color_scheme":{"type":["string","null"]},"logo_path":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"logo_size":{"type":["integer","null"]},"show_name":{"type":"boolean"},"hide_currency":{"type":"boolean"},"hide_rate":{"type":"boolean"},"traffic_type":{"type":["string","null"]},"address":{"type":["string","null"]},"min_balance_threshold":{"type":["number","null"]},"qr_code":{"type":["string","null"]},"enable_telegram":{"type":"boolean"},"notify_created":{"type":"boolean"},"notify_paid":{"type":"boolean"},"notify_expired":{"type":"boolean"},"notify_error":{"type":"boolean"},"require_email":{"type":"boolean"},"email_prompt_text":{"type":["string","null"]},"require_name":{"type":"boolean"},"name_prompt_text":{"type":["string","null"]},"fixed_amount_rub":{"type":["number","null"]},"fixed_amount_usdt":{"type":["number","null"]},"payment_reference":{"type":["string","null"]},"payment_url":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","account","type","is_active","is_offline","permanent_link","kyc_mode","commission","commission_local","color_scheme","logo_path","logo_url","logo_size","show_name","hide_currency","hide_rate","traffic_type","address","min_balance_threshold","qr_code","enable_telegram","notify_created","notify_paid","notify_expired","notify_error","require_email","email_prompt_text","require_name","name_prompt_text","fixed_amount_rub","fixed_amount_usdt","payment_reference","payment_url","created_at","updated_at"]}},"required":["point"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/rates":{"get":{"operationId":"getRates","description":"Возвращает актуальные курсы обмена с учётом комиссии мерчанта.\nКурсы обновляются каждые 30 секунд.\n\nЕсли у мерчанта есть кассы с локальными валютами, в `local_rates` будут курсы\nэтих валют к USDT и к рублю.\n\n\n\nПример ответа (200):\n```json\n{\n  \"rub_per_usdt\": 83.753,\n  \"updated_at\": \"2026-03-30T12:00:00+00:00\",\n  \"local_rates\": {\n    \"THB\": {\n      \"symbol\": \"฿\",\n      \"per_usdt\": 32.97,\n      \"rub_per_unit\": 2.540,\n      \"units_per_rub\": 0.3937\n}\n```\n  }\n}","summary":"Текущие курсы","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"point_id","in":"query","schema":{"type":"string"}},{"name":"kyc_type","in":"query","description":"Если включён kyc_dependent_markup — клиент может передать ?kyc_type=verified|unverified","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"rub_per_usdt":{"type":"number"},"updated_at":{"type":"string"},"kyc_dependent_markup":{"type":"boolean"},"local_rates":{"type":"object","additionalProperties":{"type":"object","properties":{"symbol":{"type":["string","null"]},"per_usdt":{"type":"number"},"rub_per_unit":{"type":"number"},"units_per_rub":{"type":"number"}},"required":["symbol","per_usdt","rub_per_unit","units_per_rub"]}}},"required":["rub_per_usdt","updated_at","kyc_dependent_markup","local_rates"]}}}}}}},"/v1/balance":{"get":{"operationId":"getBalance","description":"Текущий баланс мерчанта по всем валютам.\n- `available` — доступно для вывода\n- `hold` — на удержании (ожидает подтверждения)\n\n\n\nПример ответа (200):\n```json\n{\n  \"balances\": {\n    \"usdt\": {\"available\": 1250.50, \"hold\": 120.00},\n    \"thb\": {\"available\": 35000.00, \"hold\": 0.00}\n}\n```\n}","summary":"Баланс мерчанта","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"balances":{"type":"object","additionalProperties":{"type":"object","properties":{"available":{"type":"number"},"hold":{"type":"number"}},"required":["available","hold"]}}},"required":["balances"]}}}}}}},"/v1/balance-history":{"get":{"operationId":"balanceHistory","description":"Возвращает последние 500 движений по балансу (deposit / withdrawal /\nrelease_hold и т.п.) — та же история, что в кабинете мерчанта.\n\nОпциональные фильтры: type, from, to (даты YYYY-MM-DD).\n\n\n\nПример ответа (200):\n```json\n{\n  \"data\": [\n    {\"id\": 1, \"global_id\": \"abc\", \"type\": \"deposit\", \"amount\": \"10.00\",\n     \"currency\": \"USDT\", \"after_balance\": \"100.00\",\n     \"comment\": \"Заказ #42\", \"created_at\": \"2026-06-02T12:00:00.000000Z\"}\n  ]\n}\n```","summary":"История изменений баланса мерчанта","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"type":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"after_balance":{"type":["string","null"]},"comment":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","global_id","type","amount","currency","after_balance","comment","created_at"]}}},"required":["data"]}}}}}}},"/v1/traffic-types":{"get":{"operationId":"listTrafficTypes","description":"Возвращает список traffic_type, разрешённых вашему мерчанту администратором.\nИспользуйте `key` из этого списка при создании/обновлении кассы (`traffic_type`).\n\n\n\nПример ответа (200):\n```json\n{\n  \"traffic_types\": [\n    {\"key\": \"exchange\", \"label\": \"Обмен\"},\n    {\"key\": \"retail\",   \"label\": \"Ритейл\"}\n  ]\n}\n```","summary":"Доступные типы трафика","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"traffic_types":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]}}},"required":["traffic_types"]}}}}}}},"/v1/currencies":{"get":{"operationId":"listCurrencies","description":"Возвращает валюты, которые ваш мерчант может использовать в кассах\n(значение поля `account` при создании/обновлении кассы).\n\n\n\nПример ответа (200):\n```json\n{\n  \"currencies\": [\n    {\"code\": \"USDT\", \"name\": \"Tether USD\",  \"symbol\": \"₮\", \"decimals\": 2},\n    {\"code\": \"THB\",  \"name\": \"Thai Baht\",   \"symbol\": \"฿\", \"decimals\": 2}\n  ]\n}\n```","summary":"Доступные валюты касс","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"currencies":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"symbol":{"type":["string","null"]},"decimals":{"type":"integer"}},"required":["code","name","symbol","decimals"]}}},"required":["currencies"]}}}}}}},"/v1/capabilities":{"get":{"operationId":"capabilities","description":"Пример ответа (200):\n```json\n{\n  \"allow_permanent_link\": false,\n  \"allow_offline_points\": false\n}\n```","summary":"Фиче-флаги вашего аккаунта: какие функции доступны по API. Проверяйте их\nперед использованием опций (например, permanent_link при создании кассы —\nесли allow_permanent_link выключен, запрос вернёт 403)","tags":["Merchant API","MerchantExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"allow_permanent_link":{"type":"boolean"},"allow_offline_points":{"type":"boolean"}},"required":["allow_permanent_link","allow_offline_points"]}}}}}}},"/v1/orders/{id}/simulate-payment":{"post":{"operationId":"simulatePayment","description":"Переводит **тестовый заказ из песочницы** в статус `paid` и отправляет\n**настоящий вебхук** `order.paid` (payload помечен `\"is_test\": true`,\nподписи V1/V2 — вашими боевыми секретами подписок). Работает только с\nтестовым ключом (`rbk_test_...`), прод-база не затрагивается.\n\nПолный end-to-end в песочнице: `POST /v1/orders` → readback `pending` →\n`simulate-payment` → вебхук → readback `paid`.\n\nЗаказ должен быть создан этим же тестовым ключом (песочница хранит заказы\n48 часов). Повторная симуляция уже оплаченного заказа идемпотентна —\nвебхук не дублируется. Если активных вебхук-подписок нет,\n`webhooks_queued` будет `0`.\n\n\n\nПример ответа (200):\n```json\n{\n  \"message\": \"Тестовый платёж успешно симулирован\",\n  \"order\": {\n    \"id\": 42,\n    \"global_id\": \"RB-000042\",\n    \"order_number\": \"RB-000042\",\n    \"status\": \"paid\",\n    \"amount_rub\": 5000.00,\n    \"amount_usdt\": 59.70,\n    \"rate_usdt\": 83.75,\n    \"local_currency_code\": \"THB\",\n    \"amount_local\": 1967.23,\n    \"rate_local\": 2.54,\n    \"rate_local_per_usdt\": 32.97,\n    \"profit_usdt\": 0.60,\n    \"profit_local\": 19.80,\n    \"payment_reference\": \"ABCDEF1234567890\",\n    \"client_name\": null,\n    \"kyc_type\": \"unverified\",\n    \"kyc_status\": \"pending\",\n    \"point_id\": 1,\n    \"created_at\": \"2026-03-30T12:00:00.000000Z\",\n    \"updated_at\": \"2026-03-30T12:01:00.000000Z\"\n}\n```\n}\nОшибка 403: `{\"error\": \"Simulate payment доступен только с тестовым ключом (rbk_test_)\"}`\nОшибка 404: `{\"message\": \"Not found.\"}`","summary":"Симуляция оплаты (sandbox)","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":"string"},"order_number":{"type":"string"},"status":{"type":"string"},"is_test":{"type":"boolean"}},"required":["id","global_id","order_number","status","is_test"]},"webhooks_queued":{"type":"integer"},"_sandbox":{"type":"string"}},"required":["message","order","webhooks_queued","_sandbox"]}}}}}}},"/v1/orders/{id}/kyc":{"get":{"operationId":"getOrderKyc","description":"Возвращает статус верификации (KYC) и данные клиента для указанного заказа.\n\nВозможные значения `kyc_type`: `verified` (требуется KYC), `unverified` (KYC не требуется).\n\nВозможные значения `kyc_status`: `pending`, `submitted`, `approved`, `rejected`.\n\n\n\nПример ответа (200):\n```json\n{\n  \"kyc_type\": \"verified\",\n  \"kyc_status\": \"approved\",\n  \"client\": {\n    \"id\": 1,\n    \"first_name\": \"Иван\",\n    \"last_name\": \"Петров\",\n    \"document_type\": \"national_passport\",\n    \"status\": \"verified\"\n}\n```\n}\nОшибка 200: `scenario=\"KYC не требуется\" {`\n     *   \"kyc_type\": \"unverified\",\n     *   \"kyc_status\": \"pending\",\n     *   \"client\": null\n     * }\n     * Ошибка 404: `{\"message\": \"Not found.\"}`","summary":"Статус KYC заказа","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"kyc_type":{"type":"string"},"kyc_status":{"type":"string"},"client":{"type":["object","null"],"properties":{"id":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"document_type":{"type":"string"},"status":{"type":"string"}},"required":["id","first_name","last_name","document_type","status"]}},"required":["kyc_type","kyc_status","client"]}}}}}}},"/v1/clients":{"get":{"operationId":"listClients","description":"Клиенты вашей базы (создаются при заказах с `kyc_type=verified` и ключом\n`client_external_id`/`client_phone`, либо через верификацию на странице оплаты).\n`status=verified` означает, что документы клиента подтверждены — его заказы\nпроходят KYC автоматически, файлы передавать не нужно.\n\nПример ответа (200):\n```json\n{\n  \"data\": [\n    {\n      \"id\": 15,\n      \"external_id\": \"usr-8123\",\n      \"phone\": \"+79161234567\",\n      \"first_name\": \"Иван\",\n      \"last_name\": \"Петров\",\n      \"document_type\": \"national_passport\",\n      \"status\": \"verified\",\n      \"has_documents\": true,\n      \"created_at\": \"2026-05-14T09:12:00.000000Z\"\n    }\n  ],\n  \"pagination\": {\"current_page\": 1, \"last_page\": 1, \"per_page\": 25, \"total\": 1}\n}\n```","summary":"Список клиентов","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"search","in":"query","description":"Поиск по телефону, external_id, имени или фамилии (подстрока).","schema":{"type":["string","null"],"maxLength":100}},{"name":"status","in":"query","description":"Фильтр по статусу верификации клиента.","schema":{"type":["string","null"],"maxLength":32}},{"name":"per_page","in":"query","schema":{"type":["integer","null"],"minimum":1,"maximum":100}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"external_id":{"type":["string","null"]},"phone":{"type":["string","null"]},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"document_type":{"type":["string","null"]},"status":{"type":["string","null"]},"has_documents":{"type":"boolean"},"created_at":{"type":"string"}},"required":["id","external_id","phone","first_name","last_name","document_type","status","has_documents","created_at"]}},"pagination":{"type":"object","properties":{"current_page":{"type":"integer"},"last_page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"required":["current_page","last_page","per_page","total"]}},"required":["data","pagination"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/clients/{key}":{"get":{"operationId":"showClient","description":"Ищет клиента по `client_external_id` или `client_phone` (в этом порядке).\nИспользуйте перед созданием заказа: если клиент найден и `status=verified` —\nпередавайте в заказе только ключ, без KYC-файлов.\n\nПример ответа (200):\n```json\n{\n  \"client\": {\n    \"id\": 15,\n    \"external_id\": \"usr-8123\",\n    \"phone\": \"+79161234567\",\n    \"first_name\": \"Иван\",\n    \"last_name\": \"Петров\",\n    \"document_type\": \"national_passport\",\n    \"status\": \"verified\",\n    \"has_documents\": true,\n    \"created_at\": \"2026-05-14T09:12:00.000000Z\"\n  }\n}\n```\nОшибка 404: `{\"message\": \"Клиент не найден\"}`","summary":"Получить клиента по ключу","tags":["Merchant API","MerchantExternalApi"],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"client":{"type":"object","properties":{"id":{"type":"integer"},"external_id":{"type":["string","null"]},"phone":{"type":["string","null"]},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"document_type":{"type":["string","null"]},"status":{"type":["string","null"]},"has_documents":{"type":"boolean"},"created_at":{"type":"string"}},"required":["id","external_id","phone","first_name","last_name","document_type","status","has_documents","created_at"]}},"required":["client"]}}}}}}},"/v1/registered/clients/verification-code":{"post":{"operationId":"registeredSendVerificationCode","description":"Отправляет клиенту код подтверждения (Telegram или SMS — на усмотрение\nпроцессинга) для последующего вызова регистрации. Полученный код\nпередаётся в поле `verification_code` при вызове\n`POST /api/v1/registered/clients`.\n\nПоле `ip_address` — IP-адрес конечного клиента (нужен антифроду\nпроцессинга). Если не передан — подставится IP вашего сервера,\nчто снижает качество проверки.\n\nПример ответа (200):\n```json\n{\n  \"send_as\": \"sms\",\n  \"remaining_attempts\": 3,\n  \"can_retry_at\": \"2026-04-22T12:05:00Z\"\n}\n```\nОшибка 400: `{\"error\": \"Метод недоступен для вашего аккаунта\"}`\nОшибка 422: `{\"message\": \"The phone field is required.\"}`\nОшибка 500: `{\"error\": \"Ошибка отправки кода: ...\"}`","summary":"Отправить код подтверждения","tags":["Registered Clients","RegisteredClientsExternalApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","maxLength":50},"ip_address":{"type":["string","null"]}},"required":["phone"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"send_as":{"type":"string"},"remaining_attempts":{"type":"integer"},"can_retry_at":{"type":"string"}},"required":["send_as","remaining_attempts","can_retry_at"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/registered/clients":{"post":{"operationId":"registeredRegisterClient","description":"Регистрирует клиента в платёжной системе провайдера. После успешной\nрегистрации у клиента появится `account_number`, который используется\nдля последующих списаний при создании заказов.\n\nДокументы передаются в виде публично доступных URL (селфи, паспорт,\nподтверждение адреса). Для паспорта `ru` обязателен `address_url`,\nдля `other` — текстовый `address`.\n\nЕсли провайдер требует подтверждение номера телефона, сначала получите\nкод через `POST /api/v1/registered/clients/verification-code`\nи передайте его в поле `verification_code`.\n\nПример ответа (200):\n```json\n{\n  \"account_number\": \"40817810000000000001\",\n  \"identification_level\": 1,\n  \"is_blocked\": false,\n  \"passport_state\": \"processing\"\n}\n```\nОшибка 400: `{\"error\": \"Метод недоступен для вашего аккаунта\"}`\nОшибка 422: `{\"message\": \"The phone field is required.\"}`\nОшибка 500: `{\"error\": \"Ошибка регистрации: ...\"}`","summary":"Регистрация клиента","tags":["Registered Clients","RegisteredClientsExternalApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","maxLength":50},"passport_type":{"type":"string","enum":["ru","other"]},"selfie_url":{"type":"string","format":"uri","maxLength":1000},"document_url":{"type":"string","format":"uri","maxLength":1000},"address_url":{"type":["string","null"],"format":"uri","maxLength":1000},"address":{"type":["string","null"],"maxLength":500},"verification_code":{"type":["string","null"],"maxLength":10}},"required":["phone","passport_type","selfie_url","document_url"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"account_number":{"type":["string","null"]},"identification_level":{"type":["integer","null"]},"is_blocked":{"type":["boolean","null"]},"passport_state":{"type":["string","null"]},"address_state":{"type":["string","null"]},"identification_error":{"type":["string","null"]}},"required":["account_number","identification_level","is_blocked","passport_state","address_state","identification_error"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}},"/v1/registered/clients/{phone}":{"get":{"operationId":"registeredGetClient","description":"Возвращает актуальные данные клиента по номеру телефона, включая уровень\nидентификации, состояние паспорта и адреса.\n\nПример ответа (200):\n```json\n{\n  \"account_number\": \"40817810000000000001\",\n  \"identification_level\": 1,\n  \"is_blocked\": false,\n  \"passport_state\": \"success\",\n  \"address_state\": \"success\",\n  \"identification_error\": null\n}\n```\nОшибка 400: `{\"error\": \"Метод недоступен для вашего аккаунта\"}`\nОшибка 404: `{\"error\": \"Клиент не найден\"}`\nОшибка 500: `{\"error\": \"Ошибка получения данных: ...\"}`","summary":"Статус клиента","tags":["Registered Clients","RegisteredClientsExternalApi"],"parameters":[{"name":"phone","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"account_number":{"type":["string","null"]},"identification_level":{"type":["integer","null"]},"is_blocked":{"type":["boolean","null"]},"passport_state":{"type":["string","null"]},"address_state":{"type":["string","null"]},"identification_error":{"type":["string","null"]}},"required":["account_number","identification_level","is_blocked","passport_state","address_state","identification_error"]}}}}}}},"/v1/registered/sbp-banks":{"get":{"operationId":"registeredGetSbpBanks","description":"Возвращает список доступных банков СБП. Используйте `id` банка в поле\n`bank_id` при создании заказа на оплату.\n\nПример ответа (200):\n```json\n{\n  \"banks\": [\n    {\"id\": \"100000000111\", \"name\": \"Сбербанк\"},\n    {\"id\": \"100000000004\", \"name\": \"Т-Банк\"}\n  ]\n}\n```\nОшибка 400: `{\"error\": \"Метод недоступен для вашего аккаунта\"}`\nОшибка 500: `{\"error\": \"Ошибка получения банков: ...\"}`","summary":"Список банков СБП","tags":["Registered Clients","RegisteredClientsExternalApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"banks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}}},"required":["banks"]}}}}}}},"/v1/registered/orders":{"post":{"operationId":"registeredCreateOrder","description":"Создаёт новый заказ на списание со счёта ранее зарегистрированного клиента.\nКлиент должен быть зарегистрирован через `POST /api/v1/registered/clients`\nи иметь `account_number` (верифицирован на стороне процессинга).\n\nВ ответе возвращается `payment_url` — ссылка, на которой клиент выберет\nбанк и подтвердит списание через СБП. Курс фиксируется в момент создания.\n\n**Тестовый режим (`rbk_test_`):** заказ НЕ сохраняется в базу. Возвращается\nреалистичный ответ для проверки интеграции; в теле присутствуют `_sandbox`\nи `is_test: true`.\n\nЕсли касса привязана к локальной валюте (THB и т.п.), в ответе заполнены\n`local_currency_code`, `amount_local`, `rate_local`, `rate_local_per_usdt`,\n`profit_local`.\n\nПример ответа (201):\n```json\n{\n  \"order\": {\n    \"id\": 42,\n    \"global_id\": \"RB-000042\",\n    \"order_number\": \"RB-000042\",\n    \"status\": \"pending\",\n    \"amount_rub\": 5000.00,\n    \"amount_usdt\": 59.70,\n    \"payment_reference\": \"ABCDEF1234567890\",\n    \"created_at\": \"2026-04-22T12:00:00.000000Z\"\n  },\n  \"payment_url\": \"https://pay.rubrek.com/pay/ABCDEF1234567890\"\n}\n```\nОшибка 400: `{\"error\": \"Метод недоступен для вашего аккаунта\"}`\nОшибка 422: `{\"message\": \"Клиент не зарегистрирован. Сначала вызовите POST /api/v1/registered/clients.\"}`\nОшибка 429: `{\"error\": \"Слишком много запросов, повторите позже\"}`\nОшибка 503: `{\"error\": \"Не удалось получить курс. Попробуйте позже.\"}`\n\nУспешный ответ приходит с HTTP-кодом **201** (в спецификации показан как 200 — ограничение генератора).","summary":"Создать заказ (по зарегистрированному клиенту)","tags":["Registered Clients","RegisteredClientsExternalApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"point_id":{"type":"integer"},"amount_rub":{"type":"number","minimum":1},"client_phone":{"type":"string","maxLength":50},"client_name":{"type":["string","null"],"maxLength":255}},"required":["point_id","amount_rub","client_phone"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"integer"},"global_id":{"type":["string","null"]},"order_number":{"type":"string"},"status":{"type":"string"},"amount_rub":{"type":"number"},"amount_usdt":{"type":"number"},"local_currency_code":{"type":["string","null"]},"amount_local":{"type":["number","null"]},"rate_local":{"type":["number","null"]},"rate_local_per_usdt":{"type":["number","null"]},"profit_local":{"type":["number","null"]},"payment_reference":{"type":"string"},"created_at":{"type":"string"}},"required":["id","global_id","order_number","status","amount_rub","amount_usdt","local_currency_code","amount_local","rate_local","rate_local_per_usdt","profit_local","payment_reference","created_at"]},"payment_url":{"type":"string"}},"required":["order","payment_url"]}}}},"422":{"$ref":"#/components/responses/ValidationException"}}}}},"components":{"securitySchemes":{"http":{"type":"http","scheme":"bearer"}},"responses":{"ValidationException":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Errors overview."},"errors":{"type":"object","description":"A detailed description of each field that failed validation.","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["message","errors"]}}}},"ModelNotFoundException":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview."}},"required":["message"]}}}}}}}