{
  "openapi": "3.1.0",
  "info": {
    "title": "ULTA Crypto Payment Service",
    "version": "0.2.1",
    "description": "Test checkout: mainnet выключен; checkout доступен только для тестового Nile при настроенных RPC. Время Unix ms, суммы результата — атомарные строки. API-ключ только на backend магазина."
  },
  "servers": [
    {
      "url": "https://pay.coolnik.ru"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/payment-methods": {
      "get": {
        "summary": "Разрешённые методы проекта",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environment": {
                      "const": "test"
                    },
                    "methods": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Route"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoices": {
      "post": {
        "summary": "Создать тестовый счёт",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "external_order_id",
                  "attempt_no",
                  "amount",
                  "payment_method_id"
                ],
                "properties": {
                  "external_order_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "attempt_no": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,71})(\\.[0-9]{1,6})?$",
                    "example": "10.000000",
                    "description": "Положительная сумма в USDT, до uint256 атомов"
                  },
                  "payment_method_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoices/{id}": {
      "get": {
        "summary": "Актуальное состояние счёта",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/v1/invoices/{id}/cancel": {
      "post": {
        "summary": "Отменить неоплаченный счёт",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ]
      }
    },
    "/v1/invoices/{id}/checkout-sessions": {
      "post": {
        "summary": "Создать сессию тестового checkout",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "invoice_id",
                    "checkout_token",
                    "expires_at",
                    "checkout_url"
                  ],
                  "properties": {
                    "invoice_id": {
                      "type": "string"
                    },
                    "checkout_token": {
                      "type": "string"
                    },
                    "checkout_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expires_at": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ]
      }
    },
    "/v1/events": {
      "get": {
        "summary": "До 100 событий после курсора",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "cursor": {
                            "type": "string"
                          },
                          "payload": {
                            "$ref": "#/components/schemas/Event"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "after",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,19}$",
              "default": "0"
            },
            "description": "Не более 9223372036854775807. Хранить как строку."
          }
        ]
      }
    },
    "/health/live": {
      "get": {
        "summary": "Процесс запущен",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/health/ready": {
      "get": {
        "summary": "Готовность БД и журнала для integration preview",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/health/payments": {
      "get": {
        "summary": "Платёжный процессинг ещё не включён",
        "security": [],
        "responses": {
          "503": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/observer": {
      "get": {
        "summary": "Состояние проверок, интервалы и диагностика без секретов",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "state": {
                      "enum": [
                        "configured",
                        "degraded",
                        "configuration-required"
                      ]
                    },
                    "poll_interval_seconds": {
                      "type": "integer",
                      "minimum": 30,
                      "maximum": 300
                    },
                    "idle_interval_seconds": {
                      "type": "integer",
                      "minimum": 30,
                      "maximum": 3600,
                      "description": "Не меньше poll_interval_seconds"
                    },
                    "settings_revision": {
                      "type": "integer"
                    },
                    "last_run_at": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "last_code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "network": {
                      "const": "tron-nile"
                    },
                    "mainnet_enabled": {
                      "const": false
                    },
                    "providers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "operator": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "queue": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "state": {
                            "enum": [
                              "PENDING",
                              "PAID",
                              "REVIEW"
                            ]
                          },
                          "count": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "diagnostics": {
                      "$ref": "#/components/schemas/RpcDiagnostics"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ]
      },
      "put": {
        "summary": "Сохранить интервалы проверок для всех магазинов",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "poll_interval_seconds": {
                      "type": "integer",
                      "minimum": 30,
                      "maximum": 300
                    },
                    "idle_interval_seconds": {
                      "type": "integer",
                      "minimum": 30,
                      "maximum": 3600,
                      "description": "Не меньше poll_interval_seconds"
                    },
                    "revision": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "poll_interval_seconds",
                  "idle_interval_seconds"
                ],
                "properties": {
                  "poll_interval_seconds": {
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 300
                  },
                  "idle_interval_seconds": {
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 3600,
                    "description": "Не меньше poll_interval_seconds"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/observer/diagnostics": {
      "post": {
        "summary": "Запустить проверку RPC: только чтение, не чаще раза в минуту",
        "responses": {
          "202": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RpcDiagnostics"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "description": "Повторный POST присоединяется к текущей проверке или возвращает её недавний результат. Результат доступен через GET /v1/admin/observer. Не меняет счета и конфигурацию RPC."
      }
    },
    "/v1/admin/projects": {
      "get": {
        "summary": "Список проектов без секретных ключей",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ]
      },
      "post": {
        "summary": "Создать проект с кошельками",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Project"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "api_key": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "name"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{1,49}$"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "wallets": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "$ref": "#/components/schemas/Wallet"
                    }
                  },
                  "routes": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "$ref": "#/components/schemas/RouteInput"
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/projects/{id}": {
      "put": {
        "summary": "Изменить настройки для новых счетов",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]{1,49}$"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "name",
                  "wallets",
                  "routes",
                  "enabled"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "wallets": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "$ref": "#/components/schemas/Wallet"
                    }
                  },
                  "routes": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "$ref": "#/components/schemas/RouteInput"
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/projects/{id}/rotate-key": {
      "post": {
        "summary": "Сменить API-ключ магазина",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]{1,49}$"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ]
      }
    },
    "/v1/admin/projects/{id}/test-invoice": {
      "post": {
        "summary": "Создать тестовый счёт и checkout URL",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoice_id": {
                      "type": "string"
                    },
                    "checkout_url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]{1,49}$"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,100}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "external_order_id",
                  "attempt_no",
                  "amount",
                  "payment_method_id"
                ],
                "properties": {
                  "external_order_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  },
                  "attempt_no": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,71})(\\.[0-9]{1,6})?$",
                    "example": "10.000000",
                    "description": "Положительная сумма в USDT, до uint256 атомов"
                  },
                  "payment_method_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkout": {
      "get": {
        "summary": "Данные одного счёта для плательщика",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoice_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "PENDING",
                        "PARTIALLY_PAID",
                        "PAID",
                        "EXPIRED",
                        "CANCELLED"
                      ]
                    },
                    "version": {
                      "type": "integer"
                    },
                    "amount": {
                      "type": "string",
                      "description": "Человекочитаемая сумма, не атомы"
                    },
                    "received": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string",
                      "enum": [
                        "tron-nile",
                        "ton-testnet"
                      ]
                    },
                    "recipient": {
                      "type": "string"
                    },
                    "contract": {
                      "type": "string"
                    },
                    "environment": {
                      "const": "test"
                    },
                    "expires_at": {
                      "type": "integer"
                    },
                    "server_time": {
                      "type": "integer"
                    },
                    "expected_genesis": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "wallet_payment_available": {
                      "type": "boolean"
                    },
                    "payment_check": {
                      "type": "object",
                      "properties": {
                        "state": {
                          "type": "string",
                          "enum": [
                            "NOT_STARTED",
                            "PENDING",
                            "PAID",
                            "REVIEW"
                          ]
                        },
                        "last_code": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "last_checked_at": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "txid": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "checkoutAuth": []
          }
        ]
      }
    },
    "/v1/checkout/tron-instruction": {
      "post": {
        "summary": "Получить заранее связанную неподписанную инструкцию",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "intent": {
                      "type": "object"
                    },
                    "transaction": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ошибка",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "checkoutAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "sender"
                ],
                "properties": {
                  "sender": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "ownerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Отдельный секретный ключ владельца; не ключ магазина."
      },
      "checkoutAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Только checkout_token конкретного счёта."
      }
    },
    "schemas": {
      "Route": {
        "type": "object",
        "required": [
          "id",
          "network",
          "contract",
          "recipient",
          "mode"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "network": {
            "type": "string",
            "enum": [
              "tron-nile",
              "ton-testnet"
            ]
          },
          "contract": {
            "type": "string"
          },
          "recipient": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "TRON_BOUND_TRANSACTION",
              "TRON_SHARED_REVIEW",
              "TON_REFERENCE"
            ]
          },
          "wallet_id": {
            "type": "string"
          }
        }
      },
      "Invoice": {
        "type": "object",
        "required": [
          "id",
          "project_id",
          "order_id",
          "attempt",
          "route",
          "due",
          "received",
          "excess",
          "reference",
          "created_at",
          "expires_at",
          "cancelled_at",
          "status",
          "version"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "attempt": {
            "type": "integer",
            "minimum": 1
          },
          "route": {
            "$ref": "#/components/schemas/Route"
          },
          "due": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]*)$",
            "description": "Атомарные единицы: 1000000 = 1 USDT"
          },
          "received": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]*)$",
            "description": "Атомарные единицы: 1000000 = 1 USDT"
          },
          "excess": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]*)$",
            "description": "Атомарные единицы: 1000000 = 1 USDT"
          },
          "reference": {
            "type": "string"
          },
          "created_at": {
            "type": "integer",
            "format": "int64"
          },
          "expires_at": {
            "type": "integer",
            "format": "int64"
          },
          "cancelled_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PARTIALLY_PAID",
              "PAID",
              "EXPIRED",
              "CANCELLED"
            ]
          },
          "version": {
            "type": "integer"
          }
        }
      },
      "Event": {
        "type": "object",
        "required": [
          "event_id",
          "schema_version",
          "environment",
          "type",
          "invoice",
          "occurred_at"
        ],
        "properties": {
          "event_id": {
            "type": "string"
          },
          "schema_version": {
            "const": 1
          },
          "environment": {
            "const": "test"
          },
          "type": {
            "type": "string",
            "enum": [
              "invoice.paid",
              "invoice.partially_paid",
              "invoice.expired",
              "invoice.cancelled"
            ]
          },
          "invoice": {
            "$ref": "#/components/schemas/Invoice"
          },
          "occurred_at": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Wallet": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "network",
          "recipient"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9-]*$",
            "maxLength": 50
          },
          "network": {
            "type": "string",
            "enum": [
              "ton-mainnet",
              "ton-testnet",
              "tron-mainnet",
              "tron-nile"
            ]
          },
          "recipient": {
            "type": "string",
            "maxLength": 100
          }
        }
      },
      "RouteInput": {
        "type": "object",
        "required": [
          "id",
          "network",
          "contract",
          "mode"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "network": {
            "type": "string",
            "enum": [
              "tron-nile",
              "ton-testnet"
            ]
          },
          "contract": {
            "type": "string"
          },
          "recipient": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "TRON_BOUND_TRANSACTION",
              "TRON_SHARED_REVIEW",
              "TON_REFERENCE"
            ]
          },
          "wallet_id": {
            "type": "string"
          }
        },
        "anyOf": [
          {
            "required": [
              "recipient"
            ]
          },
          {
            "required": [
              "wallet_id"
            ]
          }
        ],
        "additionalProperties": false
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150
          },
          "wallets": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/Wallet"
            }
          },
          "routes": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/RouteInput"
            }
          },
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "wallets",
          "routes",
          "enabled"
        ]
      },
      "RpcDiagnostics": {
        "type": "object",
        "properties": {
          "running": {
            "type": "boolean"
          },
          "started_at": {
            "type": [
              "integer",
              "null"
            ]
          },
          "result": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "checked_at": {
                "type": "integer"
              },
              "network": {
                "const": "tron-nile"
              },
              "scope": {
                "const": "genesis-and-solidified-head-only"
              },
              "payment_verified": {
                "const": false
              },
              "providers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "operator": {
                      "type": "string"
                    },
                    "state": {
                      "enum": [
                        "reachable",
                        "unavailable"
                      ]
                    },
                    "block_number": {
                      "type": "integer"
                    },
                    "block_time": {
                      "type": "integer"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              },
              "agreement": {
                "type": "object",
                "properties": {
                  "state": {
                    "enum": [
                      "verified",
                      "unavailable"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "block_number": {
                    "type": "integer"
                  },
                  "block_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
