{
  "openapi": "3.1.0",
  "info": {
    "title": "CRYPTOSHA Merchant API",
    "version": "0.8.8",
    "description": "Полный контракт внешнего API: счета и реквизиты для собственного checkout, управляемые адреса, переводы, сбор, ресурсы и подписанные события. JSON UTF-8; точные денежные значения строками. API-ключ хранится только на сервере. Лимиты: 120 запросов/мин на IP для маршрутов без отдельного лимита; отдельные счётчики указаны у методов. Максимальное JSON-тело 32768 байт. Внешний прокси дополнительно ограничивает 5 запросов/сек с burst 50 на IP. Кабинетные /api/* не входят в контракт merchant-интеграции."
  },
  "servers": [
    {
      "url": "https://cryptosha.net",
      "description": "Production. Доступность активов определяется настройками проекта."
    }
  ],
  "security": [
    {
      "BearerKey": []
    }
  ],
  "tags": [
    {
      "name": "Активы"
    },
    {
      "name": "Счета"
    },
    {
      "name": "Кошельки"
    },
    {
      "name": "Переводы"
    },
    {
      "name": "Ресурсы"
    },
    {
      "name": "Публичные методы"
    }
  ],
  "paths": {
    "/v1/main-wallets": {
      "get": {
        "operationId": "listMainWallets",
        "tags": [
          "Кошельки"
        ],
        "summary": "Главные кошельки и архив",
        "description": "Один активный главный кошелёк на сеть для текущего магазина. Каждый магазин имеет отдельные адреса, архив и историю; ключ одного магазина не видит кошельки другого, даже при общем владельце. GET возвращает кеш без RPC. В XRP счета используют главный адрес с уникальным Destination Tag в memo; только платёж с тегом счёта создаёт его webhook. Ручные пополнения без тега счёта и обновление баланса webhook не создают. В остальных сетях адреса счетов отдельные.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWalletList"
                },
                "example": {
                  "wallets": [
                    {
                      "id": "cw_main_example",
                      "merchantId": "mer_example",
                      "chain": "bsc",
                      "address": "0x2222222222222222222222222222222222222222",
                      "status": "active",
                      "archivedAt": null,
                      "createdAt": "2026-09-30T10:00:00.000Z",
                      "balances": [],
                      "balanceCheckedAt": null,
                      "balanceError": null,
                      "refreshAfter": null,
                      "refreshing": false
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createMainWallet",
        "tags": [
          "Кошельки"
        ],
        "summary": "Создать или заменить главный кошелёк",
        "description": "Создаёт отдельный зашифрованный ключ без экспорта. Первое создание требует подтверждённый email, но не требует повторного пароля или MFA; для API нужен ключ этого магазина с wallets:create. При замене передайте replaceWalletId: прежний адрес становится архивным, средства автоматически не переводятся; в кабинете потребуются пароль и MFA. Архивный кошелёк остаётся доступен для ручного обновления и вывода через /v1/transfers. Незавершённые операции с текущим главным кошельком блокируют замену. В XRP каждый магазин использует собственный главный адрес с разными тегами своих счетов. Перед первым счётом активируйте адрес пополнением XRP; без этого вернётся 409 XRP_ACTIVATION_REQUIRED. Старые счета при замене сохраняют адрес и tag. В остальных сетях счета получают отдельные адреса.",
        "x-rate-limit": "5 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [
          "wallets:create"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMainWallet"
              },
              "example": {
                "chain": "bsc"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Идемпотентный повтор",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWallet"
                },
                "example": {
                  "id": "cw_main_example",
                  "merchantId": "mer_example",
                  "chain": "bsc",
                  "address": "0x2222222222222222222222222222222222222222",
                  "status": "active",
                  "archivedAt": null,
                  "createdAt": "2026-09-30T10:00:00.000Z",
                  "balances": [],
                  "balanceCheckedAt": null,
                  "balanceError": null,
                  "refreshAfter": null,
                  "refreshing": false,
                  "replayed": true
                }
              }
            }
          },
          "201": {
            "description": "Главный кошелёк создан",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWallet"
                },
                "example": {
                  "id": "cw_main_example",
                  "merchantId": "mer_example",
                  "chain": "bsc",
                  "address": "0x2222222222222222222222222222222222222222",
                  "status": "active",
                  "archivedAt": null,
                  "createdAt": "2026-09-30T10:00:00.000Z",
                  "balances": [],
                  "balanceCheckedAt": null,
                  "balanceError": null,
                  "refreshAfter": null,
                  "refreshing": false,
                  "replayed": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/main-wallets/bulk": {
      "post": {
        "operationId": "createMissingMainWallets",
        "tags": [
          "Кошельки"
        ],
        "summary": "Создать все недостающие главные кошельки",
        "description": "Одна операция для всех включённых управляемых сетей проекта. Создаёт только отсутствующие главные адреса текущего магазина, существующие и архивные кошельки не меняет. Все новые адреса создаются атомарно: при ошибке ни один не сохраняется. Повтор безопасен и возвращает пустой created, если всё уже создано. Тело и Idempotency-Key не нужны. Требуется подтверждённый email и право wallets:create ключа текущего магазина; в кабинете повторный пароль и MFA не требуются. Переводы и замена адреса сохраняют дополнительную защиту.",
        "x-rate-limit": "5 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [
          "wallets:create"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Все адреса уже существовали",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWalletBulk"
                },
                "example": {
                  "created": [
                    "bsc"
                  ],
                  "wallets": [
                    {
                      "id": "cw_main_example",
                      "merchantId": "mer_example",
                      "chain": "bsc",
                      "address": "0x2222222222222222222222222222222222222222",
                      "status": "active",
                      "archivedAt": null,
                      "createdAt": "2026-09-30T10:00:00.000Z",
                      "balances": [],
                      "balanceCheckedAt": null,
                      "balanceError": null,
                      "refreshAfter": null,
                      "refreshing": false
                    }
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Создан хотя бы один новый адрес",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWalletBulk"
                },
                "example": {
                  "created": [
                    "bsc"
                  ],
                  "wallets": [
                    {
                      "id": "cw_main_example",
                      "merchantId": "mer_example",
                      "chain": "bsc",
                      "address": "0x2222222222222222222222222222222222222222",
                      "status": "active",
                      "archivedAt": null,
                      "createdAt": "2026-09-30T10:00:00.000Z",
                      "balances": [],
                      "balanceCheckedAt": null,
                      "balanceError": null,
                      "refreshAfter": null,
                      "refreshing": false
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/main-wallets/{id}/refresh": {
      "post": {
        "operationId": "refreshMainWallet",
        "tags": [
          "Кошельки"
        ],
        "summary": "Обновить баланс главного адреса",
        "description": "Ручное чтение каталожных активов. TON использует настроенный источник с проверкой основной сети и свежести masterchain; остальные управляемые сети используют независимые источники. Ограничение 5 минут на адрес в БД, общее для всех ключей/IP, включая неуспешные попытки. Повтор внутри окна возвращает cached=true и прежний снимок; это не очередь нового RPC-запроса. При ошибке сохраняет предыдущие значения и balanceError. Работает для архива; не создаёт webhook. Только ключ магазина, которому принадлежит кошелёк.",
        "x-rate-limit": "10 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MainWallet"
                },
                "example": {
                  "id": "cw_main_example",
                  "merchantId": "mer_example",
                  "chain": "bsc",
                  "address": "0x2222222222222222222222222222222222222222",
                  "status": "active",
                  "archivedAt": null,
                  "createdAt": "2026-09-30T10:00:00.000Z",
                  "balances": [],
                  "balanceCheckedAt": null,
                  "balanceError": null,
                  "refreshAfter": null,
                  "refreshing": false,
                  "cached": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/assets": {
      "get": {
        "operationId": "listAssets",
        "tags": [
          "Активы"
        ],
        "summary": "Доступные активы",
        "description": "Возвращает активы, разрешённые для приёма вашему проекту. Наличие валюты на сайте или доступность сети на Health не заменяет этот запрос. При пустом assets не создавайте платёжную форму. Точность зависит от сети: у USDT в BSC 18 знаков, в TRON 6.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetList"
                },
                "example": {
                  "assets": [
                    {
                      "id": "bsc:usdt",
                      "chain": "bsc",
                      "symbol": "USDT",
                      "name": "Tether USD",
                      "decimals": 18,
                      "contract": "0x55d398326f99059ff775485246999027b3197955"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoices": {
      "post": {
        "operationId": "createInvoice",
        "tags": [
          "Счета"
        ],
        "summary": "Создать счёт",
        "description": "Создаёт отдельный счёт и выделяет реквизиты. Нужны подтверждённый email, MFA владельца, доступный актив, настроенный источник адресов и не менее 0.01 USDT ресурсов. Первое создание списывает 0.01 USDT за отслеживание. Ответ сразу содержит адрес, memo, сумму, сеть и платёжную ссылку для вашей формы. Приватные ключи сюда не входят. orderId не уникален: от дублей защищает Idempotency-Key.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvoice"
              },
              "example": {
                "orderId": "order-1049",
                "assetId": "bsc:usdt",
                "amount": "12.5",
                "description": "Подписка Pro",
                "expiresIn": 1800
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Повтор: тот же счёт с актуальными данными, повторного списания нет",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "id": "inv_example",
                  "order_id": "order-1049",
                  "description": "Подписка Pro",
                  "status": "pending",
                  "status_version": 0,
                  "resolution": null,
                  "asset_id": "bsc:usdt",
                  "asset": {
                    "id": "bsc:usdt",
                    "chain": "bsc",
                    "symbol": "USDT",
                    "name": "Tether USD",
                    "decimals": 18,
                    "contract": "0x55d398326f99059ff775485246999027b3197955",
                    "chain_id": 56
                  },
                  "amount": "12.5",
                  "received": "0",
                  "remaining": "12.5",
                  "address": "0x1111111111111111111111111111111111111111",
                  "memo": null,
                  "payment_uri": "0x1111111111111111111111111111111111111111",
                  "can_pay": true,
                  "test_mode": false,
                  "confirmations": 0,
                  "required_confirmations": 15,
                  "checkout_url": "https://cryptosha.net/pay/EXAMPLE_TOKEN_DO_NOT_PAY_00000000000000000000",
                  "created_at": "2026-09-28T10:00:00.000Z",
                  "expires_at": "2026-09-28T10:30:00.000Z",
                  "wallet_id": "cw_example"
                }
              }
            }
          },
          "201": {
            "description": "Счёт создан; реквизиты выделены",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "id": "inv_example",
                  "order_id": "order-1049",
                  "description": "Подписка Pro",
                  "status": "pending",
                  "status_version": 0,
                  "resolution": null,
                  "asset_id": "bsc:usdt",
                  "asset": {
                    "id": "bsc:usdt",
                    "chain": "bsc",
                    "symbol": "USDT",
                    "name": "Tether USD",
                    "decimals": 18,
                    "contract": "0x55d398326f99059ff775485246999027b3197955",
                    "chain_id": 56
                  },
                  "amount": "12.5",
                  "received": "0",
                  "remaining": "12.5",
                  "address": "0x1111111111111111111111111111111111111111",
                  "memo": null,
                  "payment_uri": "0x1111111111111111111111111111111111111111",
                  "can_pay": true,
                  "test_mode": false,
                  "confirmations": 0,
                  "required_confirmations": 15,
                  "checkout_url": "https://cryptosha.net/pay/EXAMPLE_TOKEN_DO_NOT_PAY_00000000000000000000",
                  "created_at": "2026-09-28T10:00:00.000Z",
                  "expires_at": "2026-09-28T10:30:00.000Z",
                  "wallet_id": "cw_example"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listInvoices",
        "tags": [
          "Счета"
        ],
        "summary": "Список счетов",
        "description": "Постраничный список только текущего проекта. Поиск q — подстрока в orderId, description или id. Сортировка created_at DESC, id DESC; при новых вставках offset-пагинация может сдвигаться, устраняйте дубли по id. Основные поля совпадают с созданием и получением счёта. Старые camelCase-поля сохранены только здесь для совместимости.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Поисковая подстрока.",
            "schema": {
              "type": "string",
              "description": "",
              "maxLength": 100,
              "default": ""
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Фильтр состояния; all — все.",
            "schema": {
              "type": "string",
              "description": "",
              "enum": [
                "all",
                "pending",
                "confirming",
                "paid",
                "underpaid",
                "overpaid",
                "expired",
                "late",
                "review",
                "cancelled"
              ],
              "default": "all"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Количество записей на странице.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "",
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Количество пропускаемых записей.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "",
              "maximum": 1000000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceList"
                },
                "example": {
                  "invoices": [
                    {
                      "id": "inv_example",
                      "order_id": "order-1049",
                      "description": "Подписка Pro",
                      "status": "pending",
                      "status_version": 0,
                      "resolution": null,
                      "asset_id": "bsc:usdt",
                      "asset": {
                        "id": "bsc:usdt",
                        "chain": "bsc",
                        "symbol": "USDT",
                        "name": "Tether USD",
                        "decimals": 18,
                        "contract": "0x55d398326f99059ff775485246999027b3197955",
                        "chain_id": 56
                      },
                      "amount": "12.5",
                      "received": "0",
                      "remaining": "12.5",
                      "address": "0x1111111111111111111111111111111111111111",
                      "memo": null,
                      "payment_uri": "0x1111111111111111111111111111111111111111",
                      "can_pay": true,
                      "test_mode": false,
                      "confirmations": 0,
                      "required_confirmations": 15,
                      "checkout_url": "https://cryptosha.net/pay/EXAMPLE_TOKEN_DO_NOT_PAY_00000000000000000000",
                      "created_at": "2026-09-28T10:00:00.000Z",
                      "expires_at": "2026-09-28T10:30:00.000Z",
                      "wallet_id": "cw_example"
                    }
                  ],
                  "total": 1,
                  "limit": 30,
                  "offset": 0
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoices/{id}": {
      "get": {
        "operationId": "getInvoice",
        "tags": [
          "Счета"
        ],
        "summary": "Получить счёт",
        "description": "Возвращает актуальные реквизиты и состояние. Чужой ID возвращает 404. Реквизиты реального счёта сохраняются после завершения, но can_pay=false и payment_uri=null. Полученная сумма может включать неподтверждённые поступления. Подтверждайте оплату по status и сверяйте asset_id, amount, order_id.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                },
                "example": {
                  "id": "inv_example",
                  "order_id": "order-1049",
                  "description": "Подписка Pro",
                  "status": "pending",
                  "status_version": 0,
                  "resolution": null,
                  "asset_id": "bsc:usdt",
                  "asset": {
                    "id": "bsc:usdt",
                    "chain": "bsc",
                    "symbol": "USDT",
                    "name": "Tether USD",
                    "decimals": 18,
                    "contract": "0x55d398326f99059ff775485246999027b3197955",
                    "chain_id": 56
                  },
                  "amount": "12.5",
                  "received": "0",
                  "remaining": "12.5",
                  "address": "0x1111111111111111111111111111111111111111",
                  "memo": null,
                  "payment_uri": "0x1111111111111111111111111111111111111111",
                  "can_pay": true,
                  "test_mode": false,
                  "confirmations": 0,
                  "required_confirmations": 15,
                  "checkout_url": "https://cryptosha.net/pay/EXAMPLE_TOKEN_DO_NOT_PAY_00000000000000000000",
                  "created_at": "2026-09-28T10:00:00.000Z",
                  "expires_at": "2026-09-28T10:30:00.000Z",
                  "wallet_id": "cw_example"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoices/{id}/cancel": {
      "post": {
        "operationId": "cancelInvoice",
        "tags": [
          "Счета"
        ],
        "summary": "Отменить счёт",
        "description": "Разрешено только при status=pending и received=0. Тело и Idempotency-Key не нужны. Успешный ответ {ok:true}; повтор после отмены даёт 409. Отмена не возвращает средства и не запрещает перевод в блокчейне: позднее поступление на отменённый счёт переводит его в review. Адрес не выдаётся другому счёту.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/addresses": {
      "post": {
        "operationId": "createAddress",
        "tags": [
          "Кошельки"
        ],
        "summary": "Создать управляемый адрес",
        "description": "Создаёт отдельный ключ и адрес в EVM/TRON/Solana/Sui/XRP/TON. Обязательны email/MFA, работающий сервис подписи и wallets:create. returnPrivateKey=true дополнительно требует wallets:export. Первый ответ может содержать ключ, повтор никогда его не содержит. При потере первого ответа с экспортом ключа создайте новый адрес до использования средств, если вам нужна собственная копия. Создание адреса не создаёт счёт и не включает отслеживание поступлений.",
        "x-rate-limit": "20 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [
          "wallets:create",
          "wallets:export (только returnPrivateKey=true)"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAddress"
              },
              "example": {
                "chain": "bsc",
                "returnPrivateKey": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Повтор, replayed=true; privateKey отсутствует",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressCreated"
                },
                "example": {
                  "id": "cw_example",
                  "chain": "bsc",
                  "address": "0x1111111111111111111111111111111111111111",
                  "keyFormat": "secp256k1-hex",
                  "keyExported": false,
                  "replayed": true
                }
              }
            }
          },
          "201": {
            "description": "Создан новый адрес, replayed=false",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressCreated"
                },
                "example": {
                  "id": "cw_example",
                  "chain": "bsc",
                  "address": "0x1111111111111111111111111111111111111111",
                  "keyFormat": "secp256k1-hex",
                  "keyExported": false,
                  "replayed": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAddresses",
        "tags": [
          "Кошельки"
        ],
        "summary": "Список адресов",
        "description": "До 100 последних адресов проекта; приватных ключей нет. Query-параметров и пагинации нет. Для чтения достаточно обычного ключа проекта. Сохраните id нужного кошелька при создании, если адресов больше 100.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressList"
                },
                "example": {
                  "addresses": [
                    {
                      "id": "cw_example",
                      "chain": "bsc",
                      "address": "0x1111111111111111111111111111111111111111",
                      "keyFormat": "secp256k1-hex",
                      "keyExported": false,
                      "createdAt": "2026-09-28 10:00:00.000"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/transfers": {
      "post": {
        "operationId": "createTransfer",
        "tags": [
          "Переводы"
        ],
        "summary": "Отправить заданную сумму",
        "description": "Асинхронная заявка с управляемого кошелька EVM/TRON/Solana/Sui/XRP/TON. Списывается 0.01 USDT ресурсов за заявку, ещё 0.01 резервируется на отправку. Один незавершённый перевод на исходный кошелёк. Средства актива нужны на исходном адресе. При нехватке комиссии для токена fundGas=true разрешает одно пополнение с главного кошелька этого магазина и ожидание его подтверждения. Сам главный адрес пополняйте вручную; ресурсный баланс не заменяет сетевой gas. В XRP поддержан нативный XRP: destination — classic address, destinationTag передаётся отдельно. Резерв остаётся на кошельке, feeBudget оплачивается XRP. В TON поддержаны TON и USDT Jetton: кошелёк V4R2, комиссия в TON, приём на новые адреса без обязательного комментария. Для Jetton в бюджет входит 0.1 TON, прикрепляемый к запросу токенового кошелька, и оценка комиссии отправителя с запасом 30%; неиспользованный TON возвращается на исходный адрес. Статус confirmed требует финальной доставки, включая завершённую цепочку Jetton. txid в TON — хэш подписанного внешнего сообщения; исходная транзакция находится по хэшу его тела. HTTP 202 означает принятие заявки, не перевод средств. Нужны email/MFA, transfers:create и разрешённая проекту сеть.",
        "x-rate-limit": "15 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [
          "transfers:create"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTransfer"
              },
              "example": {
                "walletId": "cw_example",
                "assetId": "bsc:usdt",
                "destination": "0x2222222222222222222222222222222222222222",
                "amount": "12.5",
                "feeBudget": "0.001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Повтор: актуальная ранее созданная заявка",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "12.5",
                  "status": "queued",
                  "sweep": false,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "replayed": true
                }
              }
            }
          },
          "202": {
            "description": "Заявка принята в очередь",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "12.5",
                  "status": "queued",
                  "sweep": false,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "replayed": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTransfers",
        "tags": [
          "Переводы"
        ],
        "summary": "Список переводов и сборов",
        "description": "Последние 100 заявок текущего проекта, новые первыми. Включает переводы и сборы. Пагинации и фильтров нет; для долгой истории храните ID и статусы в своей системе. Webhook об исходящих переводах не отправляется — проверяйте GET /v1/transfers/{id}.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferList"
                },
                "example": {
                  "transfers": [
                    {
                      "id": "tr_example",
                      "walletId": "cw_example",
                      "assetId": "bsc:usdt",
                      "destination": "0x2222222222222222222222222222222222222222",
                      "amount": "12.5",
                      "status": "queued",
                      "sweep": false,
                      "txid": null,
                      "errorCode": null,
                      "createdAt": "2026-09-28 10:10:00.000",
                      "requestCost": "0.01",
                      "sendCost": "0"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/transfers/{id}": {
      "get": {
        "operationId": "getTransfer",
        "tags": [
          "Переводы"
        ],
        "summary": "Состояние перевода",
        "description": "Проверяйте до confirmed или failed_onchain/cancelled. unknown означает, что результат отправки не определён: не создавайте замену с новым Idempotency-Key. txid может существовать до включения в блок. Сервис продолжает проверку той же транзакции.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "12.5",
                  "status": "queued",
                  "sweep": false,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/transfers/{id}/cancel": {
      "post": {
        "operationId": "cancelTransfer",
        "tags": [
          "Переводы"
        ],
        "summary": "Отменить неподписанную заявку",
        "description": "Тело и Idempotency-Key не нужны. Разрешено для queued/blocked, если подпись ещё не сохранена. Повтор отмены возвращает тот же cancelled. Резерв 0.01 USDT освобождается, стоимость принятой заявки не возвращается. После подписи возвращает 409, поскольку отправка уже могла произойти. Требует transfers:create и email/MFA.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [
          "transfers:create"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "12.5",
                  "status": "cancelled",
                  "sweep": false,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/sweeps": {
      "post": {
        "operationId": "createSweep",
        "tags": [
          "Переводы"
        ],
        "summary": "Собрать средства",
        "description": "Сбор с управляемого кошелька на активный главный кошелёк этого магазина в той же сети. Создайте его заранее; для старых проектов без него сохраняется настроенный адрес сбора. Нельзя передавать destination или amount. Адрес назначения фиксируется в заявке и не меняется при смене настроек. Токен отправляется целиком; нативная монета — за вычетом бюджета комиссии. Остаток на gas возможен. XRP-счета сразу получают средства на главный адрес и сбора не требуют. При сборе с отдельного или архивного XRP-кошелька сохраняются сетевой резерв и бюджет комиссии. Оплата счёта сама по себе не запускает сбор. Тарифы и права такие же, как у /v1/transfers.",
        "x-rate-limit": "15 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [
          "transfers:create"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSweep"
              },
              "example": {
                "walletId": "cw_example",
                "assetId": "bsc:usdt",
                "feeBudget": "0.001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Повтор: прежняя заявка на сбор",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "max",
                  "status": "queued",
                  "sweep": true,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "replayed": true
                }
              }
            }
          },
          "202": {
            "description": "Сбор принят в очередь",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transfer"
                },
                "example": {
                  "id": "tr_example",
                  "walletId": "cw_example",
                  "assetId": "bsc:usdt",
                  "destination": "0x2222222222222222222222222222222222222222",
                  "amount": "max",
                  "status": "queued",
                  "sweep": true,
                  "txid": null,
                  "errorCode": null,
                  "createdAt": "2026-09-28 10:10:00.000",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "replayed": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/broadcast": {
      "post": {
        "operationId": "broadcastTransaction",
        "tags": [
          "Переводы"
        ],
        "summary": "Опубликовать подписанную транзакцию",
        "description": "Для транзакций, которые подписаны вашим кошельком. Сервис не меняет и не подписывает их. Проверяет формат и сеть; одна и та же каноническая транзакция в проекте не тарифицируется повторно. 0.01 USDT за заявку, 0.01 за принятие сетью. Неопределённый результат удерживает резерв. submitted не является подтверждением в блокчейне; этот метод не отслеживает финальность. Нужны email/MFA и включённая сеть; дополнительного custody-права не требуется.",
        "x-rate-limit": "15 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Сохраните ключ до отправки. Повторяйте неопределённый результат с тем же ключом и теми же параметрами; другой запрос с прежним ключом вернёт 409.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 8,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9_.:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BroadcastInput"
              },
              "example": {
                "chain": "bsc",
                "signedTransaction": "0xSIGNED_TRANSACTION_FROM_YOUR_WALLET"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Результат submitted или rejected",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "br_example",
                  "status": "submitted",
                  "requestCost": "0.01",
                  "sendCost": "0.01",
                  "reserved": "0",
                  "txid": "0x1111111111111111111111111111111111111111111111111111111111111111"
                }
              }
            }
          },
          "202": {
            "description": "processing или unknown: результат ещё не определён",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "br_example",
                  "status": "unknown",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "reserved": "0.01"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно доступного баланса ресурсов; code=INSUFFICIENT_RESOURCE_BALANCE."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "409": {
            "description": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Конфликт Idempotency-Key, исчерпан пул адресов, кошелёк занят или текущее состояние запрещает действие."
                }
              }
            }
          },
          "413": {
            "description": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Тело запроса превышает 32768 байт. Ответ внешнего прокси при ещё большем теле может быть не JSON."
                }
              }
            }
          },
          "415": {
            "description": "Неподдерживаемый Content-Type. Отправляйте application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Неподдерживаемый Content-Type. Отправляйте application/json."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/broadcast/{id}": {
      "get": {
        "operationId": "getBroadcast",
        "tags": [
          "Переводы"
        ],
        "summary": "Результат публикации",
        "description": "Возвращает состояние сохранённой заявки. Сам GET не запускает повторную отправку. При unknown повторяйте исходный POST с прежним ключом и теми же подписанными байтами. submitted подтверждает принятие сетью, а не исполнение транзакции.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID ресурса, полученный при создании или в списке. Ресурс должен принадлежать проекту API-ключа.",
            "schema": {
              "type": "string",
              "description": "ID ресурса"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "br_example",
                  "status": "unknown",
                  "requestCost": "0.01",
                  "sendCost": "0",
                  "reserved": "0.01"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/v1/balance": {
      "get": {
        "operationId": "getBalance",
        "tags": [
          "Ресурсы"
        ],
        "summary": "Баланс и тарифы",
        "description": "Баланс оплаты ресурсов общий для проектов одного аккаунта в одном режиме (live/test). Это не баланс криптовалюты на ваших адресах и не выручка. available учитывает резервы. Тарифы возвращаются вместе с балансом; пополнение выполняется в кабинете.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "balance": "5",
                  "reserved": "0.01",
                  "available": "4.99",
                  "currency": "USDT",
                  "testMode": false,
                  "rates": [
                    {
                      "kind": "tracking",
                      "label": "Заявка на отслеживание",
                      "detail": "Один раз при создании счёта; дальнейшие проверки включены",
                      "price": "0.01"
                    },
                    {
                      "kind": "send_request",
                      "label": "Заявка на отправку",
                      "detail": "Когда проверенная заявка принята в обработку",
                      "price": "0.01"
                    },
                    {
                      "kind": "send",
                      "label": "Отправка транзакции",
                      "detail": "Когда сеть приняла подписанную транзакцию",
                      "price": "0.01"
                    },
                    {
                      "kind": "webhook",
                      "label": "IPN / WebHook",
                      "detail": "За уведомление; автоматические повторы бесплатны",
                      "price": "0.01"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "401": {
            "description": "API-ключ отсутствует, неверен или отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "API-ключ отсутствует, неверен или отозван."
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Недостаточно прав ключа, не подтверждён email/MFA или запрещён режим работы."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/checkout-api/{token}": {
      "get": {
        "operationId": "getCheckout",
        "tags": [
          "Публичные методы"
        ],
        "summary": "Данные платёжной ссылки",
        "description": "Без API-ключа: доступ предоставляет 43-символьный токен из checkout_url. Не путайте с ID счёта. Здесь используется camelCase; address/memo/paymentUri отсутствуют, когда оплата закрыта. Для собственного checkout предпочтительно получать /v1/invoices/{id} с вашего сервера и выдавать покупателю только данные его заказа. Межсайтовый CORS не предоставляется.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Токен доступа из ссылки /pay/{token}; не сохраняйте в публичных логах.",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 43,
              "maxLength": 43,
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkout"
                },
                "example": {
                  "id": "inv_example",
                  "orderId": "order-1049",
                  "description": "Подписка Pro",
                  "assetId": "bsc:usdt",
                  "status": "pending",
                  "amount": "12.5",
                  "received": "0",
                  "remaining": "12.5",
                  "expiresAt": "2026-09-28T10:30:00.000Z",
                  "confirmations": 0,
                  "requiredConfirmations": 15,
                  "brandName": "Ваш магазин",
                  "brandColor": "#b8ec69",
                  "testMode": false,
                  "localMode": false,
                  "canPay": true,
                  "asset": {
                    "id": "bsc:usdt",
                    "chain": "bsc",
                    "symbol": "USDT",
                    "decimals": 18,
                    "contract": "0x55d398326f99059ff775485246999027b3197955"
                  },
                  "address": "0x1111111111111111111111111111111111111111",
                  "paymentUri": "0x1111111111111111111111111111111111111111"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "404": {
            "description": "Объект не найден в проекте данного ключа либо неверен токен ссылки.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Объект не найден в проекте данного ключа либо неверен токен ссылки."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/status-api/rpc": {
      "get": {
        "operationId": "getNetworkHealth",
        "tags": [
          "Публичные методы"
        ],
        "summary": "Доступность сетей",
        "description": "Обезличенные измерения сети, без служебных адресов и поставщиков. Снимок кешируется до 15 секунд. 24h — 96 интервалов по 15 минут; 7d — 84 по 2 часа; 30d — 90 по 8 часов. Зелёный график не подтверждает успешный приём, сбор или вывод. Для доступности конкретному проекту используйте /v1/assets.",
        "x-rate-limit": "60 запросов / 60 с на IP, отдельный счётчик этого маршрута",
        "x-scopes": [],
        "security": [],
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "description": "Окно истории.",
            "schema": {
              "type": "string",
              "description": "",
              "enum": [
                "24h",
                "7d",
                "30d"
              ],
              "default": "24h"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "generatedAt": "2026-09-28T10:00:00.000Z",
                  "period": "24h",
                  "intervalMs": 60000,
                  "staleAfterMs": 180000,
                  "windowStart": "2026-09-27T10:15:00.000Z",
                  "windowEnd": "2026-09-28T10:15:00.000Z",
                  "barMs": 900000,
                  "chains": []
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Некорректные поля, JSON, сумма, адрес или неподдерживаемая операция."
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "operationId": "getServiceHealth",
        "tags": [
          "Публичные методы"
        ],
        "summary": "Проверка API",
        "description": "Лёгкая проверка API и соединения с базой. Не проверяет входящие платежи, очереди или отправку средств. /health без Accept: text/html возвращает тот же JSON; в браузере /health — страница доступности.",
        "x-rate-limit": "120 запросов / 60 с на IP, общий счётчик",
        "x-scopes": [],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceHealth"
                },
                "example": {
                  "status": "ok"
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка.",
            "headers": {
              "x-ratelimit-limit": {
                "description": "Максимум запросов в текущем окне для этого счётчика.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "description": "Сколько запросов осталось; общий счётчик разделяют маршруты без отдельного лимита.",
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "description": "Секунды до сброса окна (не Unix timestamp).",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Секунды до следующей попытки. Может отсутствовать в ответе прокси.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Превышен лимит. На уровне приложения ответ JSON и Retry-After в секундах; внешний прокси может вернуть HTML без этого заголовка."
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Временная недоступность, сеть не включена для проекта или платёжная инфраструктура не готова."
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "invoiceEvent": {
      "post": {
        "summary": "Событие счёта",
        "operationId": "receiveInvoiceEvent",
        "security": [],
        "description": "POST на HTTPS URL из настроек проекта (порт 443, без перенаправлений). HMAC-SHA256(secret, timestamp + '.' + rawBody), hex. Проверяйте подпись и свежесть 300 секунд, дедуплицируйте id, учитывайте data.version. 12 попыток доставки, интервал после неудачи 10 × 2^n секунд (n с 0), с верхней границей 86400 с; доставка может задерживаться. Тайм-аут HTTP-запроса 10 секунд. 2xx после надёжного сохранения события; остальные коды и timeout ведут к повтору. Уведомление стоит 0.01 USDT один раз; повторы бесплатны. Недостаток ресурсов приостанавливает доставку. После исчерпания попыток повтор доступен в кабинете. Адрес и платёжную ссылку запрашивайте через /v1/invoices/{id}.",
        "parameters": [
          {
            "name": "X-Cryptosha-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "ID события; должен совпадать с body.id"
            }
          },
          {
            "name": "X-Cryptosha-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Unix-время попытки доставки в секундах",
              "pattern": "^\\d{10}$"
            }
          },
          {
            "name": "X-Cryptosha-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "HMAC-SHA256 в lowercase hex",
              "pattern": "^[a-f0-9]{64}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "example": {
                "id": "evt_example",
                "type": "invoice.paid",
                "created_at": "2026-09-28T10:05:00.000Z",
                "data": {
                  "invoice_id": "inv_example",
                  "test_mode": false,
                  "order_id": "order-1049",
                  "status": "paid",
                  "amount": "12.5",
                  "received": "12.5",
                  "asset_id": "bsc:usdt",
                  "version": 2,
                  "resolution": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Событие надёжно сохранено, повторная доставка не нужна; принимается любой 2xx."
          },
          "default": {
            "description": "Любой не-2xx или тайм-аут: повтор с тем же id."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API-ключ проекта из кабинета. Передаётся только вашим сервером через HTTPS. Отдельные custody-права перечислены у методов."
      }
    },
    "schemas": {
      "MainWallet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID управляемого кошелька."
          },
          "merchantId": {
            "type": "string",
            "description": "ID магазина, которому принадлежит кошелёк."
          },
          "chain": {
            "type": "string",
            "description": "Сеть."
          },
          "address": {
            "type": "string",
            "description": "Адрес для ручного пополнения и сборов."
          },
          "status": {
            "type": "string",
            "description": "Состояние главного кошелька.",
            "enum": [
              "active",
              "archived"
            ]
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Время замены на новый адрес.",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "description": "Время создания.",
            "format": "date-time"
          },
          "balances": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "assetId": {
                  "type": "string",
                  "description": "Актив каталога."
                },
                "symbol": {
                  "type": "string",
                  "description": "Тикер."
                },
                "decimals": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Точность."
                },
                "balance": {
                  "type": "string",
                  "description": "Последний успешно проверенный баланс.",
                  "pattern": "^\\d+(\\.\\d+)?$"
                },
                "reserve": {
                  "type": "string",
                  "description": "Только XRP: сетевой резерв с учётом принадлежащих счёту объектов.",
                  "pattern": "^\\d+(\\.\\d+)?$"
                },
                "spendable": {
                  "type": "string",
                  "description": "Только XRP: баланс сверх резерва, комиссия ещё не вычтена.",
                  "pattern": "^\\d+(\\.\\d+)?$"
                },
                "activated": {
                  "type": "boolean",
                  "description": "Только XRP: адрес существует в подтверждённом реестре."
                }
              },
              "required": [
                "assetId",
                "symbol",
                "decimals",
                "balance"
              ]
            },
            "description": "Кеш балансов; пуст до первого обновления или проверки активации XRP."
          },
          "balanceCheckedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Время последнего успешного обновления.",
            "format": "date-time"
          },
          "balanceError": {
            "type": [
              "string",
              "null"
            ],
            "description": "BALANCE_UNAVAILABLE при сбое. Прежний баланс сохраняется."
          },
          "refreshAfter": {
            "type": [
              "string",
              "null"
            ],
            "description": "Раньше этого времени повторный POST вернёт кеш без обращения к сети.",
            "format": "date-time"
          },
          "refreshing": {
            "type": "boolean",
            "description": "Предыдущая проверка ещё выполняется."
          },
          "cached": {
            "type": "boolean",
            "description": "Только в ответе обновления: повтор использовал кеш."
          },
          "replayed": {
            "type": "boolean",
            "description": "Только в ответе создания: повтор с тем же Idempotency-Key."
          }
        },
        "required": [
          "id",
          "merchantId",
          "chain",
          "address",
          "status",
          "archivedAt",
          "createdAt",
          "balances",
          "balanceCheckedAt",
          "balanceError",
          "refreshAfter",
          "refreshing"
        ]
      },
      "MainWalletList": {
        "type": "object",
        "properties": {
          "wallets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MainWallet"
            },
            "description": "Главные кошельки текущего магазина, включая архив; до 200: сначала активные, затем архивные, новые первыми в каждой группе."
          }
        },
        "required": [
          "wallets"
        ]
      },
      "MainWalletBulk": {
        "type": "object",
        "properties": {
          "created": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "Сеть нового кошелька."
            },
            "description": "Сети, для которых созданы новые главные адреса."
          },
          "wallets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MainWallet"
            },
            "description": "Все активные главные кошельки текущего магазина после операции."
          }
        },
        "required": [
          "created",
          "wallets"
        ]
      },
      "CreateMainWallet": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "string",
            "description": "Включённая сеть EVM, TRON, Solana, Sui или XRP.",
            "maxLength": 40
          },
          "replaceWalletId": {
            "type": "string",
            "description": "Для замены обязательно передайте ID текущего активного кошелька. При первом создании не передавайте.",
            "maxLength": 50
          }
        },
        "required": [
          "chain"
        ],
        "additionalProperties": false
      },
      "Asset": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор актива. Берите из GET /v1/assets; не составляйте по символу валюты.",
            "example": "bsc:usdt"
          },
          "chain": {
            "type": "string",
            "description": "Идентификатор сети.",
            "example": "bsc"
          },
          "symbol": {
            "type": "string",
            "description": "Тикер актива; не уникален между сетями.",
            "example": "USDT"
          },
          "name": {
            "type": "string",
            "description": "Полное название актива.",
            "example": "Tether USD"
          },
          "decimals": {
            "type": "integer",
            "minimum": 0,
            "description": "Количество знаков после запятой; 1 токен = 10^decimals минимальных единиц.",
            "maximum": 255,
            "example": 18
          },
          "contract": {
            "type": [
              "string",
              "null"
            ],
            "description": "Адрес контракта или идентификатор токена. null для нативной монеты."
          }
        },
        "required": [
          "id",
          "chain",
          "symbol",
          "name",
          "decimals",
          "contract"
        ]
      },
      "InvoiceAsset": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор актива. Берите из GET /v1/assets; не составляйте по символу валюты.",
            "example": "bsc:usdt"
          },
          "chain": {
            "type": "string",
            "description": "Идентификатор сети.",
            "example": "bsc"
          },
          "symbol": {
            "type": "string",
            "description": "Тикер актива; не уникален между сетями.",
            "example": "USDT"
          },
          "name": {
            "type": "string",
            "description": "Полное название актива.",
            "example": "Tether USD"
          },
          "decimals": {
            "type": "integer",
            "minimum": 0,
            "description": "Количество знаков после запятой; 1 токен = 10^decimals минимальных единиц.",
            "maximum": 255,
            "example": 18
          },
          "contract": {
            "type": [
              "string",
              "null"
            ],
            "description": "Адрес контракта или идентификатор токена. null для нативной монеты."
          },
          "chain_id": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "EVM chainId для кошелька (например, 56 для BSC); null для других сетей.",
            "example": 56
          }
        },
        "required": [
          "id",
          "chain",
          "symbol",
          "name",
          "decimals",
          "contract",
          "chain_id"
        ]
      },
      "CreateInvoice": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "description": "ID заказа вашей системы. Может повторяться; для защиты от дублей нужен Idempotency-Key.",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "description": "Описание заказа.",
            "maxLength": 300,
            "default": ""
          },
          "assetId": {
            "type": "string",
            "description": "Точное значение id из GET /v1/assets для вашего проекта.",
            "minLength": 1,
            "maxLength": 180
          },
          "amount": {
            "type": "string",
            "description": "Положительная сумма в единицах актива, строка без знака, пробелов и экспоненты. Не более decimals дробных знаков и 48 цифр целой части; не более 78 цифр в сумме минимальных единиц.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80,
            "example": "12.5"
          },
          "expiresIn": {
            "type": "integer",
            "minimum": 300,
            "description": "Срок оплаты от момента создания, в секундах.",
            "maximum": 86400,
            "default": 1800
          }
        },
        "required": [
          "orderId",
          "assetId",
          "amount"
        ],
        "additionalProperties": false
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID счёта в CRYPTOSHA.",
            "example": "inv_example"
          },
          "order_id": {
            "type": "string",
            "description": "Ваш orderId, переданный при создании. Не является уникальным ключом операции."
          },
          "description": {
            "type": "string",
            "description": "Описание заказа; пустая строка, если не задано."
          },
          "status": {
            "type": "string",
            "description": "Состояние счёта; обработка каждого значения описана в разделе «Статусы».",
            "enum": [
              "pending",
              "confirming",
              "paid",
              "underpaid",
              "overpaid",
              "expired",
              "late",
              "review",
              "cancelled"
            ]
          },
          "status_version": {
            "type": "integer",
            "minimum": 0,
            "description": "Версия состояния. Сравнивайте с data.version в webhook; более старые события не должны перезаписывать новые."
          },
          "resolution": {
            "type": [
              "string",
              "null"
            ],
            "description": "Решение продавца по спорному платежу. Само по себе не изменяет статус и не переводит средства.",
            "enum": [
              "open",
              "accepted",
              "rejected",
              "refund_requested",
              "refund_recorded",
              null
            ]
          },
          "asset_id": {
            "type": "string",
            "description": "ID выбранного актива."
          },
          "asset": {
            "$ref": "#/components/schemas/InvoiceAsset",
            "description": "Актив, сеть, точность и контракт, необходимые для вашей формы оплаты."
          },
          "amount": {
            "type": "string",
            "description": "Полная запрошенная сумма в выбранном активе.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "received": {
            "type": "string",
            "description": "Сумма найденных валидных поступлений, включая ещё не подтверждённые. Не используйте её вместо status для выдачи заказа.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "remaining": {
            "type": "string",
            "description": "max(amount − received, 0). Сумма доплаты; точная десятичная строка.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Исходный адрес получения. Сохраняется и после завершения счёта для сверки. null в песочнице; показывайте для оплаты только при can_pay=true."
          },
          "memo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Обязательная метка/комментарий, если не null: XRP Destination Tag или TON comment. Передавайте без изменения вместе с адресом."
          },
          "payment_uri": {
            "type": [
              "string",
              "null"
            ],
            "description": "Данные для QR. Могут быть обычным адресом, а не URL. UTXO URI включает remaining, XRP X-address включает tag, TON URI включает сумму и comment. Для EVM это только адрес: сеть, токен и сумму передавайте отдельно. null, если can_pay=false."
          },
          "can_pay": {
            "type": "boolean",
            "description": "true только для реального неоплаченного/недоплаченного счёта до expires_at с remaining>0 и без отмены. Пересчитывается при каждом ответе."
          },
          "test_mode": {
            "type": "boolean",
            "description": "true означает симуляцию: реального платежа нет, address/memo/payment_uri равны null, can_pay=false."
          },
          "confirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Число подтверждений, учитываемое для текущего набора поступлений. Ориентируйтесь на status, а не только на счётчик."
          },
          "required_confirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Требуемое для счёта количество подтверждений."
          },
          "checkout_url": {
            "type": "string",
            "description": "Готовая платёжная ссылка. Секретный токен в URL даёт доступ к этому счёту; передавайте только соответствующему покупателю.",
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "description": "Время создания в UTC, ISO 8601.",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "description": "Срок оплаты в UTC, ISO 8601. После него не показывайте новые инструкции по оплате, даже если status ещё pending.",
            "format": "date-time"
          },
          "wallet_id": {
            "type": "string",
            "description": "ID управляемого кошелька для сбора через /v1/sweeps. Поле отсутствует для импортированных адресов и общих адресов с memo."
          }
        },
        "required": [
          "id",
          "order_id",
          "description",
          "status",
          "status_version",
          "resolution",
          "asset_id",
          "asset",
          "amount",
          "received",
          "remaining",
          "address",
          "memo",
          "payment_uri",
          "can_pay",
          "test_mode",
          "confirmations",
          "required_confirmations",
          "checkout_url",
          "created_at",
          "expires_at"
        ]
      },
      "ListedInvoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID счёта в CRYPTOSHA.",
            "example": "inv_example"
          },
          "order_id": {
            "type": "string",
            "description": "Ваш orderId, переданный при создании. Не является уникальным ключом операции."
          },
          "description": {
            "type": "string",
            "description": "Описание заказа; пустая строка, если не задано."
          },
          "status": {
            "type": "string",
            "description": "Состояние счёта; обработка каждого значения описана в разделе «Статусы».",
            "enum": [
              "pending",
              "confirming",
              "paid",
              "underpaid",
              "overpaid",
              "expired",
              "late",
              "review",
              "cancelled"
            ]
          },
          "status_version": {
            "type": "integer",
            "minimum": 0,
            "description": "Версия состояния. Сравнивайте с data.version в webhook; более старые события не должны перезаписывать новые."
          },
          "resolution": {
            "type": [
              "string",
              "null"
            ],
            "description": "Решение продавца по спорному платежу. Само по себе не изменяет статус и не переводит средства.",
            "enum": [
              "open",
              "accepted",
              "rejected",
              "refund_requested",
              "refund_recorded",
              null
            ]
          },
          "asset_id": {
            "type": "string",
            "description": "ID выбранного актива."
          },
          "asset": {
            "$ref": "#/components/schemas/InvoiceAsset",
            "description": "Актив, сеть, точность и контракт, необходимые для вашей формы оплаты."
          },
          "amount": {
            "type": "string",
            "description": "Полная запрошенная сумма в выбранном активе.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "received": {
            "type": "string",
            "description": "Сумма найденных валидных поступлений, включая ещё не подтверждённые. Не используйте её вместо status для выдачи заказа.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "remaining": {
            "type": "string",
            "description": "max(amount − received, 0). Сумма доплаты; точная десятичная строка.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Исходный адрес получения. Сохраняется и после завершения счёта для сверки. null в песочнице; показывайте для оплаты только при can_pay=true."
          },
          "memo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Обязательная метка/комментарий, если не null: XRP Destination Tag или TON comment. Передавайте без изменения вместе с адресом."
          },
          "payment_uri": {
            "type": [
              "string",
              "null"
            ],
            "description": "Данные для QR. Могут быть обычным адресом, а не URL. UTXO URI включает remaining, XRP X-address включает tag, TON URI включает сумму и comment. Для EVM это только адрес: сеть, токен и сумму передавайте отдельно. null, если can_pay=false."
          },
          "can_pay": {
            "type": "boolean",
            "description": "true только для реального неоплаченного/недоплаченного счёта до expires_at с remaining>0 и без отмены. Пересчитывается при каждом ответе."
          },
          "test_mode": {
            "type": "boolean",
            "description": "true означает симуляцию: реального платежа нет, address/memo/payment_uri равны null, can_pay=false."
          },
          "confirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Число подтверждений, учитываемое для текущего набора поступлений. Ориентируйтесь на status, а не только на счётчик."
          },
          "required_confirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Требуемое для счёта количество подтверждений."
          },
          "checkout_url": {
            "type": "string",
            "description": "Готовая платёжная ссылка. Секретный токен в URL даёт доступ к этому счёту; передавайте только соответствующему покупателю.",
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "description": "Время создания в UTC, ISO 8601.",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "description": "Срок оплаты в UTC, ISO 8601. После него не показывайте новые инструкции по оплате, даже если status ещё pending.",
            "format": "date-time"
          },
          "wallet_id": {
            "type": "string",
            "description": "ID управляемого кошелька для сбора через /v1/sweeps. Поле отсутствует для импортированных адресов и общих адресов с memo."
          },
          "orderId": {
            "type": "string",
            "description": "Поле совместимости только в списке счетов. Используйте order_id.",
            "deprecated": true
          },
          "assetId": {
            "type": "string",
            "description": "Поле совместимости только в списке счетов. Используйте asset_id.",
            "deprecated": true
          },
          "testMode": {
            "type": "boolean",
            "description": "Поле совместимости только в списке счетов. Используйте test_mode.",
            "deprecated": true
          },
          "createdAt": {
            "type": "string",
            "description": "Поле совместимости только в списке счетов. Используйте created_at.",
            "format": "date-time",
            "deprecated": true
          },
          "expiresAt": {
            "type": "string",
            "description": "Поле совместимости только в списке счетов. Используйте expires_at.",
            "format": "date-time",
            "deprecated": true
          },
          "checkoutUrl": {
            "type": "string",
            "description": "Поле совместимости только в списке счетов. Используйте checkout_url.",
            "deprecated": true
          },
          "requiredConfirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Поле совместимости только в списке счетов. Используйте required_confirmations.",
            "deprecated": true
          },
          "resolutionNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "Примечание продавца к решению по спорному платежу; поле списка."
          },
          "lastCheckedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Время последней проверки платежа; поле списка.",
            "format": "date-time"
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ],
            "description": "Обобщённый код последней ошибки проверки; поле списка. Служебные адреса не возвращаются."
          },
          "recheckRequested": {
            "type": "boolean",
            "description": "Запрошена повторная проверка из кабинета; поле списка."
          },
          "monitoringArchived": {
            "type": "boolean",
            "description": "Автоматическая проверка адреса остановлена. Для позднего перевода запустите повторную проверку счета в кабинете; поле списка."
          },
          "cancelledAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Время отмены счёта; поле списка.",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "order_id",
          "description",
          "status",
          "status_version",
          "resolution",
          "asset_id",
          "asset",
          "amount",
          "received",
          "remaining",
          "address",
          "memo",
          "payment_uri",
          "can_pay",
          "test_mode",
          "confirmations",
          "required_confirmations",
          "checkout_url",
          "created_at",
          "expires_at"
        ]
      },
      "InvoiceList": {
        "type": "object",
        "properties": {
          "invoices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListedInvoice"
            },
            "description": "Счета: сначала новые, затем ID по убыванию для одинакового времени.",
            "maxItems": 100
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Всего счетов с учётом фильтра."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "description": "Размер страницы.",
            "maximum": 100
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "description": "Смещение.",
            "maximum": 1000000
          }
        },
        "required": [
          "invoices",
          "total",
          "limit",
          "offset"
        ]
      },
      "AssetList": {
        "type": "object",
        "properties": {
          "assets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Asset"
            },
            "description": "Только активы, доступные для приёма именно вашему проекту. Пустой массив — сейчас нет доступных активов."
          }
        },
        "required": [
          "assets"
        ]
      },
      "Ok": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "true при успешном выполнении.",
            "example": true
          }
        },
        "required": [
          "ok"
        ]
      },
      "CreateAddress": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "string",
            "description": "Идентификатор сети семейства EVM, TRON, Solana, Sui или XRP.",
            "maxLength": 40,
            "example": "bsc"
          },
          "returnPrivateKey": {
            "type": "boolean",
            "description": "Выдать приватный ключ один раз в первом успешном ответе. Требует дополнительного права wallets:export.",
            "default": false
          }
        },
        "required": [
          "chain"
        ],
        "additionalProperties": false
      },
      "Address": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID управляемого кошелька, используется как walletId."
          },
          "chain": {
            "type": "string",
            "description": "Идентификатор сети."
          },
          "address": {
            "type": "string",
            "description": "Публичный адрес."
          },
          "keyFormat": {
            "type": "string",
            "description": "Формат ключа; XRP использует family seed, TON — 32-байтный seed кошелька V4R2.",
            "enum": [
              "secp256k1-hex",
              "ed25519-seed-hex",
              "xrpl-family-seed",
              "ton-v4r2-seed-hex"
            ]
          },
          "keyExported": {
            "type": "boolean",
            "description": "Запрашивался ли экспорт ключа при создании."
          },
          "createdAt": {
            "type": "string",
            "description": "Время UTC в формате YYYY-MM-DD HH:mm:ss.SSS. Присутствует в списке и при повторе; первый ответ может не содержать поле."
          }
        },
        "required": [
          "id",
          "chain",
          "address",
          "keyFormat",
          "keyExported"
        ]
      },
      "AddressCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID кошелька."
          },
          "chain": {
            "type": "string",
            "description": "Сеть."
          },
          "address": {
            "type": "string",
            "description": "Публичный адрес."
          },
          "keyFormat": {
            "type": "string",
            "description": "Формат ключа; XRP использует family seed, TON — 32-байтный seed кошелька V4R2.",
            "enum": [
              "secp256k1-hex",
              "ed25519-seed-hex",
              "xrpl-family-seed",
              "ton-v4r2-seed-hex"
            ]
          },
          "keyExported": {
            "type": "boolean",
            "description": "Был запрошен экспорт ключа."
          },
          "createdAt": {
            "type": "string",
            "description": "Время UTC YYYY-MM-DD HH:mm:ss.SSS; первый ответ может не содержать поле."
          },
          "replayed": {
            "type": "boolean",
            "description": "false для первого создания, true при повторе."
          },
          "privateKey": {
            "type": "string",
            "description": "Только при returnPrivateKey=true в первом ответе. Формат задаётся keyFormat: XRP — строка family seed, остальные — 32 байта hex с 0x. Никогда не сохраняйте в логах и не передавайте в браузер. Для TRON при импорте может требоваться убрать 0x."
          },
          "keyDelivery": {
            "type": "string",
            "description": "При запросе экспорта: one_time в первом ответе; not_repeated в повторном. Если первый ответ потерян, ключ повторно не выдаётся.",
            "enum": [
              "one_time",
              "not_repeated"
            ]
          }
        },
        "required": [
          "id",
          "chain",
          "address",
          "keyFormat",
          "keyExported",
          "replayed"
        ]
      },
      "AddressList": {
        "type": "object",
        "properties": {
          "addresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Address"
            },
            "description": "Последние 100 адресов, новые первыми; пагинации нет.",
            "maxItems": 100
          }
        },
        "required": [
          "addresses"
        ]
      },
      "CreateTransfer": {
        "type": "object",
        "properties": {
          "fundGas": {
            "type": "boolean",
            "description": "При нехватке нативной монеты на временном адресе пополнить её с главного кошелька этого магазина. Только для токенов и адресов без экспорта ключа. На заявку допускается одно пополнение не более недостающей суммы до feeBudget. Главные и архивные главные адреса не пополняются автоматически.",
            "default": true
          },
          "fundingFeeBudget": {
            "type": "string",
            "description": "Бюджет сетевой комиссии отдельной транзакции пополнения. По умолчанию feeBudget; те же пределы и точность. Пополнение имеет свою плату за заявку и отправку по 0.01 USDT ресурсов.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80
          },
          "walletId": {
            "type": "string",
            "description": "ID управляемого кошелька вашего проекта в выбранной сети.",
            "maxLength": 50
          },
          "assetId": {
            "type": "string",
            "description": "Актив каталога переводов EVM/TRON/Solana/Sui/XRP/TON, соответствующий сети кошелька.",
            "maxLength": 180
          },
          "destination": {
            "type": "string",
            "description": "Адрес получателя в той же сети; нулевой адрес и исходный адрес запрещены.",
            "maxLength": 160
          },
          "destinationTag": {
            "type": "integer",
            "minimum": 0,
            "description": "Только XRP: Destination Tag получателя. Целое число от 0 до 4294967295; если получателю нужен тег, передайте его явно. Для остальных сетей и /sweeps параметр запрещён.",
            "maximum": 4294967295
          },
          "amount": {
            "type": "string",
            "description": "Положительная сумма в единицах актива, строка без знака, пробелов и экспоненты. Не более decimals дробных знаков и 48 цифр целой части; не более 78 цифр в сумме минимальных единиц.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80,
            "example": "12.5"
          },
          "feeBudget": {
            "type": "string",
            "description": "Бюджет сетевой комиссии в НАТИВНОЙ монете (BNB/ETH/TRX/SOL/SUI/XRP/TON), не в токене. >0; ≤100 для TRON, ≤1 для остальных сетей. Точность нативной монеты; maxLength 80. Средства на комиссии нужны на исходном кошельке. В Base проверяется оценка дополнительной L1/operator fee с запасом, но протокол не позволяет жёстко ограничить L1-сбор; итог может измениться до включения в блок.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80,
            "example": "0.001"
          }
        },
        "required": [
          "walletId",
          "assetId",
          "destination",
          "amount",
          "feeBudget"
        ],
        "additionalProperties": false
      },
      "CreateSweep": {
        "type": "object",
        "properties": {
          "walletId": {
            "type": "string",
            "description": "ID управляемого кошелька вашего проекта в выбранной сети.",
            "maxLength": 50
          },
          "assetId": {
            "type": "string",
            "description": "Актив каталога переводов EVM/TRON/Solana/Sui/XRP/TON, соответствующий сети кошелька.",
            "maxLength": 180
          },
          "feeBudget": {
            "type": "string",
            "description": "Бюджет сетевой комиссии в НАТИВНОЙ монете (BNB/ETH/TRX/SOL/SUI/XRP/TON), не в токене. >0; ≤100 для TRON, ≤1 для остальных сетей. Точность нативной монеты; maxLength 80. Средства на комиссии нужны на исходном кошельке. В Base проверяется оценка дополнительной L1/operator fee с запасом, но протокол не позволяет жёстко ограничить L1-сбор; итог может измениться до включения в блок.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80,
            "example": "0.001"
          },
          "fundGas": {
            "type": "boolean",
            "description": "При нехватке нативной монеты на временном адресе пополнить её с главного кошелька этого магазина. Только для токенов и адресов без экспорта ключа. На заявку допускается одно пополнение не более недостающей суммы до feeBudget. Главные и архивные главные адреса не пополняются автоматически.",
            "default": true
          },
          "fundingFeeBudget": {
            "type": "string",
            "description": "Бюджет сетевой комиссии отдельной транзакции пополнения. По умолчанию feeBudget; те же пределы и точность. Пополнение имеет свою плату за заявку и отправку по 0.01 USDT ресурсов.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "maxLength": 80
          }
        },
        "required": [
          "walletId",
          "assetId",
          "feeBudget"
        ],
        "additionalProperties": false
      },
      "Transfer": {
        "type": "object",
        "properties": {
          "destinationTag": {
            "type": "integer",
            "minimum": 0,
            "description": "Destination Tag для XRP; поле отсутствует, если не задан.",
            "maximum": 4294967295
          },
          "purpose": {
            "type": "string",
            "description": "Назначение операции.",
            "enum": [
              "transfer",
              "gas_funding"
            ]
          },
          "parentTransferId": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID перевода, для которого выдана комиссия. null для обычного перевода."
          },
          "gasFunding": {
            "type": "boolean",
            "description": "У заявки есть зафиксированный главный кошелёк для возможного пополнения комиссии."
          },
          "id": {
            "type": "string",
            "description": "ID заявки."
          },
          "walletId": {
            "type": "string",
            "description": "Исходный управляемый кошелёк."
          },
          "assetId": {
            "type": "string",
            "description": "Актив перевода."
          },
          "destination": {
            "type": "string",
            "description": "Получатель, зафиксированный при создании заявки."
          },
          "amount": {
            "type": "string",
            "description": "Запрошенная сумма или строка max для сбора всего доступного остатка."
          },
          "sentAmount": {
            "type": "string",
            "description": "Фактическая подготовленная сумма; отсутствует до подготовки. Наличие не означает подтверждение.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "status": {
            "type": "string",
            "description": "Состояние обработки; только confirmed подтверждает выполнение.",
            "enum": [
              "queued",
              "blocked",
              "signed",
              "unknown",
              "submitted",
              "confirmed",
              "failed_onchain",
              "cancelled"
            ]
          },
          "sweep": {
            "type": "boolean",
            "description": "true для сбора через /v1/sweeps."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Хеш транзакции. Может быть известен до отправки; сам по себе не доказывает поступление."
          },
          "errorCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "Код препятствия/ошибки; перечень и действия — в разделе ошибок."
          },
          "createdAt": {
            "type": "string",
            "description": "Время создания UTC, YYYY-MM-DD HH:mm:ss.SSS."
          },
          "requestCost": {
            "type": "string",
            "description": "Стоимость принятой заявки, USDT.",
            "pattern": "^\\d+(\\.\\d+)?$",
            "example": "0.01"
          },
          "sendCost": {
            "type": "string",
            "description": "Стоимость отправки, USDT. 0.01 для submitted/confirmed/failed_onchain, иначе 0.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "replayed": {
            "type": "boolean",
            "description": "Только в ответе на POST /transfers или /sweeps: признак повтора."
          }
        },
        "required": [
          "id",
          "walletId",
          "assetId",
          "destination",
          "amount",
          "status",
          "sweep",
          "txid",
          "errorCode",
          "createdAt",
          "requestCost",
          "sendCost"
        ]
      },
      "TransferList": {
        "type": "object",
        "properties": {
          "transfers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transfer"
            },
            "description": "Последние 100 заявок, включая сборы; новые первыми, пагинации нет.",
            "maxItems": 100
          }
        },
        "required": [
          "transfers"
        ]
      },
      "BroadcastInput": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "string",
            "description": "Сеть с включённой отправкой для проекта. EVM, TRON, UTXO, XRP или Solana; TON и SUI не поддержаны этим методом."
          },
          "signedTransaction": {
            "type": "string",
            "description": "Уже подписанная транзакция: EVM — 0x-prefixed hex (chainId должен совпадать); UTXO/XRP — hex без 0x; Solana — base64; TRON — JSON, закодированный строкой, с signature, raw_data_hex и txID. Не передавайте приватные ключи.",
            "minLength": 10,
            "maxLength": 30000
          }
        },
        "required": [
          "chain",
          "signedTransaction"
        ],
        "additionalProperties": false
      },
      "Broadcast": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID заявки на публикацию."
          },
          "status": {
            "type": "string",
            "description": "submitted означает принятие сетью, а не финальное подтверждение. unknown — результат неизвестен; processing — обработка; rejected — отклонено.",
            "enum": [
              "processing",
              "unknown",
              "submitted",
              "rejected"
            ]
          },
          "txid": {
            "type": "string",
            "description": "Хеш транзакции, если известен."
          },
          "requestCost": {
            "type": "string",
            "description": "Стоимость заявки, USDT.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "sendCost": {
            "type": "string",
            "description": "0.01 USDT для submitted, иначе 0.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "reserved": {
            "type": "string",
            "description": "0.01 USDT при processing/unknown, иначе 0.",
            "pattern": "^\\d+(\\.\\d+)?$"
          }
        },
        "required": [
          "id",
          "status",
          "requestCost",
          "sendCost",
          "reserved"
        ]
      },
      "Rate": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "description": "Вид оплачиваемого действия.",
            "enum": [
              "send",
              "tracking",
              "send_request",
              "webhook"
            ]
          },
          "label": {
            "type": "string",
            "description": "Название."
          },
          "detail": {
            "type": "string",
            "description": "Когда начисляется стоимость."
          },
          "price": {
            "type": "string",
            "description": "Стоимость в USDT.",
            "pattern": "^\\d+(\\.\\d+)?$"
          }
        },
        "required": [
          "kind",
          "label",
          "detail",
          "price"
        ]
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "string",
            "description": "Учётный баланс ресурсов, USDT, до вычета резерва. Десятичная строка; может быть отрицательной после корректировки поступлений.",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "reserved": {
            "type": "string",
            "description": "Резерв на незавершённые отправки.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "available": {
            "type": "string",
            "description": "balance − reserved; может быть отрицательной строкой."
          },
          "currency": {
            "type": "string",
            "description": "Валюта ресурсов.",
            "enum": [
              "USDT"
            ]
          },
          "testMode": {
            "type": "boolean",
            "description": "Ресурсы песочницы; не реальные средства."
          },
          "rates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rate"
            },
            "description": "Текущие тарифы сервиса."
          }
        },
        "required": [
          "balance",
          "reserved",
          "available",
          "currency",
          "testMode",
          "rates"
        ]
      },
      "ValidationField": {
        "type": "object",
        "properties": {
          "path": {
            "type": "array",
            "items": {
              "type": [
                "string",
                "integer"
              ]
            },
            "description": "Путь до неверного поля, включая индексы массива."
          },
          "message": {
            "type": "string",
            "description": "Описание нарушения."
          }
        },
        "required": [
          "path",
          "message"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Сообщение для человека; формулировка может изменяться."
          },
          "code": {
            "type": "string",
            "description": "Машинный код, если определён. Не все ошибки имеют code."
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationField"
            },
            "description": "Детали ошибок валидации, если доступны."
          },
          "requestId": {
            "type": "string",
            "description": "В конфликте broadcast с той же транзакцией и новым ключом — ID исходной заявки. Продолжайте с исходным Idempotency-Key."
          },
          "balance": {
            "type": "string",
            "description": "В ошибке 402 — баланс ресурсов."
          },
          "available": {
            "type": "string",
            "description": "В ошибке 402 — доступные ресурсы."
          },
          "reserved": {
            "type": "string",
            "description": "В ошибке 402 — резерв."
          },
          "currency": {
            "type": "string",
            "description": "В ошибке 402 — USDT."
          }
        },
        "required": [
          "error"
        ]
      },
      "WebhookData": {
        "type": "object",
        "properties": {
          "invoice_id": {
            "type": "string",
            "description": "ID счёта."
          },
          "test_mode": {
            "type": "boolean",
            "description": "Симуляция, не реальная оплата."
          },
          "order_id": {
            "type": "string",
            "description": "Номер вашего заказа."
          },
          "status": {
            "type": "string",
            "description": "Статус на момент события.",
            "enum": [
              "pending",
              "confirming",
              "paid",
              "underpaid",
              "overpaid",
              "expired",
              "late",
              "review",
              "cancelled"
            ]
          },
          "amount": {
            "type": "string",
            "description": "Сумма счёта.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "received": {
            "type": "string",
            "description": "Сумма валидных поступлений, включая неподтверждённые.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "asset_id": {
            "type": "string",
            "description": "ID актива."
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "description": "Монотонная версия состояния конкретного счёта."
          },
          "resolution": {
            "type": [
              "string",
              "null"
            ],
            "description": "Решение продавца по спорному платежу. Само по себе не изменяет статус и не переводит средства.",
            "enum": [
              "open",
              "accepted",
              "rejected",
              "refund_requested",
              "refund_recorded",
              null
            ]
          }
        },
        "required": [
          "invoice_id",
          "test_mode",
          "order_id",
          "status",
          "amount",
          "received",
          "asset_id",
          "version",
          "resolution"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Уникальный ID события, постоянный при повторной доставке."
          },
          "type": {
            "type": "string",
            "description": "invoice.<status> либо invoice.reviewed после решения продавца.",
            "enum": [
              "invoice.pending",
              "invoice.confirming",
              "invoice.paid",
              "invoice.underpaid",
              "invoice.overpaid",
              "invoice.expired",
              "invoice.late",
              "invoice.review",
              "invoice.cancelled",
              "invoice.reviewed"
            ]
          },
          "created_at": {
            "type": "string",
            "description": "Время создания события (не время конкретной попытки доставки).",
            "format": "date-time"
          },
          "data": {
            "$ref": "#/components/schemas/WebhookData"
          }
        },
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ]
      },
      "CheckoutAsset": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор актива. Берите из GET /v1/assets; не составляйте по символу валюты.",
            "example": "bsc:usdt"
          },
          "chain": {
            "type": "string",
            "description": "Идентификатор сети.",
            "example": "bsc"
          },
          "symbol": {
            "type": "string",
            "description": "Тикер актива; не уникален между сетями.",
            "example": "USDT"
          },
          "decimals": {
            "type": "integer",
            "minimum": 0,
            "description": "Количество знаков после запятой; 1 токен = 10^decimals минимальных единиц.",
            "maximum": 255,
            "example": 18
          },
          "contract": {
            "type": "string",
            "description": "Идентификатор токена, отсутствует у нативной монеты."
          }
        },
        "required": [
          "id",
          "chain",
          "symbol",
          "decimals"
        ]
      },
      "Checkout": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID счёта в CRYPTOSHA.",
            "example": "inv_example"
          },
          "orderId": {
            "type": "string",
            "description": "Ваш orderId, переданный при создании. Не является уникальным ключом операции."
          },
          "description": {
            "type": "string",
            "description": "Описание заказа; пустая строка, если не задано."
          },
          "assetId": {
            "type": "string",
            "description": "ID выбранного актива."
          },
          "status": {
            "type": "string",
            "description": "Состояние счёта; обработка каждого значения описана в разделе «Статусы».",
            "enum": [
              "pending",
              "confirming",
              "paid",
              "underpaid",
              "overpaid",
              "expired",
              "late",
              "review",
              "cancelled"
            ]
          },
          "amount": {
            "type": "string",
            "description": "Полная запрошенная сумма в выбранном активе.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "received": {
            "type": "string",
            "description": "Сумма найденных валидных поступлений, включая ещё не подтверждённые. Не используйте её вместо status для выдачи заказа.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "remaining": {
            "type": "string",
            "description": "max(amount − received, 0). Сумма доплаты; точная десятичная строка.",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "expiresAt": {
            "type": "string",
            "description": "Срок оплаты в UTC, ISO 8601. После него не показывайте новые инструкции по оплате, даже если status ещё pending.",
            "format": "date-time"
          },
          "confirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Число подтверждений, учитываемое для текущего набора поступлений. Ориентируйтесь на status, а не только на счётчик."
          },
          "requiredConfirmations": {
            "type": "integer",
            "minimum": 0,
            "description": "Требуемое для счёта количество подтверждений."
          },
          "brandName": {
            "type": "string",
            "description": "Название проекта."
          },
          "brandColor": {
            "type": "string",
            "description": "Цвет проекта, #RRGGBB."
          },
          "testMode": {
            "type": "boolean",
            "description": "true означает симуляцию: реального платежа нет, address/memo/payment_uri равны null, can_pay=false."
          },
          "localMode": {
            "type": "boolean",
            "description": "Признак локального окружения; не показатель оплаты."
          },
          "canPay": {
            "type": "boolean",
            "description": "true только для реального неоплаченного/недоплаченного счёта до expires_at с remaining>0 и без отмены. Пересчитывается при каждом ответе."
          },
          "asset": {
            "$ref": "#/components/schemas/CheckoutAsset"
          },
          "address": {
            "type": "string",
            "description": "Только при canPay=true. При остальных состояниях отсутствует."
          },
          "memo": {
            "type": "string",
            "description": "Метка платежа, если требуется; только при canPay=true."
          },
          "paymentUri": {
            "type": "string",
            "description": "Данные QR, только при canPay=true; те же правила, что payment_uri счёта."
          }
        },
        "required": [
          "id",
          "orderId",
          "description",
          "assetId",
          "status",
          "amount",
          "received",
          "remaining",
          "expiresAt",
          "confirmations",
          "requiredConfirmations",
          "brandName",
          "brandColor",
          "testMode",
          "localMode",
          "canPay",
          "asset"
        ]
      },
      "HealthBar": {
        "type": "object",
        "properties": {
          "at": {
            "type": "string",
            "description": "Начало интервала UTC.",
            "format": "date-time"
          },
          "samples": {
            "type": "integer",
            "minimum": 0,
            "description": "Количество проверок."
          },
          "failures": {
            "type": "integer",
            "minimum": 0,
            "description": "Количество неудачных проверок."
          },
          "latencyMs": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Средняя задержка, миллисекунды; null без измерений."
          }
        },
        "required": [
          "at",
          "samples",
          "failures",
          "latencyMs"
        ]
      },
      "HealthNode": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Обезличенный идентификатор внутри сети; не адрес узла."
          },
          "name": {
            "type": "string",
            "description": "Нейтральная подпись узла."
          },
          "role": {
            "type": "string",
            "description": "Роль.",
            "enum": [
              "primary",
              "fallback"
            ]
          },
          "status": {
            "type": "string",
            "description": "Последний свежий результат.",
            "enum": [
              "up",
              "down",
              "unknown"
            ]
          },
          "checkedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Последняя проверка.",
            "format": "date-time"
          },
          "latencyMs": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Последняя задержка в миллисекундах."
          },
          "uptime": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100,
            "description": "Доля успешных измерений за окно, в процентах; null при отсутствии данных."
          },
          "samples": {
            "type": "integer",
            "minimum": 0,
            "description": "Проверок за окно."
          },
          "failures": {
            "type": "integer",
            "minimum": 0,
            "description": "Сбоев за окно."
          },
          "bars": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthBar"
            },
            "description": "Интервалы по возрастанию времени."
          }
        },
        "required": [
          "id",
          "name",
          "role",
          "status",
          "checkedAt",
          "latencyMs",
          "uptime",
          "samples",
          "failures",
          "bars"
        ]
      },
      "HealthChain": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор сети."
          },
          "name": {
            "type": "string",
            "description": "Название сети."
          },
          "symbol": {
            "type": "string",
            "description": "Тикер нативной монеты."
          },
          "color": {
            "type": "string",
            "description": "Цвет #RRGGBB."
          },
          "status": {
            "type": "string",
            "description": "Агрегированное состояние.",
            "enum": [
              "up",
              "fallback",
              "down",
              "unknown",
              "unconfigured"
            ]
          },
          "activeProvider": {
            "type": [
              "string",
              "null"
            ],
            "description": "Обезличенный id доступного узла; не поставщик и не URL."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthNode"
            }
          }
        },
        "required": [
          "id",
          "name",
          "symbol",
          "color",
          "status",
          "activeProvider",
          "nodes"
        ]
      },
      "Health": {
        "type": "object",
        "properties": {
          "generatedAt": {
            "type": "string",
            "description": "Время снимка.",
            "format": "date-time"
          },
          "period": {
            "type": "string",
            "description": "Окно истории.",
            "enum": [
              "24h",
              "7d",
              "30d"
            ]
          },
          "intervalMs": {
            "type": "integer",
            "minimum": 0,
            "description": "Интервал проверок в миллисекундах."
          },
          "staleAfterMs": {
            "type": "integer",
            "minimum": 0,
            "description": "Возраст измерения, после которого статус становится unknown, миллисекунды."
          },
          "windowStart": {
            "type": "string",
            "description": "Начало окна.",
            "format": "date-time"
          },
          "windowEnd": {
            "type": "string",
            "description": "Конец окна.",
            "format": "date-time"
          },
          "barMs": {
            "type": "integer",
            "minimum": 0,
            "description": "Размер интервала графика, миллисекунды."
          },
          "chains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HealthChain"
            }
          }
        },
        "required": [
          "generatedAt",
          "period",
          "intervalMs",
          "staleAfterMs",
          "windowStart",
          "windowEnd",
          "barMs",
          "chains"
        ]
      },
      "ServiceHealth": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "ok — API и база отвечают; не подтверждает возможность приёма конкретного платежа.",
            "enum": [
              "ok"
            ]
          }
        },
        "required": [
          "status"
        ]
      }
    }
  }
}
