{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Kevmi — серверный API",
    "version": "2026-10-23.12",
    "description": "Kevmi API: вход через Telegram, сессии, счета продавца, зашифрованная оплата покупателем, поддержка, уведомления, приложения и доставка вебхуков. Только разовые прямые платежи. JSON-ответы используют no-store. Метки времени — UTC Unix в миллисекундах, если не указано иное. Живая оплата использует настроенный внешний шлюз; поля карты и банковского кода шифруются в браузере и расшифровываются только шлюзом. Новые списания требуют одобрения последней версии приложения магазина. Создание счета не списывает средства с покупателя.",
    "x-updated-at": "2026-10-23"
  },
  "servers": [
    {
      "url": "https://kevmi.one",
      "description": "Публичный origin проекта; отдельная платформа хостинга может дополнительно ограничивать доступ."
    }
  ],
  "externalDocs": {
    "description": "Публичная документация продукта",
    "url": "https://kevmi.one/docs"
  },
  "tags": [
    {
      "name": "Service",
      "description": "Публичные сведения о состоянии."
    },
    {
      "name": "Auth",
      "description": "Регистрация и вход используют один подтверждённый сценарий Telegram."
    },
    {
      "name": "Account",
      "description": "Настройки только текущего пользователя."
    },
    {
      "name": "Payment links",
      "description": "Серверные счета текущего магазина. Цена, валюта, плательщик НДС, имя продавца и расчёт сохраняются неизменно."
    },
    {
      "name": "Checkout",
      "description": "Чтение отдельного счёта без аккаунта. Доступность оплаты проверяется отдельно."
    },
    {
      "name": "Support",
      "description": "Публичная база знаний и собственные обращения."
    },
    {
      "name": "Notifications",
      "description": "Собственный центр событий, прочтение на сайте и независимое состояние доставки Telegram."
    },
    {
      "name": "Telegram",
      "description": "Webhook бота; не платёжный webhook."
    },
    {
      "name": "Disabled payments",
      "description": "Неподдерживаемые устаревшие денежные маршруты и выполнение выплат. Публичный поток оплаты имеет собственные документированные конечные точки."
    },
    {
      "name": "Merchant API",
      "description": "Ограниченные серверные счета и неизменяемая история событий."
    },
    {
      "name": "Webhooks",
      "description": "Проверенные HTTPS-конечные точки, подписанные события, попытки доставки и повторные попытки."
    },
    {
      "name": "Applications",
      "description": "Аутентифицированные приложения сайта и индивидуальное отслеживание."
    },
    {
      "name": "Moderation",
      "description": "Модераторы Telegram из белого списка; каждое решение проверяется по версии."
    },
    {
      "name": "Gateway events",
      "description": "События шлюза из источника проверяются, затем авторитетный платеж читается через аутентифицированный серверный транспорт. Вебхуки для продавца используют отдельную подпись и очередь доставки."
    }
  ],
  "security": [],
  "x-disabled-route-prefixes": [
    "/api/payments",
    "/api/payouts",
    "/api/gateway",
    "/api/linzapay"
  ],
  "x-disabled-route-behavior": "Legacy unscoped direct-money routes and payout execution remain disabled. Authenticated /api/v1/payments creates invoices; /api/checkout/{token} exposes the separate buyer checkout flow. POST /api/gateway/webhook accepts signed gateway events.",
  "paths": {
    "/api/config": {
      "get": {
        "tags": [
          "Service"
        ],
        "operationId": "getConfig",
        "summary": "Фактическая готовность интеграций",
        "responses": {
          "200": {
            "description": "Конфигурация без секретов.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Config"
                }
              }
            }
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "Service"
        ],
        "operationId": "getHealth",
        "summary": "Состояние API и таблиц D1",
        "description": "not_configured допускает status=ok: публичные страницы и поиск могут работать без DB. Наличие DB с недоступными таблицами даёт 503/degraded. Ответ не проверяет работоспособность Telegram или модели по сети.",
        "responses": {
          "200": {
            "description": "Хранилище ready или not_configured.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "503": {
            "description": "D1 недоступна либо неожиданная ошибка сервиса.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Health"
                    },
                    {
                      "$ref": "#/components/schemas/Error"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/me": {
      "get": {
        "tags": [
          "Auth"
        ],
        "operationId": "getCurrentSession",
        "summary": "Текущая сессия и CSRF",
        "security": [
          {},
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "authenticated=false без действующей сессии.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Anonymous"
                    },
                    {
                      "$ref": "#/components/schemas/CurrentSession"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/auth/telegram/start": {
      "post": {
        "tags": [
          "Auth"
        ],
        "operationId": "startTelegramLogin",
        "summary": "Начать вход или регистрацию",
        "description": "Создаёт challenge на 300 секунд и HttpOnly cookie browser proof; максимум 6 запусков в минуту по хешу адреса. Сравните шестизначный код на сайте и в личном чате бота.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Запрос входа создан; cookie proof привязывает его к исходному браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Set-Cookie": {
                "schema": {
                  "type": "string"
                },
                "description": "Secure; HttpOnly; SameSite=Lax; Path=/. Значение сессии не доступно JavaScript. При завершении входа также удаляется cookie browser proof."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginChallenge"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/auth/telegram/complete": {
      "post": {
        "tags": [
          "Auth"
        ],
        "operationId": "completeTelegramLogin",
        "summary": "Завершить подтверждённый вход",
        "description": "Требует proof cookie из start и того же браузера. Pending возвращает 202. После подтверждения ботом запрос выдаёт одну сессию на 24 часа. Максимум 90 проверок в минуту на challenge. Значение Telegram ID из браузера не принимается.",
        "security": [
          {
            "browserProof": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "challengeId": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9_-]{43}$"
                  }
                },
                "required": [
                  "challengeId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Аккаунт создан/обновлён, сессия выдана.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Set-Cookie": {
                "schema": {
                  "type": "string"
                },
                "description": "Secure; HttpOnly; SameSite=Lax; Path=/. Значение сессии не доступно JavaScript. При завершении входа также удаляется cookie browser proof."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletedLogin"
                }
              }
            }
          },
          "202": {
            "description": "Ожидается подтверждение в Telegram.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "pending"
                    }
                  },
                  "required": [
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "410": {
            "description": "Пятиминутный запрос входа истёк.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_EXPIRED"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "operationId": "logoutCurrentSession",
        "summary": "Завершить текущую сессию",
        "description": "Тело не требуется и не читается. /logout в боте отдельно завершает все сессии аккаунта.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Сессия удалена, cookie очищена.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Set-Cookie": {
                "schema": {
                  "type": "string"
                },
                "description": "Secure; HttpOnly; SameSite=Lax; Path=/. Значение сессии не доступно JavaScript. При завершении входа также удаляется cookie browser proof."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "loggedOut": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "loggedOut"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/account/settings": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getAccountSettings",
        "summary": "Настройки текущего пользователя",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Публичная часть собственного профиля.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ]
      },
      "patch": {
        "tags": [
          "Account"
        ],
        "operationId": "updateAccountSettings",
        "summary": "Изменить название, плательщика НДС или уведомления",
        "description": "Все поля необязательны; частичный patch. Сервер сохраняет настройку vatPayer, но не создаёт денежную операцию. Переключатели payments/payouts не подключают платёжный шлюз.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingsPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Обновлённый профиль.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/support/ask": {
      "post": {
        "tags": [
          "Support"
        ],
        "operationId": "askDocumentation",
        "summary": "Ответ по всей публичной базе знаний",
        "description": "Публичный вопрос без сессии и CSRF. Переданный Origin должен совпасть с APP_ORIGIN; агенты могут не отправлять Origin. В AI-режиме сервер передаёт все опубликованные статьи, факты, каталог страниц и готовность функций. Необязательные history и pageContext используются только как недоверенный контекст вопроса. Доступа к аккаунтам, деньгам, приватным обращениям и инструментам у модели нет. При D1 действует лимит 12 вопросов/минуту по хешу адреса. Режим ai требует D1, корректной конфигурации провайдера и квоты: по умолчанию 60 генераций/час на весь сервис. Готовность конфигурации не подтверждает доступность внешнего API. Ошибка провайдера, превышение квоты или некорректный ответ возвращают search с aiUnavailable=true и HTTP 200. Без генеративной конфигурации возвращается обычный search.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект до 65 536 байт. Неизвестные поля отклоняются. Длины текстов проверяются после trim.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SupportQuestion"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ответ либо найденный материал с проверенными ссылками на опубликованные статьи.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportAnswer"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/support/tickets": {
      "get": {
        "tags": [
          "Support"
        ],
        "operationId": "listOwnTickets",
        "summary": "Последние 30 собственных обращений",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "По убыванию createdAt; возвращаются последние 30 записей.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tickets": {
                      "type": "array",
                      "maxItems": 30,
                      "items": {
                        "$ref": "#/components/schemas/Ticket"
                      }
                    }
                  },
                  "required": [
                    "tickets"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "post": {
        "tags": [
          "Support"
        ],
        "operationId": "createOwnTicket",
        "summary": "Сохранить обращение",
        "description": "До 6 обращений в час на пользователя, общая квота сайта и бота. Сохранение создаёт обращение в аккаунте. Используйте его номер для уточнения статуса.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "minLength": 1,
                    "x-trimmedMaxLength": 120,
                    "x-trimmedMinLength": 1,
                    "description": "Пробелы по краям удаляются. Длина после удаления: 1–120 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
                  },
                  "message": {
                    "type": "string",
                    "minLength": 5,
                    "x-trimmedMaxLength": 4000,
                    "x-trimmedMinLength": 5,
                    "description": "Пробелы по краям удаляются. Длина после удаления: 5–4000 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
                  }
                },
                "required": [
                  "subject",
                  "message"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Обращение сохранено.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/support/tickets/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^tkt_[a-f0-9-]{36}$"
          },
          "description": "Идентификатор собственного обращения."
        }
      ],
      "get": {
        "tags": [
          "Support"
        ],
        "operationId": "getOwnTicket",
        "summary": "Прочитать своё обращение",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Чужое и отсутствующее обращение одинаково дают 404.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "patch": {
        "tags": [
          "Support"
        ],
        "operationId": "closeOwnTicket",
        "summary": "Закрыть своё обращение",
        "description": "Метод принимает только status=closed. Он не поддерживает повторное открытие, редактирование сообщений или отправку ответов.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "const": "closed"
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Обращение закрыто.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "closed": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "closed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/notifications": {
      "get": {
        "tags": [
          "Notifications"
        ],
        "operationId": "listOwnNotifications",
        "summary": "Страница собственных уведомлений",
        "description": "До 30 записей: createdAt DESC, затем id DESC. Чтение списка не меняет readAt и не запускает доставку. unreadCount — общее число непрочитанных событий текущего пользователя, независимо от страницы. Поля владельца, Telegram ID и секреты не возвращаются.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "name": "unread",
            "in": "query",
            "description": "1 — только непрочитанные; 0 или отсутствие — все события.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "nextCursor предыдущего ответа. Передавайте без изменений через URLSearchParams; формат createdAt:id, createdAt — безопасное целое в миллисекундах.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,16}:ntf_[A-Za-z0-9-]{1,80}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "События с независимыми состояниями прочтения и доставки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationsPage"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/notifications/read": {
      "patch": {
        "tags": [
          "Notifications"
        ],
        "operationId": "markOwnNotificationsRead",
        "summary": "Отметить собственные уведомления прочитанными",
        "description": "Принимается одна из двух форм: ids либо all:true вместе с before. before — дата последнего уже наблюдавшегося события; значение не должно быть позже текущего времени сервера. Более новые события сохраняются непрочитанными. Повторный запрос идемпотентен: readAt уже прочитанных записей не меняется. Чужие и отсутствующие ids не изменяются и не раскрываются. status и sentAt доставки Telegram остаются прежними.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadNotifications"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Количество новых отметок, время операции и актуальный счётчик.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadNotificationsResult"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/notifications/test": {
      "post": {
        "tags": [
          "Notifications"
        ],
        "operationId": "testOwnNotification",
        "summary": "Отправить тестовое уведомление в свой Telegram",
        "description": "Это действие ставит сообщение в очередь и пытается отправить его. Максимум 3/час на пользователя. Тест не является уведомлением об оплате и не меняет баланс. HTTP 202 не подтверждает доставку; проверяйте список уведомлений.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Результат постановки в очередь.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "queued"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/telegram/webhook": {
      "post": {
        "tags": [
          "Telegram"
        ],
        "operationId": "receiveTelegramUpdate",
        "summary": "Принять событие Telegram Bot API",
        "description": "Только секретный заголовок Telegram, без session/CSRF/Origin. Дополнительные поля Update разрешены. Обрабатываются message и callback_query, персональные действия только в private-чате подтверждённого отправителя. Прочие события пропускаются. update_id дедуплицируется; выполняющийся update даёт 503 для повтора. Это не webhook платёжного провайдера.",
        "security": [
          {
            "telegramWebhookSecret": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Telegram Update, максимум 65 536 байт.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TelegramUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Обработано, пропущено либо уже обработано ранее.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ошибка обращения к Telegram.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TELEGRAM_UNAVAILABLE",
              "TELEGRAM_INVALID_RESPONSE",
              "TELEGRAM_RATE_LIMITED",
              "TELEGRAM_DELIVERY_FAILED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/payments": {
      "post": {
        "tags": [
          "Disabled payments"
        ],
        "operationId": "paymentsUnavailable",
        "summary": "Денежная операция отключена",
        "description": "Возвращает 503 GATEWAY_NOT_CONNECTED. Денежные операции недоступны. Тело не обрабатывается, запрос к шлюзу не выполняется.",
        "security": [],
        "responses": {
          "503": {
            "description": "Денежные операции недоступны.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "const": "GATEWAY_NOT_CONNECTED"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/api/payouts": {
      "post": {
        "tags": [
          "Disabled payments"
        ],
        "operationId": "payoutsUnavailable",
        "summary": "Денежная операция отключена",
        "description": "Возвращает 503 GATEWAY_NOT_CONNECTED. Денежные операции недоступны. Тело не обрабатывается, запрос к шлюзу не выполняется.",
        "security": [],
        "responses": {
          "503": {
            "description": "Денежные операции недоступны.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "const": "GATEWAY_NOT_CONNECTED"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Service"
        ],
        "operationId": "getOpenApi",
        "summary": "Публичный машиночитаемый контракт",
        "description": "Только чтение. Не содержит секретов, сессий, данных пользователей или рабочего контракта платёжного провайдера.",
        "responses": {
          "200": {
            "description": "Этот документ OpenAPI 3.1.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "public, max-age=300"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "openapi",
                    "info",
                    "paths"
                  ],
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/payment-links": {
      "get": {
        "tags": [
          "Payment links"
        ],
        "operationId": "listOwnPaymentLinks",
        "summary": "Список собственных ссылок",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "description": "Сортировка createdAt DESC, id DESC. Публичные ссылки читаются между устройствами; доступ к списку требует аккаунт.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "nextCursor из предыдущего ответа. Сервис использует base64 JSON [createdAt,id]; клиенту следует передавать значение без изменений через URLSearchParams."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Страница собственных ссылок.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinksPage"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "post": {
        "tags": [
          "Payment links"
        ],
        "operationId": "createOwnPaymentLink",
        "summary": "Создать счёт с неизменными условиями",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,100}$"
            },
            "description": "Один ключ на логический запрос. Повтор с теми же каноническими полями возвращает исходную запись; другое тело с тем же ключом даёт 409."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "description": "Создать неизменяемый счёт и сразу получить checkoutUrl; это не списывает средства с покупателя. USD: карта/Alipay; RUB: SBP; USDT: криптовалюта. USD криптовалюта остаётся принятой для совместимости, но не может быть оплачена без счёта USDT. Доли комиссии и НДС, оплачиваемые покупателем, — независимые целые числа от 0 до 100; текущая живая карта/Alipay поддерживает НДС покупатель=100 и комиссия покупатель=0. Итоговая сумма для покупателя никогда не изменяется молча. Последнее приложение веб-сайта должно быть одобрено перед новым живым списанием. Создание счёта и его событие для продавца фиксируются атомарно.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentLink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Идемпотентный повтор; replayed=true.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "201": {
            "description": "Счёт создан; replayed=false.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/payment-links/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^lnk_[0-9a-f-]{36}$"
          },
          "description": "Идентификатор собственной ссылки; не публичный token."
        }
      ],
      "get": {
        "tags": [
          "Payment links"
        ],
        "operationId": "getOwnPaymentLink",
        "summary": "Собственная ссылка и сохранённый расчёт",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Чужой и отсутствующий ID одинаково возвращают 404.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ]
      },
      "patch": {
        "tags": [
          "Payment links"
        ],
        "operationId": "changePaymentLinkStatus",
        "summary": "Приостановить, возобновить или отменить ссылку",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "description": "Изменяет только статус. Обновление и неизменяемое событие invoice.updated фиксируются атомарно. Одновременные изменения используют проверку версии; обновите и повторите при LINK_CHANGED. cancelled является конечным, срок действия никогда не продлевается, а цена, способы оплаты, доли затрат и описание остаются замороженными. Повторение сохранённого статуса возвращает текущий счёт.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused",
                      "cancelled"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Актуальное состояние собственной ссылки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "get": {
        "tags": [
          "Checkout"
        ],
        "operationId": "getPublicCheckout",
        "summary": "Публичные детали счёта для покупателя",
        "description": "Читает неизменяемую публичную цитату счёта и его сохранённый платёжный снимок. method должен принадлежать счёту. Аккаунт не требуется. Не раскрывает личность владельца, приватные метаданные или поступления продавца. Токен даёт доступ только к этому оформлению заказа. availability отражает конфигурацию, распределение, технические ограничения и одобрение продавца; подтверждение оплаты отдельно.",
        "parameters": [
          {
            "name": "method",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "card",
                "alipay",
                "sbp",
                "crypto"
              ]
            },
            "description": "Должен входить в сохранённый methods счёта."
          }
        ],
        "responses": {
          "200": {
            "description": "Публичный счёт и существующий платёж, если он был отправлен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoice": {
                      "$ref": "#/components/schemas/CheckoutInvoice"
                    },
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "invoice",
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/pay": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "post": {
        "tags": [
          "Checkout"
        ],
        "operationId": "startCheckoutPayment",
        "summary": "Начать или восстановить оплату счёта",
        "description": "Операция покупателя с тем же источником; аккаунт или токен CSRF не требуются. Сервер резервирует одну операцию и стабильный ключ идемпотентности перед отправкой на шлюз. Повтор восстанавливает ту же операцию; потерянный ответ должен быть разрешён через статус. Способ оплаты фиксируется после отправки. Данные карты должны быть зашифрованы в браузере с помощью свежего платёжного намерения. SBP/криптовалюта отправляют сохранённую итоговую сумму покупателя; карта/Alipay используют поддерживаемую неизменяемую налоговую конфигурацию. Новые списания требуют одобренного приложения продавца. Существующие отправленные платежи могут быть восстановлены после истечения счёта, паузы или изменений одобрения. Маршрут /v2 или hosted-card не используется.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartCheckoutPayment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Существующая операция восстановлена; второй платёж не выполняется.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "202": {
            "description": "Операция отправлена; завершение асинхронно.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "410": {
            "description": "Намерение шлюза или банковский вызов истекло. Получите новое намерение для той же операции; не создавайте заменяющий платеж.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CARD_SESSION_INVALID"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/v1/payments": {
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "listOwnPaymentLinksViaPayments",
        "summary": "Список собственных ссылок",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "description": "Сортировка createdAt DESC, id DESC. Публичные ссылки читаются между устройствами; доступ к списку требует аккаунт.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "nextCursor из предыдущего ответа. Сервис использует base64 JSON [createdAt,id]; клиенту следует передавать значение без изменений через URLSearchParams."
          }
        ],
        "responses": {
          "200": {
            "description": "Страница собственных ссылок.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinksPage"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:read"
      },
      "post": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "createOwnPaymentLinkViaPayments",
        "summary": "Создать счёт с неизменными условиями",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,100}$"
            },
            "description": "Один ключ на логический запрос. Повтор с теми же каноническими полями возвращает исходную запись; другое тело с тем же ключом даёт 409."
          }
        ],
        "description": "Создать неизменяемый счёт и сразу получить checkoutUrl; это не списывает средства с покупателя. USD: карта/Alipay; RUB: SBP; USDT: криптовалюта. USD криптовалюта остаётся принятой для совместимости, но не может быть оплачена без счёта USDT. Доли комиссии и НДС, оплачиваемые покупателем, — независимые целые числа от 0 до 100; текущая живая карта/Alipay поддерживает НДС покупатель=100 и комиссия покупатель=0. Итоговая сумма для покупателя никогда не изменяется молча. Последнее приложение веб-сайта должно быть одобрено перед новым живым списанием. Создание счёта и его событие для продавца фиксируются атомарно.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentLink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Идемпотентный повтор; replayed=true.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "201": {
            "description": "Счёт создан; replayed=false.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:write"
      }
    },
    "/api/v1/payments/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^lnk_[0-9a-f-]{36}$"
          },
          "description": "Идентификатор собственной ссылки; не публичный token."
        }
      ],
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "getOwnPaymentLinkViaPayments",
        "summary": "Собственная ссылка и сохранённый расчёт",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Чужой и отсутствующий ID одинаково возвращают 404.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [],
        "x-required-scope": "invoices:read"
      },
      "patch": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "changePaymentLinkStatusViaPayments",
        "summary": "Приостановить, возобновить или отменить ссылку",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "parameters": [],
        "description": "Изменяет только статус. Обновление и неизменяемое событие invoice.updated фиксируются атомарно. Одновременные изменения используют проверку версии; обновите и повторите при LINK_CHANGED. cancelled является конечным, срок действия никогда не продлевается, а цена, способы оплаты, доли затрат и описание остаются замороженными. Повторение сохранённого статуса возвращает текущий счёт.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused",
                      "cancelled"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Актуальное состояние собственной ссылки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:write"
      }
    },
    "/api/v1/payment-links": {
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "listOwnPaymentLinksViaLinks",
        "summary": "Список собственных ссылок",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "description": "Сортировка createdAt DESC, id DESC. Публичные ссылки читаются между устройствами; доступ к списку требует аккаунт.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "nextCursor из предыдущего ответа. Сервис использует base64 JSON [createdAt,id]; клиенту следует передавать значение без изменений через URLSearchParams."
          }
        ],
        "responses": {
          "200": {
            "description": "Страница собственных ссылок.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinksPage"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:read"
      },
      "post": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "createOwnPaymentLinkViaLinks",
        "summary": "Создать счёт с неизменными условиями",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,100}$"
            },
            "description": "Один ключ на логический запрос. Повтор с теми же каноническими полями возвращает исходную запись; другое тело с тем же ключом даёт 409."
          }
        ],
        "description": "Создать неизменяемый счёт и сразу получить checkoutUrl; это не списывает средства с покупателя. USD: карта/Alipay; RUB: SBP; USDT: криптовалюта. USD криптовалюта остаётся принятой для совместимости, но не может быть оплачена без счёта USDT. Доли комиссии и НДС, оплачиваемые покупателем, — независимые целые числа от 0 до 100; текущая живая карта/Alipay поддерживает НДС покупатель=100 и комиссия покупатель=0. Итоговая сумма для покупателя никогда не изменяется молча. Последнее приложение веб-сайта должно быть одобрено перед новым живым списанием. Создание счёта и его событие для продавца фиксируются атомарно.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentLink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Идемпотентный повтор; replayed=true.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "201": {
            "description": "Счёт создан; replayed=false.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:write"
      }
    },
    "/api/v1/payment-links/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^lnk_[0-9a-f-]{36}$"
          },
          "description": "Идентификатор собственной ссылки; не публичный token."
        }
      ],
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "getOwnPaymentLinkViaLinks",
        "summary": "Собственная ссылка и сохранённый расчёт",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Чужой и отсутствующий ID одинаково возвращают 404.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [],
        "x-required-scope": "invoices:read"
      },
      "patch": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "changePaymentLinkStatusViaLinks",
        "summary": "Приостановить, возобновить или отменить ссылку",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "parameters": [],
        "description": "Изменяет только статус. Обновление и неизменяемое событие invoice.updated фиксируются атомарно. Одновременные изменения используют проверку версии; обновите и повторите при LINK_CHANGED. cancelled является конечным, срок действия никогда не продлевается, а цена, способы оплаты, доли затрат и описание остаются замороженными. Повторение сохранённого статуса возвращает текущий счёт.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused",
                      "cancelled"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Актуальное состояние собственной ссылки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "invoices:write"
      }
    },
    "/api/api-keys": {
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "listMerchantKeys",
        "summary": "Список метаданных собственных ключей",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Секреты и хеши секретов опущены.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MerchantKey"
                      }
                    }
                  },
                  "required": [
                    "keys"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ]
      },
      "post": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "createMerchantKey",
        "summary": "Создайте ограниченный ключ; покажите его секрет один раз",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "description": "Максимум 10 активных ключей. Не более 5 созданий/час/пользователь. Ключи истекают, могут быть отозваны и ограничены по частоте до 90 запросов API/мин/ключ.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "scopes": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 3,
                    "uniqueItems": true,
                    "items": {
                      "type": "string",
                      "enum": [
                        "invoices:read",
                        "invoices:write",
                        "events:read"
                      ]
                    }
                  },
                  "expiresInDays": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 365,
                    "default": 90
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Храните секрет безопасно на вашем сервере.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "$ref": "#/components/schemas/MerchantKey"
                    },
                    "secret": {
                      "type": "string",
                      "pattern": "^kv_live_[A-Za-z0-9_-]{43}$"
                    }
                  },
                  "required": [
                    "key",
                    "secret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/api-keys/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^key_[0-9a-f-]{36}$"
          }
        }
      ],
      "delete": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "revokeMerchantKey",
        "summary": "Отозвать собственный ключ",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Будущее использование ключа отклоняется.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "const": true
                    }
                  },
                  "required": [
                    "revoked"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/events": {
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "listOwnEvents",
        "summary": "Чтение собственной неизменяемой истории событий",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Unix timestamp в миллисекундах, UTC."
            },
            "description": "Устаревшая эксклюзивная граница метки времени. Не может сочетаться с курсором. Используйте nextCursor для постраничной выдачи без потерь."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Непрозрачный nextCursor, возвращенный предыдущей страницей. Кодирует [createdAt,id] и сохраняет события, разделяющие одну метку времени."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Сначала новейшие; до 50 событий. Следуйте за nextCursor до null.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "$ref": "#/components/schemas/MerchantEvent"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "events",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/v1/events": {
      "get": {
        "tags": [
          "Merchant API"
        ],
        "operationId": "listMerchantEventsWithKey",
        "summary": "Чтение собственной неизменяемой истории событий",
        "security": [
          {
            "merchantKey": []
          }
        ],
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Unix timestamp в миллисекундах, UTC."
            },
            "description": "Устаревшая эксклюзивная граница метки времени. Не может сочетаться с курсором. Используйте nextCursor для постраничной выдачи без потерь."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Непрозрачный nextCursor, возвращенный предыдущей страницей. Кодирует [createdAt,id] и сохраняет события, разделяющие одну метку времени."
          }
        ],
        "responses": {
          "200": {
            "description": "Сначала новейшие; до 50 событий. Следуйте за nextCursor до null.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "$ref": "#/components/schemas/MerchantEvent"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "events",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "x-required-scope": "events:read"
      }
    },
    "/api/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhookEndpoints",
        "summary": "Список конечных точек и последних 30 доставок",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Секреты подписи не возвращаются.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    },
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "eventTypes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "invoice.created",
                          "invoice.updated",
                          "payment.succeeded",
                          "payment.failed",
                          "payment.refunded",
                          "payment.partially_refunded",
                          "payment.disputed",
                          "payment.review_required"
                        ]
                      }
                    }
                  },
                  "required": [
                    "endpoints",
                    "deliveries",
                    "available",
                    "eventTypes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ]
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhookEndpoint",
        "summary": "Зарегистрируйте публичный HTTPS-адрес",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "description": "До 5 конечных точек и 6 созданий/час/пользователь. Только публичные HTTPS-домены; без учетных данных, IP-литералов или нестандартных портов. Недавно созданная конечная точка не получает актуальных доставок, пока ее вызов не будет успешен.",
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 8,
                    "uniqueItems": true,
                    "items": {
                      "type": "string",
                      "enum": [
                        "invoice.created",
                        "invoice.updated",
                        "payment.succeeded",
                        "payment.failed",
                        "payment.refunded",
                        "payment.partially_refunded",
                        "payment.disputed",
                        "payment.review_required"
                      ]
                    }
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Сохраните одноразовый секрет подписи.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    "secret": {
                      "type": "string",
                      "pattern": "^whsec_[A-Za-z0-9_-]{43}$",
                      "description": "Показывается только при создании/ротации. Хранится в зашифрованном виде на сервере."
                    }
                  },
                  "required": [
                    "endpoint",
                    "secret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/webhooks/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^wh_[0-9a-f-]{36}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "getWebhookEndpoint",
        "summary": "Список конечных точек и последних 30 доставок",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Секреты подписи не возвращаются.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    },
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "eventTypes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "invoice.created",
                          "invoice.updated",
                          "payment.succeeded",
                          "payment.failed",
                          "payment.refunded",
                          "payment.partially_refunded",
                          "payment.disputed",
                          "payment.review_required"
                        ]
                      }
                    }
                  },
                  "required": [
                    "endpoints",
                    "deliveries",
                    "available",
                    "eventTypes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        },
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "setWebhookStatus",
        "summary": "Приостановить или возобновить проверенную конечную точку",
        "description": "Приостановленные проверенные конечные точки сохраняют подходящие события в очереди; возобновление обрабатывает просроченные доставки.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Статус сохранен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "updated": {
                      "const": true
                    }
                  },
                  "required": [
                    "updated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhookEndpoint",
        "summary": "Удалить конечную точку и отменить недоставленные задания",
        "description": "Отменяет ожидающие, неудачные и арендованные задания. Запрос, уже отправленный по сети, невозможно отозвать.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Конечная точка удалена.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/webhooks/{id}/verify": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^wh_[0-9a-f-]{36}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "verifyWebhookEndpoint",
        "summary": "Отправить подписанный вызов проверки конечной точки",
        "description": "Максимум 5 попыток проверки/час/пользователь. Ваш сервер должен проверить Kevmi-Signature и вернуть JSON 2xx {\"challenge\":\"<data.challenge>\"}. Таймаут запроса: 8 секунд; лимит ответа: 8192 байта. Перенаправления не отслеживаются. Проверка активирует конечную точку.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Проверена и активна.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verified": {
                      "const": true
                    },
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    }
                  },
                  "required": [
                    "verified",
                    "endpoint"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "422": {
            "description": "Адрес назначения не удалось проверить.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "WEBHOOK_UNREACHABLE",
              "WEBHOOK_VERIFICATION_FAILED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/webhooks/{id}/rotate": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^wh_[0-9a-f-]{36}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "rotateWebhookSecret",
        "summary": "Заменить секрет подписи и потребовать повторную проверку",
        "description": "Максимум 3 ротации/час/пользователь. Обновите ваш сервер и проверьте конечную точку снова. Уже выполняемый запрос может по-прежнему содержать предыдущую подпись.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Новый секрет показан один раз.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "secret": {
                      "type": "string",
                      "pattern": "^whsec_[A-Za-z0-9_-]{43}$",
                      "description": "Показывается только при создании/ротации. Хранится в зашифрованном виде на сервере."
                    },
                    "requiresVerification": {
                      "const": true
                    }
                  },
                  "required": [
                    "secret",
                    "requiresVerification"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/webhooks/{id}/deliveries/{deliveryId}/retry": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^wh_[0-9a-f-]{36}$"
          }
        },
        {
          "name": "deliveryId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^del_[a-f0-9]{40}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "retryWebhookDelivery",
        "summary": "Повторить неудачную доставку на активную конечную точку",
        "description": "Сохраняет идентификатор события и полезную нагрузку; генерирует новую метку времени и подпись. Каждый автоматический цикл доставки делает не более 6 попыток, включая истекшие аренды, с задержками 1м, 5м, 30м, 2ч и 12ч. Доставка выполняется как минимум один раз; дедуплицируйте идентификаторы событий на вашем сервере.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Повтор запланирован.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "const": true
                    }
                  },
                  "required": [
                    "queued"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/applications": {
      "get": {
        "tags": [
          "Applications"
        ],
        "operationId": "listOwnApplications",
        "summary": "Список до 30 собственных приложений",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "name": "X-Kevmi-Locale",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en",
                "es",
                "de",
                "fr",
                "pt",
                "tr",
                "kk"
              ]
            },
            "description": "URL отслеживания и язык системных сообщений. Без поддерживаемого значения учитываются реферер с того же источника и язык браузера; запасной вариант — английский."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Сначала новейшие.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applications": {
                      "type": "array",
                      "maxItems": 30,
                      "items": {
                        "$ref": "#/components/schemas/Application"
                      }
                    }
                  },
                  "required": [
                    "applications"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "post": {
        "tags": [
          "Applications"
        ],
        "operationId": "submitWebsiteApplication",
        "summary": "Отправить информацию о веб-сайте и получить URL отслеживания",
        "description": "Требуется подтвержденный вход через Telegram. До 5 новых отправок/день/пользователь. Идемпотентный повтор возвращает 200. Сервер продвигает реальные сохраненные этапы; недоступные или рискованные автоматические результаты требуют проверки человеком. Одобрение не настраивает платежный шлюз. Владение и состояние не могут быть указаны заявителем.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,100}$"
            },
            "description": "Один ключ на логический запрос. Повтор с теми же каноническими полями возвращает исходную запись; другое тело с тем же ключом даёт 409."
          },
          {
            "name": "X-Kevmi-Locale",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en",
                "es",
                "de",
                "fr",
                "pt",
                "tr",
                "kk"
              ]
            },
            "description": "URL отслеживания и язык системных сообщений. Без поддерживаемого значения учитываются реферер с того же источника и язык браузера; запасной вариант — английский."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "websiteUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Публичный HTTPS-домен без учетных данных, параметров запроса, IP-литералов или нестандартных портов. Фрагмент удаляется при нормализации."
                  },
                  "businessName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "businessType": {
                    "type": "string",
                    "enum": [
                      "digital_goods",
                      "software",
                      "services",
                      "physical_goods",
                      "education",
                      "other"
                    ]
                  },
                  "description": {
                    "type": "string",
                    "minLength": 40,
                    "maxLength": 3000
                  },
                  "contactTelegram": {
                    "type": "string",
                    "description": "Имя пользователя Telegram длиной 5–32 символа, начинающееся с буквы, затем буквы/цифры/знаки подчеркивания. Необязательный префикс @ или https://t.me/; окружающие пробелы обрезаются. Хранится как @username."
                  },
                  "consent": {
                    "type": "boolean",
                    "const": true
                  }
                },
                "required": [
                  "websiteUrl",
                  "businessName",
                  "businessType",
                  "description",
                  "contactTelegram",
                  "consent"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Существующая отправка.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "application",
                    "url",
                    "replayed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "202": {
            "description": "Принято; обработка продолжается на сервере.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "application",
                    "url",
                    "replayed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/applications/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^app_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Applications"
        ],
        "operationId": "getOwnApplication",
        "summary": "Чтение собственных этапов проверки и истории событий",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "name": "X-Kevmi-Locale",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en",
                "es",
                "de",
                "fr",
                "pt",
                "tr",
                "kk"
              ]
            },
            "description": "URL отслеживания и язык системных сообщений. Без поддерживаемого значения учитываются реферер с того же источника и язык браузера; запасной вариант — английский."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "responses": {
          "200": {
            "description": "Частная проекция заявителя. Доказательства и выходные данные модели не раскрываются.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    },
                    "events": {
                      "type": "array",
                      "maxItems": 40,
                      "items": {
                        "$ref": "#/components/schemas/ApplicationEvent"
                      }
                    }
                  },
                  "required": [
                    "application",
                    "events"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/applications/{id}/resume": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^app_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Applications"
        ],
        "operationId": "resumeApplicationJob",
        "summary": "Возобновить подходящий фоновый этап",
        "description": "Нельзя пропустить проверку или одобрить этап. Серверная аренда предотвращает дублирующую работу. Приложения, требующие проверки, и финальные приложения остаются без изменений. Не более 30 запросов возобновления обработки/мин/пользователь.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "name": "X-Kevmi-Locale",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en",
                "es",
                "de",
                "fr",
                "pt",
                "tr",
                "kk"
              ]
            },
            "description": "URL отслеживания и язык системных сообщений. Без поддерживаемого значения учитываются реферер с того же источника и язык браузера; запасной вариант — английский."
          },
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sto_[A-Za-z0-9_-]+$"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Обработка не требуется.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    }
                  },
                  "required": [
                    "application"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "202": {
            "description": "Обработка запланирована.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    },
                    "scheduled": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "application",
                    "scheduled"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/moderation/applications": {
      "get": {
        "tags": [
          "Moderation"
        ],
        "operationId": "listModerationApplications",
        "summary": "Список до 100 приложений для модерации",
        "description": "Требуется, чтобы аутентифицированная личность Telegram находилась в MODERATOR_TELEGRAM_IDS. Включает все состояния, отсортированные сначала needs_review, затем processing, затем финальные состояния; самые новые обновления первыми внутри группы.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Очередь модератора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applications": {
                      "type": "array",
                      "maxItems": 100,
                      "items": {
                        "$ref": "#/components/schemas/Application"
                      }
                    }
                  },
                  "required": [
                    "applications"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/moderation/applications/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^app_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Moderation"
        ],
        "operationId": "getModerationApplication",
        "summary": "Чтение доказательств проверки и истории этапов",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Частные доказательства модератора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    },
                    "events": {
                      "type": "array",
                      "maxItems": 40,
                      "items": {
                        "$ref": "#/components/schemas/ApplicationEvent"
                      }
                    },
                    "evidence": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "application",
                    "events",
                    "evidence"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/moderation/applications/{id}/decision": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^app_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Moderation"
        ],
        "operationId": "decideApplicationStage",
        "summary": "Одобрить текущий этап проверки или отклонить с публичной причиной",
        "description": "Требуется настроенный модератор; не более 30 решений/мин/пользователь. expectedVersion сравнивается атомарно. Можно одобрить только текущий этап needs_review; финальные приложения нельзя молча переоткрыть. Отклонение требует редактируемой публичной причины. Решение, история этапов и включенное уведомление заявителя сохраняются вместе.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "expectedVersion": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "action": {
                        "type": "string",
                        "const": "approve_step"
                      },
                      "reason": {
                        "type": "string",
                        "maxLength": 0
                      }
                    },
                    "required": [
                      "expectedVersion",
                      "action"
                    ],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "expectedVersion": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "action": {
                        "type": "string",
                        "const": "reject"
                      },
                      "reason": {
                        "type": "string",
                        "minLength": 10,
                        "maxLength": 1500
                      }
                    },
                    "required": [
                      "expectedVersion",
                      "action",
                      "reason"
                    ],
                    "additionalProperties": false
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Решение сохранено.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application": {
                      "$ref": "#/components/schemas/Application"
                    }
                  },
                  "required": [
                    "application"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/gateway/webhook": {
      "post": {
        "tags": [
          "Gateway events"
        ],
        "operationId": "receiveGatewayEvent",
        "summary": "Получать подписанные события шлюза из исходного источника",
        "description": "Native v3: укажите X-Gateway-Timestamp (секунды Unix), X-Gateway-Signature и соответствующий X-Gateway-Event-Id. Максимальное расхождение времени — 300 секунд. После проверки подписи Kevmi получает платёж через аутентифицированный API шлюза, проверяет сохранённый заказ, точную валюту/сумму, метод и подтверждённое провайдером состояние, затем атомарно сохраняет чек и событие исходящей очереди мерчанта. Текст вебхука и наблюдения браузера сами по себе никогда не подтверждают платёж. Повторные идентификаторы дедуплицируются; изменённое тело для существующего идентификатора отклоняется. Отложенные события используют свежее авторитетное состояние. Частичные возвраты, полные возвраты, споры и состояния проверки поддерживаются. Непривязанные заказы подтверждаются и игнорируются. Устаревшие нормализованные события с Kevmi-Signature остаются поддерживаемыми отдельно; применяются только их переходы succeeded/failed/full-refunded.",
        "security": [
          {
            "nativeGatewaySignature": []
          },
          {
            "gatewaySignature": []
          }
        ],
        "parameters": [
          {
            "name": "X-Gateway-Timestamp",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{10}$"
            },
            "description": "Требуется для событий native v3."
          },
          {
            "name": "X-Gateway-Event-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Требуется для native v3; должен совпадать с body.id."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Точное подписанное тело JSON; лимит native v3: 524288 байт. Не разбирайте и не пересериализуйте перед проверкой подписи.",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/NativeGatewayEvent"
                  },
                  {
                    "$ref": "#/components/schemas/LegacyGatewayEvent"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Получено, дедуплицировано или безопасно проигнорировано.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean",
                      "const": true
                    },
                    "replayed": {
                      "type": "boolean"
                    },
                    "ignored": {
                      "type": "boolean"
                    },
                    "applied": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "received"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Подпись шлюза отсутствует, недействительна или выходит за пределы допустимого временного окна.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_GATEWAY_SIGNATURE",
              "INVALID_SIGNATURE",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Идентификатор события был повторно использован с изменённым содержимым, или идентификатор платежа конфликтует с привязкой сохранённого счёта.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_EVENT_CONFLICT",
              "PAYMENT_ID_CONFLICT"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Шлюз занят; повторите доставку вебхука с тем же идентификатором события.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_BUSY"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Конфигурация шлюза или секрет подписи отсутствуют.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_NOT_CONNECTED",
              "DATABASE_NOT_CONFIGURED"
            ]
          }
        }
      }
    },
    "/api/jobs/dispatch": {
      "post": {
        "tags": [
          "Service"
        ],
        "operationId": "dispatchBackgroundJobs",
        "summary": "Запустить отложенную доставку и прикладные задачи",
        "description": "Точка входа планировщика сервера. Требует JOBS_SECRET, а не сессию браузера или ключ мерчанта. Не принимает идентификаторы задач или произвольные исходящие URL.",
        "security": [
          {
            "jobSecret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Завершено без фонового контекста.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "202": {
            "description": "Принято в фоновом контексте выполнения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": {
                      "const": true
                    }
                  },
                  "required": [
                    "accepted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/status": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "get": {
        "tags": [
          "Checkout"
        ],
        "operationId": "getCheckoutPaymentStatus",
        "summary": "Прочитать и обновить тот же платёж",
        "description": "Учётная запись не требуется. Обновляет существующую операцию через аутентифицированный транспорт шлюза с серверным ограничением частоты. Новый платёж не создаётся. Возвращает null, если ничего не было отправлено. Подтверждайте заказ только когда fulfillmentReady равно true.",
        "responses": {
          "200": {
            "description": "Текущее очищенное состояние платежа.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/reconcile": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "post": {
        "tags": [
          "Checkout"
        ],
        "operationId": "reconcileCheckoutPayment",
        "summary": "Запросить авторитетную сверку статуса",
        "description": "Читает существующую операцию и просит шлюз сверить статус провайдера. Не создаёт платёж. Не более 3 запросов на счёт в минуту. Доступно для уже отправленных платежей, даже если счёт больше не активен.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Сверенный платёж или null.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "410": {
            "description": "Намерение шлюза или банковский вызов истекло. Получите новое намерение для той же операции; не создавайте заменяющий платеж.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CARD_SESSION_INVALID"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/card-intent": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "post": {
        "tags": [
          "Checkout"
        ],
        "operationId": "createCardEncryptionIntent",
        "summary": "Получить публичный ключ шлюза и привязанное намерение шифрования",
        "description": "Только шлюз владеет закрытым ключом. Намерение истекает в течение пяти минут и привязывает заказ мерчанта, валюту, базовую/итоговую суммы, ключ идемпотентности операции и назначение. Платёжные намерения требуют активный счёт и одобренного мерчанта; кодовые намерения требуют существующий текущий банковский вызов. Никакие поля PAN, CVV, банковского кода или закрытого JWK не принимаются этой конечной точкой. Не более 8 намерений на счёт и 12 на клиента в минуту. Зашифрованный открытый текст: {intent,name,country,email?,card:{number,expiration,cvv,holder}} для платежа или {intent,code} для кода. Открытый текст собирается только внутри браузера перед шифрованием JWE.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Объект JSON, не более 2048 байт.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "payment",
                      "code"
                    ],
                    "default": "payment"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Недолговечное намерение и публичный ключ RSA — только они.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CardIntent"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "410": {
            "description": "Намерение шлюза или банковский вызов истекло. Получите новое намерение для той же операции; не создавайте заменяющий платеж.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CARD_SESSION_INVALID"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/code": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "post": {
        "tags": [
          "Checkout"
        ],
        "operationId": "submitEncryptedBankCode",
        "summary": "Передать зашифрованный код для текущего банковского вызова",
        "description": "Получить намерение с назначением=code и зашифровать {intent,code} в браузере. Шлюз проверяет текущий вызов и однократно потребляет запечатанное намерение. Kevmi никогда не получает открытый текст кода. Не более 5 отправок на счёт в минуту; обновите статус после неопределённого ответа.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sealed": {
                    "$ref": "#/components/schemas/SealedCardData"
                  }
                },
                "required": [
                  "sealed"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Код отправлен; текущее состояние платежа.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/CheckoutPayment"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "payment"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "410": {
            "description": "Намерение шлюза или банковский вызов истекло. Получите новое намерение для той же операции; не создавайте заменяющий платеж.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CARD_SESSION_INVALID"
            ]
          },
          "413": {
            "description": "Превышен размер тела: 16 384 байта; для /api/support/ask и Telegram webhook 65 536 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "REQUEST_TOO_LARGE"
            ]
          },
          "415": {
            "description": "Ожидается Content-Type: application/json.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "JSON_REQUIRED"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/checkout/{token}/crypto-services": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "description": "Случайный публичный идентификатор из URL страницы оплаты. Даёт чтение только этого счёта."
        }
      ],
      "get": {
        "tags": [
          "Checkout"
        ],
        "operationId": "getCheckoutCryptoServices",
        "summary": "Прочитать текущий каталог монет и сетей",
        "description": "Только для счёта USDT, допускающего криптовалюту. Счёт остаётся номинированным в USDT; шлюз котирует выбранную монету плательщика. Никогда не предполагайте, что USD равна USDT, и не преобразуйте сумму перевода в число с плавающей точкой. Не более 10 чтений каталога на счёт в минуту.",
        "responses": {
          "200": {
            "description": "Каталог, предоставленный шлюзом, с текущей доступностью и лимитами перевода.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "services": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string"
                          },
                          "network": {
                            "type": "string"
                          },
                          "networkLabel": {
                            "type": "string"
                          },
                          "available": {
                            "type": "boolean"
                          },
                          "minAmount": {
                            "type": "string",
                            "pattern": "^[0-9]+(?:\\.[0-9]+)?$",
                            "description": "Точное десятичное значение в выбранной монете перевода."
                          },
                          "maxAmount": {
                            "type": "string",
                            "pattern": "^[0-9]+(?:\\.[0-9]+)?$",
                            "description": "Точное десятичное значение в выбранной монете перевода."
                          },
                          "confirmations": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          }
                        },
                        "required": [
                          "currency",
                          "network",
                          "networkLabel",
                          "available",
                          "minAmount",
                          "maxAmount",
                          "confirmations"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "fetchedAt": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Unix timestamp в миллисекундах, UTC."
                    }
                  },
                  "required": [
                    "services",
                    "fetchedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "502": {
            "description": "Ответ шлюза недоступен, поврежден или не поддается проверке. Прочитайте текущий статус платежа перед любой попыткой повтора.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "GATEWAY_REQUEST_UNCERTAIN",
              "GATEWAY_INVALID_RESPONSE"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/stores": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "listStores",
        "summary": "Перечислить все магазины, принадлежащие текущей учётной записи",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Идентификаторы магазинов отличаются от идентификаторов учётных записей. Никакие секреты не раскрываются.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "stores": {
                      "type": "array",
                      "maxItems": 100,
                      "items": {
                        "$ref": "#/components/schemas/Store"
                      }
                    },
                    "defaultStoreId": {
                      "type": "string",
                      "pattern": "^sto_[A-Za-z0-9_-]+$"
                    }
                  },
                  "required": [
                    "stores",
                    "defaultStoreId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      },
      "post": {
        "tags": [
          "Account"
        ],
        "operationId": "createStore",
        "summary": "Создать отдельный магазин",
        "description": "До 100 магазинов/учётная запись и 10 созданий/час/учётная запись. Новый магазин требует собственное одобрение веб-сайта перед началом платежа.",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Создано.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "store": {
                      "$ref": "#/components/schemas/Store"
                    }
                  },
                  "required": [
                    "store"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "409": {
            "description": "Запрос входа уже использован/отменён, личность ещё не подтверждена или конфликт обращения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "CHALLENGE_UNAVAILABLE",
              "IDENTITY_INCOMPLETE",
              "TICKET_CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "LINK_CANCELLED",
              "LINK_EXPIRED",
              "LINK_UNAVAILABLE"
            ]
          },
          "429": {
            "description": "Лимит частоты превышен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "const": "60"
                },
                "description": "Сервер всегда возвращает 60; это не гарантирует истечение часовой квоты."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "RATE_LIMITED"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/stores/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          }
        }
      ],
      "patch": {
        "tags": [
          "Account"
        ],
        "operationId": "updateStore",
        "summary": "Переименовать принадлежащий магазин или изменить его значение VAT по умолчанию",
        "security": [
          {
            "cookieSession": [],
            "csrfToken": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "description": "Должен точно совпасть с настроенным APP_ORIGIN. Sec-Fetch-Site: cross-site отклоняется. Сервер не предоставляет CORS-доступ.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "description": "Токен текущей сессии из GET /api/auth/me или успешного завершения входа.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "vatPayer": {
                    "type": "string",
                    "enum": [
                      "customer",
                      "merchant"
                    ]
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Существующие котировки счетов не меняются.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "store": {
                      "$ref": "#/components/schemas/Store"
                    }
                  },
                  "required": [
                    "store"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "403": {
            "description": "Не пройдена проверка Origin, CSRF или привязки входа к браузеру.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_ORIGIN",
              "CSRF_REQUIRED",
              "BROWSER_PROOF_REQUIRED",
              "INVALID_CHALLENGE"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/exchange-rates": {
      "get": {
        "tags": [
          "Payments"
        ],
        "operationId": "getReferenceExchangeRate",
        "summary": "Получить текущий справочный курс USD/RUB",
        "description": "Кэшируется на сервере в течение одного часа. Числовой курс использует миллионные доли RUB за USD. Никакая резервная котировка не выдумывается. Используется при создании счёта; существующий счёт сохраняет свой собственный курс.",
        "security": [],
        "responses": {
          "200": {
            "description": "Официальный источник, дата публикации и время получения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rate": {
                      "$ref": "#/components/schemas/ExchangeRate"
                    }
                  },
                  "required": [
                    "rate"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    },
    "/api/account/dashboard": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getAccountDashboard",
        "summary": "Прочитать подтверждённые чеки для одного магазина или всех принадлежащих магазинов",
        "description": "Чистые поступления не являются снимаемым балансом. Устаревшие валюты остаются отдельными. Итоги — за всё время; разбивки по дням/методам используют запрошенный период UTC.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "name": "X-Kevmi-Store",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Выберите принадлежащий магазин для браузерной сессии. Опустите, чтобы использовать первый магазин. API-ключи игнорируют этот заголовок и всегда используют свою неизменяемую привязку к магазину. Значение all доступно только для чтения и поддерживается только конечными точками панели управления и списка счетов."
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                7,
                30
              ],
              "default": 7
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Сводка бухгалтерии только для чтения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "storeId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "stores": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "pattern": "^sto_[A-Za-z0-9_-]+$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "currency": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoices": {
                            "type": "integer"
                          },
                          "netMinor": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Целое количество минимальных денежных единиц."
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "currency",
                          "invoices",
                          "netMinor"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "totals": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string"
                          },
                          "invoices": {
                            "type": "integer"
                          },
                          "succeeded": {
                            "type": "integer"
                          },
                          "grossMinor": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Целое количество минимальных денежных единиц."
                          },
                          "netMinor": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Целое количество минимальных денежных единиц."
                          }
                        },
                        "required": [
                          "currency",
                          "invoices",
                          "succeeded",
                          "grossMinor",
                          "netMinor"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "daily": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string"
                          },
                          "day": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer"
                          },
                          "grossMinor": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Целое количество минимальных денежных единиц."
                          }
                        },
                        "required": [
                          "currency",
                          "day",
                          "count",
                          "grossMinor"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "methods": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string"
                          },
                          "method": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer"
                          },
                          "grossMinor": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Целое количество минимальных денежных единиц."
                          }
                        },
                        "required": [
                          "currency",
                          "method",
                          "count",
                          "grossMinor"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "days": {
                      "type": "integer",
                      "enum": [
                        7,
                        30
                      ]
                    },
                    "from": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Unix timestamp в миллисекундах, UTC."
                    },
                    "generatedAt": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Unix timestamp в миллисекундах, UTC."
                    },
                    "accountingBasis": {
                      "type": "string",
                      "const": "verified_receipts"
                    },
                    "withdrawableBalance": {
                      "type": "null"
                    },
                    "payoutCreationAvailable": {
                      "type": "boolean",
                      "const": false
                    }
                  },
                  "required": [
                    "storeId",
                    "stores",
                    "totals",
                    "daily",
                    "methods",
                    "days",
                    "from",
                    "generatedAt",
                    "accountingBasis",
                    "withdrawableBalance",
                    "payoutCreationAvailable"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON, неизвестное поле или недопустимое значение.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "INVALID_JSON",
              "UNKNOWN_FIELD",
              "INVALID_INPUT",
              "INVALID_VAT_PAYER",
              "INVALID_NOTIFICATIONS",
              "INVALID_TICKET_STATUS",
              "INVALID_UPDATE",
              "INVALID_HISTORY",
              "INVALID_PAGE_CONTEXT",
              "INVALID_LOCALE",
              "INVALID_FILTER",
              "INVALID_NOTIFICATION_SELECTION",
              "INVALID_AMOUNT",
              "INVALID_CURRENCY",
              "INVALID_METHODS",
              "INVALID_EXPIRY",
              "INVALID_QUOTE",
              "INVALID_LIMIT",
              "INVALID_CURSOR",
              "INVALID_STATUS",
              "IDEMPOTENCY_KEY_REQUIRED",
              "METHOD_UNAVAILABLE"
            ]
          },
          "401": {
            "description": "Нет действующей сессии; для webhook — неверный секрет.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "AUTH_REQUIRED",
              "SESSION_EXPIRED",
              "WEBHOOK_UNAUTHORIZED"
            ]
          },
          "404": {
            "description": "Запись отсутствует, публичный token неверен или собственная запись принадлежит другому пользователю.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "TICKET_NOT_FOUND",
              "LINK_NOT_FOUND"
            ]
          },
          "503": {
            "description": "Интеграция или хранилище не настроены, событие обрабатывается либо сервис недоступен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DATABASE_NOT_CONFIGURED",
              "ORIGIN_NOT_CONFIGURED",
              "TELEGRAM_NOT_CONFIGURED",
              "UPDATE_IN_PROGRESS",
              "SERVICE_UNAVAILABLE",
              "GATEWAY_NOT_CONNECTED"
            ]
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "cookieSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Host-kevmi-session",
        "description": "Случайный токен сессии, Secure/HttpOnly/SameSite=Lax, срок 24 часа. В базе хранится хеш. Получается только завершением подтверждённого Telegram-входа."
      },
      "browserProof": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Host-kevmi-login",
        "description": "HttpOnly cookie из start, challengeId.proof, срок 300 секунд. Не включается в Telegram deep link."
      },
      "csrfToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-CSRF-Token",
        "description": "Токен сессии, выдаётся /api/auth/me или /api/auth/telegram/complete. Для изменений дополнительно обязателен точный Origin."
      },
      "telegramWebhookSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Telegram-Bot-Api-Secret-Token",
        "description": "Отдельный секрет из серверной конфигурации webhook. Его значение не публикуется. Это не токен бота."
      },
      "merchantKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "kv_live_…",
        "description": "Ограниченный ключ API мерчанта. Хранится только его хеш. Только для взаимодействия сервер-сервер; никогда не помещайте его в виджет или сборку браузера."
      },
      "gatewaySignature": {
        "type": "apiKey",
        "in": "header",
        "name": "Kevmi-Signature",
        "description": "t=<секунды Unix>,v1=<шестнадцатеричный HMAC-SHA256(секрет, метка времени + точка + точное тело запроса UTF-8)>. Максимальное расхождение времени: 300 секунд."
      },
      "jobSecret": {
        "type": "http",
        "scheme": "bearer",
        "description": "Отдельный серверный JOBS_SECRET. Не ключ API мерчанта."
      },
      "nativeGatewaySignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Gateway-Signature",
        "description": "v1=<шестнадцатеричный HMAC-SHA256(GATEWAY_WEBHOOK_SECRET, метка времени + \".\" + точное сырое тело UTF-8)>; отдельно от мерчантовского Kevmi-Signature."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": false
      },
      "EmptyObject": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "Config": {
        "type": "object",
        "properties": {
          "telegram": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "botUsername": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "enabled",
              "botUsername"
            ],
            "additionalProperties": false
          },
          "support": {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "search",
                  "ai"
                ]
              },
              "available": {
                "type": "boolean",
                "const": true
              }
            },
            "required": [
              "mode",
              "available"
            ],
            "additionalProperties": false
          },
          "gateway": {
            "type": "object",
            "properties": {
              "configured": {
                "type": "boolean"
              },
              "connected": {
                "type": "boolean",
                "const": false,
                "description": "Публичная конечная точка конфигурации не проверяет здоровье шлюза. Конфигурация не является успешной проверкой живого соединения."
              },
              "status": {
                "type": "string",
                "enum": [
                  "configured",
                  "not_configured"
                ]
              }
            },
            "required": [
              "configured",
              "connected",
              "status"
            ],
            "additionalProperties": false
          },
          "capabilities": {
            "type": "object",
            "properties": {
              "server": {
                "type": "boolean",
                "const": true
              },
              "account": {
                "type": "boolean"
              },
              "notifications": {
                "type": "boolean"
              },
              "tickets": {
                "type": "boolean"
              },
              "directPaymentsOnly": {
                "type": "boolean",
                "const": true
              },
              "paymentLinks": {
                "type": "boolean",
                "description": "D1 настроена для серверных ссылок. Это не готовность приёма денег."
              },
              "apiKeys": {
                "type": "boolean"
              },
              "webhooks": {
                "type": "boolean"
              },
              "widgets": {
                "type": "boolean"
              },
              "applications": {
                "type": "boolean"
              },
              "applicationNotifications": {
                "type": "boolean"
              }
            },
            "required": [
              "server",
              "account",
              "notifications",
              "tickets",
              "directPaymentsOnly",
              "paymentLinks",
              "apiKeys",
              "webhooks",
              "widgets",
              "applications",
              "applicationNotifications"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "telegram",
          "support",
          "gateway",
          "capabilities"
        ],
        "additionalProperties": false
      },
      "Health": {
        "type": "object",
        "properties": {
          "telegram": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "botUsername": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "enabled",
              "botUsername"
            ],
            "additionalProperties": false
          },
          "support": {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "search",
                  "ai"
                ]
              },
              "available": {
                "type": "boolean",
                "const": true
              }
            },
            "required": [
              "mode",
              "available"
            ],
            "additionalProperties": false
          },
          "gateway": {
            "type": "object",
            "properties": {
              "configured": {
                "type": "boolean"
              },
              "connected": {
                "type": "boolean",
                "const": false,
                "description": "Публичная конечная точка конфигурации не проверяет здоровье шлюза. Конфигурация не является успешной проверкой живого соединения."
              },
              "status": {
                "type": "string",
                "enum": [
                  "configured",
                  "not_configured"
                ]
              }
            },
            "required": [
              "configured",
              "connected",
              "status"
            ],
            "additionalProperties": false
          },
          "capabilities": {
            "type": "object",
            "properties": {
              "server": {
                "type": "boolean",
                "const": true
              },
              "account": {
                "type": "boolean"
              },
              "notifications": {
                "type": "boolean"
              },
              "tickets": {
                "type": "boolean"
              },
              "directPaymentsOnly": {
                "type": "boolean",
                "const": true
              },
              "paymentLinks": {
                "type": "boolean",
                "description": "D1 настроена для серверных ссылок. Это не готовность приёма денег."
              },
              "apiKeys": {
                "type": "boolean"
              },
              "webhooks": {
                "type": "boolean"
              },
              "widgets": {
                "type": "boolean"
              },
              "applications": {
                "type": "boolean"
              },
              "applicationNotifications": {
                "type": "boolean"
              }
            },
            "required": [
              "server",
              "account",
              "notifications",
              "tickets",
              "directPaymentsOnly",
              "paymentLinks",
              "apiKeys",
              "webhooks",
              "widgets",
              "applications",
              "applicationNotifications"
            ],
            "additionalProperties": false
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "storage": {
            "type": "string",
            "enum": [
              "ready",
              "not_configured",
              "unavailable"
            ]
          }
        },
        "required": [
          "telegram",
          "support",
          "gateway",
          "capabilities",
          "status",
          "storage"
        ],
        "additionalProperties": false
      },
      "NotificationPreferences": {
        "type": "object",
        "properties": {
          "payments": {
            "type": "boolean"
          },
          "payouts": {
            "type": "boolean"
          },
          "support": {
            "type": "boolean"
          },
          "security": {
            "type": "boolean"
          }
        },
        "required": [
          "payments",
          "payouts",
          "support",
          "security"
        ],
        "additionalProperties": false
      },
      "SettingsPatch": {
        "type": "object",
        "properties": {
          "storeName": {
            "type": "string",
            "minLength": 1,
            "x-trimmedMaxLength": 80,
            "x-trimmedMinLength": 1,
            "description": "Пробелы по краям удаляются. Длина после удаления: 1–80 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant"
            ]
          },
          "notifications": {
            "type": "object",
            "properties": {
              "payments": {
                "type": "boolean"
              },
              "payouts": {
                "type": "boolean"
              },
              "support": {
                "type": "boolean"
              },
              "security": {
                "type": "boolean"
              }
            },
            "required": [],
            "additionalProperties": false
          }
        },
        "required": [],
        "additionalProperties": false
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          },
          "storeName": {
            "type": "string"
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant"
            ]
          },
          "notifications": {
            "$ref": "#/components/schemas/NotificationPreferences"
          },
          "isModerator": {
            "type": "boolean",
            "description": "Принадлежит ли эта Telegram-идентичность настроенному списку разрешённых модераторов."
          }
        },
        "required": [
          "id",
          "displayName",
          "username",
          "storeName",
          "vatPayer",
          "notifications",
          "isModerator"
        ],
        "additionalProperties": false
      },
      "UserResponse": {
        "type": "object",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/User"
          }
        },
        "required": [
          "user"
        ],
        "additionalProperties": false
      },
      "Anonymous": {
        "type": "object",
        "properties": {
          "authenticated": {
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "authenticated"
        ],
        "additionalProperties": false
      },
      "CurrentSession": {
        "type": "object",
        "properties": {
          "authenticated": {
            "type": "boolean",
            "const": true
          },
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "csrfToken": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "authenticated",
          "user",
          "csrfToken",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "LoginChallenge": {
        "type": "object",
        "properties": {
          "challengeId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "code": {
            "type": "string",
            "pattern": "^[0-9]{6}$"
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "telegramUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://t\\.me/"
          }
        },
        "required": [
          "challengeId",
          "code",
          "expiresAt",
          "telegramUrl"
        ],
        "additionalProperties": false
      },
      "CompletedLogin": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "const": "authenticated"
          },
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "csrfToken": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "status",
          "user",
          "csrfToken",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "SupportQuestion": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "minLength": 2,
            "x-trimmedMaxLength": 2000,
            "x-trimmedMinLength": 2,
            "description": "Пробелы по краям удаляются. Длина после удаления: 2–2000 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
          },
          "locale": {
            "type": "string",
            "enum": [
              "ru",
              "en",
              "es",
              "de",
              "fr",
              "pt",
              "tr",
              "kk"
            ],
            "default": "en",
            "description": "Язык ответа. Если опущен, используются поддерживаемые предпочтения Accept-Language; иначе английский. Документация доступна на каждом поддерживаемом языке интерфейса."
          },
          "history": {
            "type": "array",
            "maxItems": 6,
            "description": "До трёх последних пар вопрос/ответ. Необязательно. Это недоверенные данные, не сообщения системной роли провайдера.",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "role": {
                      "type": "string",
                      "const": "user"
                    },
                    "content": {
                      "type": "string",
                      "minLength": 1,
                      "x-trimmedMaxLength": 1800,
                      "x-trimmedMinLength": 1,
                      "description": "Пробелы по краям удаляются. Длина после удаления: 1–1800 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
                    }
                  },
                  "required": [
                    "role",
                    "content"
                  ],
                  "additionalProperties": false
                },
                {
                  "type": "object",
                  "properties": {
                    "role": {
                      "type": "string",
                      "const": "assistant"
                    },
                    "content": {
                      "type": "string",
                      "minLength": 1,
                      "x-trimmedMaxLength": 3000,
                      "x-trimmedMinLength": 1,
                      "description": "Пробелы по краям удаляются. Длина после удаления: 1–3000 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
                    }
                  },
                  "required": [
                    "role",
                    "content"
                  ],
                  "additionalProperties": false
                }
              ]
            }
          },
          "pageContext": {
            "type": "string",
            "minLength": 1,
            "x-trimmedMaxLength": 80,
            "x-trimmedMinLength": 1,
            "description": "Короткое название раздела после trim, 1–80 символов. Разрешены буквы, цифры, пробелы и ·.,—–-:(). Переносы строк, URL, query-параметры и HTML запрещены. Не передавайте токены или секреты.",
            "pattern": "^[\\p{L}\\p{N}\\s·.,—–\\-:()]+$",
            "not": {
              "pattern": "[\\r\\n]"
            }
          }
        },
        "required": [
          "question"
        ],
        "additionalProperties": false
      },
      "SupportSource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "pattern": "^/(?:ru/|en/)?docs/[^/]+$",
            "description": "Относительная ссылка на статью опубликованной базы знаний."
          }
        },
        "required": [
          "id",
          "title",
          "url"
        ],
        "additionalProperties": false
      },
      "SearchSupportAnswer": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "const": "search"
          },
          "answer": {
            "type": "string"
          },
          "sources": {
            "type": "array",
            "maxItems": 3,
            "items": {
              "$ref": "#/components/schemas/SupportSource"
            }
          },
          "knowledgeVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "needsHuman": {
            "type": "boolean"
          },
          "aiUnavailable": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "mode",
          "answer",
          "sources",
          "knowledgeVersion",
          "needsHuman"
        ],
        "additionalProperties": false
      },
      "AISupportAnswer": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "const": "ai"
          },
          "answer": {
            "type": "string",
            "minLength": 1,
            "maxLength": 6000,
            "description": "Обычный текст; URL и HTML не принимаются. Ссылки возвращаются только в sources."
          },
          "sources": {
            "type": "array",
            "maxItems": 25,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/SupportSource"
            }
          },
          "knowledgeVersion": {
            "type": "string"
          },
          "needsHuman": {
            "type": "boolean"
          }
        },
        "required": [
          "mode",
          "answer",
          "sources",
          "knowledgeVersion",
          "needsHuman"
        ],
        "additionalProperties": false,
        "allOf": [
          {
            "if": {
              "properties": {
                "needsHuman": {
                  "const": false
                }
              }
            },
            "then": {
              "properties": {
                "sources": {
                  "minItems": 1
                }
              }
            }
          }
        ]
      },
      "SupportAnswer": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/SearchSupportAnswer"
          },
          {
            "$ref": "#/components/schemas/AISupportAnswer"
          }
        ]
      },
      "Ticket": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^tkt_[a-f0-9-]{36}$"
          },
          "subject": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "answered",
              "closed"
            ],
            "description": "answered обозначает отвеченное обращение. Через публичный API пользователь может только закрыть собственное обращение."
          },
          "source": {
            "type": "string",
            "enum": [
              "web",
              "telegram"
            ]
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "id",
          "subject",
          "message",
          "status",
          "source",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "TicketResponse": {
        "type": "object",
        "properties": {
          "ticket": {
            "$ref": "#/components/schemas/Ticket"
          }
        },
        "required": [
          "ticket"
        ],
        "additionalProperties": false
      },
      "Notification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ntf_[A-Za-z0-9-]{1,80}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "payments",
              "payouts",
              "support",
              "security",
              "test"
            ]
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "sent",
              "failed"
            ],
            "description": "Состояние доставки Telegram; независимо от прочтения на сайте."
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "sentAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "readAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Время первого прочтения на сайте; null — непрочитано. Не является подтверждением прочтения в Telegram."
          }
        },
        "required": [
          "id",
          "kind",
          "message",
          "status",
          "createdAt",
          "sentAt",
          "readAt"
        ],
        "additionalProperties": false
      },
      "NotificationsPage": {
        "type": "object",
        "properties": {
          "notifications": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/Notification"
            }
          },
          "unreadCount": {
            "type": "integer",
            "minimum": 0
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Курсор следующей страницы; null, если больше записей нет."
          }
        },
        "required": [
          "notifications",
          "unreadCount",
          "nextCursor"
        ],
        "additionalProperties": false
      },
      "ReadNotifications": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "ids": {
                "type": "array",
                "minItems": 1,
                "maxItems": 100,
                "description": "Дубликаты допустимы и учитываются один раз.",
                "items": {
                  "type": "string",
                  "pattern": "^ntf_[A-Za-z0-9-]{1,80}$"
                }
              }
            },
            "required": [
              "ids"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "all": {
                "type": "boolean",
                "const": true
              },
              "before": {
                "type": "integer",
                "minimum": 0,
                "description": "createdAt последнего уже показанного события. Сервер дополнительно требует before <= Date.now().",
                "maximum": 9007199254740991
              }
            },
            "required": [
              "all",
              "before"
            ],
            "additionalProperties": false
          }
        ]
      },
      "ReadNotificationsResult": {
        "type": "object",
        "properties": {
          "updated": {
            "type": "integer",
            "minimum": 0
          },
          "readAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "unreadCount": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "updated",
          "readAt",
          "unreadCount"
        ],
        "additionalProperties": false
      },
      "TelegramUpdate": {
        "type": "object",
        "properties": {
          "update_id": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "message": {
            "type": "object",
            "additionalProperties": true,
            "description": "Telegram Message: обработчик использует message_id, text, from и chat."
          },
          "callback_query": {
            "type": "object",
            "additionalProperties": true,
            "description": "Telegram CallbackQuery: обработчик использует id, from, data и message.chat."
          }
        },
        "required": [
          "update_id"
        ],
        "additionalProperties": true
      },
      "IncomingQuote": {
        "type": "object",
        "properties": {
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "baseMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "grossMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "percentageFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "fixedFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "nominalFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "feeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "vatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerVatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantVatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerTotalMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantDeductionMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "totalFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "netMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant",
              "shared"
            ]
          },
          "vatApplies": {
            "type": "boolean"
          },
          "pricingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Версия расчёта, сохранённая вместе со счётом."
          },
          "vatCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
          },
          "feeCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
            "default": 0
          },
          "customerFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "settlement": {
            "$ref": "#/components/schemas/SettlementQuote"
          }
        },
        "required": [
          "amountMinor",
          "baseMinor",
          "grossMinor",
          "percentageFeeMinor",
          "fixedFeeMinor",
          "nominalFeeMinor",
          "feeMinor",
          "vatMinor",
          "customerVatMinor",
          "merchantVatMinor",
          "customerTotalMinor",
          "merchantDeductionMinor",
          "totalFeeMinor",
          "netMinor",
          "currency",
          "method",
          "vatPayer",
          "vatApplies",
          "pricingVersion"
        ],
        "additionalProperties": false
      },
      "PaymentLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^lnk_[0-9a-f-]{36}$"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "merchantName": {
            "type": "string"
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant",
              "shared"
            ]
          },
          "methods": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "card",
                "alipay",
                "sbp",
                "crypto"
              ]
            }
          },
          "quotes": {
            "type": "object",
            "properties": {
              "card": {
                "$ref": "#/components/schemas/IncomingQuote"
              },
              "alipay": {
                "$ref": "#/components/schemas/IncomingQuote"
              },
              "sbp": {
                "$ref": "#/components/schemas/IncomingQuote"
              },
              "crypto": {
                "$ref": "#/components/schemas/IncomingQuote"
              }
            },
            "required": [],
            "additionalProperties": false
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "expired",
              "cancelled"
            ],
            "description": "expired определяется expiresAt при чтении. cancelled окончательный."
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Публичная страница /pay/{token} на APP_ORIGIN."
          },
          "vatCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
          },
          "feeCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
            "default": 0
          },
          "orderId": {
            "type": "string",
            "maxLength": 100,
            "description": "Ссылка на заказ, видимая покупателю."
          },
          "metadata": {
            "type": "object",
            "maxProperties": 10,
            "propertyNames": {
              "pattern": "^[A-Za-z0-9_-]{1,40}$"
            },
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "description": "Приватные метаданные продавца. Не более 3000 байт UTF-8 после JSON-сериализации. Никогда не раскрываются в публичной оплате."
          },
          "checkoutUrl": {
            "type": "string",
            "format": "uri"
          },
          "payment": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PaymentSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "Включается в GET-запросы списка/деталей владельца. Жизненный цикл счёта независим от подтверждённого статуса платежа. Не содержит данных карты, банковского кода, QR или покупателя."
          },
          "storeId": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "native",
              "universal"
            ]
          },
          "fx": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ExchangeRate"
              },
              {
                "type": "null"
              }
            ]
          },
          "usdtPerUsd": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "merchantName",
          "amountMinor",
          "currency",
          "vatPayer",
          "methods",
          "quotes",
          "status",
          "createdAt",
          "updatedAt",
          "expiresAt",
          "url",
          "vatCustomerPercent",
          "feeCustomerPercent",
          "orderId",
          "metadata",
          "checkoutUrl"
        ],
        "additionalProperties": false
      },
      "CreatePaymentLink": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "x-trimmedMaxLength": 120,
                "x-trimmedMinLength": 1,
                "description": "Пробелы по краям удаляются. Длина после удаления: 1–120 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
              },
              "description": {
                "type": "string",
                "x-trimmedMaxLength": 500,
                "description": "Необязательно; пустая строка разрешена. До 500 символов после trim."
              },
              "amountMinor": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000000,
                "description": "Техническая граница целого значения, не коммерческий лимит провайдера. Отрицательное зачисление отклоняется."
              },
              "vatPayer": {
                "type": "string",
                "enum": [
                  "customer",
                  "merchant"
                ],
                "description": "При отсутствии сохраняется правило текущего магазина."
              },
              "expiresAt": {
                "type": "integer",
                "minimum": 0,
                "description": "В будущем, максимум 90 дней от момента создания. По умолчанию 7 дней. Срок сохраняется в снимке счёта."
              },
              "currency": {
                "type": "string",
                "const": "USD"
              },
              "methods": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "card",
                    "alipay",
                    "crypto"
                  ]
                },
                "description": "Новая оплата в USD поддерживает карты и Alipay. Криптовалютные счета в USD принимаются только для совместимости и возвращают crypto_requires_usdt при живой оплате; используйте USDT для криптовалюты."
              },
              "vatCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
              },
              "feeCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
                "default": 0
              },
              "orderId": {
                "type": "string",
                "maxLength": 100,
                "description": "Ссылка на заказ, видимая покупателю."
              },
              "metadata": {
                "type": "object",
                "maxProperties": 10,
                "propertyNames": {
                  "pattern": "^[A-Za-z0-9_-]{1,40}$"
                },
                "additionalProperties": {
                  "type": "string",
                  "maxLength": 500
                },
                "description": "Приватные метаданные продавца. Не более 3000 байт UTF-8 после JSON-сериализации. Никогда не раскрываются в публичной оплате."
              },
              "pricingMode": {
                "type": "string",
                "const": "native",
                "description": "Устаревшее ценообразование для конкретной валюты. Опустите для совместимости с существующими интеграциями."
              }
            },
            "required": [
              "title",
              "amountMinor",
              "currency",
              "methods"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "x-trimmedMaxLength": 120,
                "x-trimmedMinLength": 1,
                "description": "Пробелы по краям удаляются. Длина после удаления: 1–120 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
              },
              "description": {
                "type": "string",
                "x-trimmedMaxLength": 500,
                "description": "Необязательно; пустая строка разрешена. До 500 символов после trim."
              },
              "amountMinor": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000000,
                "description": "Техническая граница целого значения, не коммерческий лимит провайдера. Отрицательное зачисление отклоняется."
              },
              "vatPayer": {
                "type": "string",
                "enum": [
                  "customer",
                  "merchant"
                ],
                "description": "При отсутствии сохраняется правило текущего магазина."
              },
              "expiresAt": {
                "type": "integer",
                "minimum": 0,
                "description": "В будущем, максимум 90 дней от момента создания. По умолчанию 7 дней. Срок сохраняется в снимке счёта."
              },
              "currency": {
                "type": "string",
                "const": "RUB"
              },
              "methods": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "const": "sbp"
                }
              },
              "vatCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
              },
              "feeCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
                "default": 0
              },
              "orderId": {
                "type": "string",
                "maxLength": 100,
                "description": "Ссылка на заказ, видимая покупателю."
              },
              "metadata": {
                "type": "object",
                "maxProperties": 10,
                "propertyNames": {
                  "pattern": "^[A-Za-z0-9_-]{1,40}$"
                },
                "additionalProperties": {
                  "type": "string",
                  "maxLength": 500
                },
                "description": "Приватные метаданные продавца. Не более 3000 байт UTF-8 после JSON-сериализации. Никогда не раскрываются в публичной оплате."
              },
              "pricingMode": {
                "type": "string",
                "const": "native",
                "description": "Устаревшее ценообразование для конкретной валюты. Опустите для совместимости с существующими интеграциями."
              }
            },
            "required": [
              "title",
              "amountMinor",
              "currency",
              "methods"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "x-trimmedMaxLength": 120,
                "x-trimmedMinLength": 1,
                "description": "Пробелы по краям удаляются. Длина после удаления: 1–120 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
              },
              "description": {
                "type": "string",
                "x-trimmedMaxLength": 500,
                "description": "Необязательно; пустая строка разрешена. До 500 символов после trim."
              },
              "amountMinor": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000000,
                "description": "Техническая граница целого значения, не коммерческий лимит провайдера. Отрицательное зачисление отклоняется."
              },
              "vatPayer": {
                "type": "string",
                "enum": [
                  "customer",
                  "merchant"
                ],
                "description": "При отсутствии сохраняется правило текущего магазина."
              },
              "expiresAt": {
                "type": "integer",
                "minimum": 0,
                "description": "В будущем, максимум 90 дней от момента создания. По умолчанию 7 дней. Срок сохраняется в снимке счёта."
              },
              "currency": {
                "type": "string",
                "const": "USDT"
              },
              "methods": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "const": "crypto"
                }
              },
              "vatCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
              },
              "feeCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
                "default": 0
              },
              "orderId": {
                "type": "string",
                "maxLength": 100,
                "description": "Ссылка на заказ, видимая покупателю."
              },
              "metadata": {
                "type": "object",
                "maxProperties": 10,
                "propertyNames": {
                  "pattern": "^[A-Za-z0-9_-]{1,40}$"
                },
                "additionalProperties": {
                  "type": "string",
                  "maxLength": 500
                },
                "description": "Приватные метаданные продавца. Не более 3000 байт UTF-8 после JSON-сериализации. Никогда не раскрываются в публичной оплате."
              },
              "pricingMode": {
                "type": "string",
                "const": "native",
                "description": "Устаревшее ценообразование для конкретной валюты. Опустите для совместимости с существующими интеграциями."
              }
            },
            "required": [
              "title",
              "amountMinor",
              "currency",
              "methods"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "x-trimmedMaxLength": 120,
                "x-trimmedMinLength": 1,
                "description": "Пробелы по краям удаляются. Длина после удаления: 1–120 символов. Управляющие символы, кроме табуляции и перевода строки, запрещены."
              },
              "description": {
                "type": "string",
                "x-trimmedMaxLength": 500,
                "description": "Необязательно; пустая строка разрешена. До 500 символов после trim."
              },
              "amountMinor": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000000,
                "description": "Техническая граница целого значения, не коммерческий лимит провайдера. Отрицательное зачисление отклоняется."
              },
              "vatPayer": {
                "type": "string",
                "enum": [
                  "customer",
                  "merchant"
                ],
                "description": "При отсутствии сохраняется правило текущего магазина."
              },
              "expiresAt": {
                "type": "integer",
                "minimum": 0,
                "description": "В будущем, максимум 90 дней от момента создания. По умолчанию 7 дней. Срок сохраняется в снимке счёта."
              },
              "currency": {
                "type": "string",
                "enum": [
                  "USD",
                  "RUB",
                  "USDT"
                ],
                "description": "Единица ввода. RUB конвертируется в USD по сохранённому справочному курсу; USDT использует явное правило счёта 1:1. Базовая валюта сохранённого счёта — USD."
              },
              "methods": {
                "type": "array",
                "minItems": 1,
                "maxItems": 4,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "card",
                    "alipay",
                    "sbp",
                    "crypto"
                  ]
                }
              },
              "vatCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
              },
              "feeCustomerPercent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
                "default": 0
              },
              "orderId": {
                "type": "string",
                "maxLength": 100,
                "description": "Ссылка на заказ, видимая покупателю."
              },
              "metadata": {
                "type": "object",
                "maxProperties": 10,
                "propertyNames": {
                  "pattern": "^[A-Za-z0-9_-]{1,40}$"
                },
                "additionalProperties": {
                  "type": "string",
                  "maxLength": 500
                },
                "description": "Приватные метаданные продавца. Не более 3000 байт UTF-8 после JSON-сериализации. Никогда не раскрываются в публичной оплате."
              },
              "pricingMode": {
                "type": "string",
                "const": "universal"
              }
            },
            "required": [
              "title",
              "amountMinor",
              "currency",
              "methods",
              "pricingMode"
            ],
            "additionalProperties": false
          }
        ],
        "description": "Суммы указываются в минимальных единицах. Комиссия и НДС рассчитываются на базовую сумму заказа. Доля покупателя округляется в большую сторону; продавец покрывает точный остаток. Конфликтующее устаревшее vatPayer и vatCustomerPercent отклоняется. Распределение неизменно после создания; выпустите новый счёт для его изменения. Живая оплата картой/Alipay требует vatCustomerPercent=100 и feeCustomerPercent=0, поскольку настроенный шлюз не может переопределить свою исключительную налоговую ставку. Другие сохранённые распределения возвращают unsupported_allocation; они никогда не изменяются молча. SBP и криптовалюта USDT поддерживают распределение комиссии. Используйте публичный объект доступности счёта перед сбором платёжных данных. Универсальный режим хранит базовую цену в USD и отдельные нативные котировки: USD для карт/Alipay, RUB для SBP, USDT для криптовалюты. Конвертация RUB использует сохранённый справочный курс Банка России. Криптовалюта использует явное правило счёта 1 USD = 1 USDT, а не рыночную котировку. Счета, включающие конвертацию RUB, ограничены 24 часами, даже если expiresAt запрашивает более позднюю дату. Сбой источника валютного курса возвращает 503 FX_UNAVAILABLE. Опустите pricingMode для устаревшего нативного поведения.",
        "examples": [
          {
            "pricingMode": "universal",
            "title": "Заказ 1042",
            "amountMinor": 1000,
            "currency": "USD",
            "methods": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ],
            "vatCustomerPercent": 100,
            "feeCustomerPercent": 0
          },
          {
            "title": "Заказ 1042",
            "amountMinor": 500,
            "currency": "USD",
            "methods": [
              "card",
              "alipay"
            ],
            "vatCustomerPercent": 100,
            "feeCustomerPercent": 0,
            "orderId": "1042"
          },
          {
            "title": "Заказ 1043",
            "amountMinor": 1000,
            "currency": "USDT",
            "methods": [
              "crypto"
            ],
            "feeCustomerPercent": 23,
            "orderId": "1043"
          }
        ]
      },
      "PaymentLinkResponse": {
        "type": "object",
        "properties": {
          "link": {
            "$ref": "#/components/schemas/PaymentLink"
          },
          "checkoutUrl": {
            "type": "string",
            "format": "uri",
            "description": "Включается в ответы на обновления статуса; вложенная ссылка всегда содержит свой checkoutUrl."
          }
        },
        "required": [
          "link"
        ],
        "additionalProperties": false
      },
      "CreatePaymentLinkResponse": {
        "type": "object",
        "properties": {
          "link": {
            "$ref": "#/components/schemas/PaymentLink"
          },
          "replayed": {
            "type": "boolean"
          },
          "checkoutUrl": {
            "type": "string",
            "format": "uri",
            "description": "Платёжная ссылка доступна немедленно; опрос не требуется."
          }
        },
        "required": [
          "link",
          "replayed",
          "checkoutUrl"
        ],
        "additionalProperties": false
      },
      "PaymentLinksPage": {
        "type": "object",
        "properties": {
          "links": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/PaymentLink"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Непрозрачный курсор следующей страницы. Передавайте как query с URL-кодированием; null означает конец."
          }
        },
        "required": [
          "links",
          "nextCursor"
        ],
        "additionalProperties": false
      },
      "CheckoutQuote": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "vatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerVatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerTotalMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "vatApplies": {
            "type": "boolean"
          },
          "pricingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Версия расчёта, сохранённая вместе со счётом."
          },
          "customerFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantCoveredMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          }
        },
        "required": [
          "method",
          "amountMinor",
          "vatMinor",
          "customerVatMinor",
          "customerTotalMinor",
          "vatApplies",
          "pricingVersion",
          "customerFeeMinor",
          "merchantCoveredMinor"
        ],
        "additionalProperties": false
      },
      "CheckoutInvoice": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "merchantName": {
            "type": "string"
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant",
              "shared"
            ]
          },
          "methods": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "items": {
              "type": "string",
              "enum": [
                "card",
                "alipay",
                "sbp",
                "crypto"
              ]
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "expired",
              "cancelled"
            ],
            "description": "expired определяется expiresAt при чтении. cancelled окончательный."
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "quote": {
            "$ref": "#/components/schemas/CheckoutQuote"
          },
          "gatewayConnected": {
            "type": "boolean",
            "description": "Псевдоним совместимости для availability.available, а не проверка работоспособности шлюза."
          },
          "vatCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
          },
          "feeCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
            "default": 0
          },
          "orderId": {
            "type": "string",
            "maxLength": 100,
            "description": "Ссылка на заказ, видимая покупателю."
          },
          "availability": {
            "$ref": "#/components/schemas/CheckoutAvailability"
          },
          "baseAmountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "baseCurrency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ]
          },
          "fx": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ExchangeRate"
              },
              {
                "type": "null"
              }
            ]
          },
          "usdtPerUsd": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "token",
          "title",
          "description",
          "merchantName",
          "amountMinor",
          "currency",
          "vatPayer",
          "methods",
          "status",
          "expiresAt",
          "createdAt",
          "quote",
          "gatewayConnected",
          "vatCustomerPercent",
          "feeCustomerPercent",
          "orderId",
          "availability"
        ],
        "additionalProperties": false
      },
      "MerchantKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^key_[0-9a-f-]{36}$"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "invoices:read",
                "invoices:write",
                "events:read"
              ]
            }
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "revokedAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "lastUsedAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "storeId": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "createdAt",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "MerchantEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[a-f0-9]{40}$"
          },
          "type": {
            "type": "string",
            "enum": [
              "invoice.created",
              "invoice.updated",
              "payment.succeeded",
              "payment.failed",
              "payment.refunded",
              "payment.partially_refunded",
              "payment.disputed",
              "payment.review_required"
            ]
          },
          "apiVersion": {
            "type": "string",
            "const": "2026-10-21"
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "livemode": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "invoice.created/updated: сохранённый счёт продавца, включая приватные метаданные. payment events: подтверждённые факты платежа. Примеры см. в руководстве по вебхукам."
          }
        },
        "required": [
          "id",
          "type",
          "apiVersion",
          "createdAt",
          "livemode",
          "data"
        ],
        "additionalProperties": false
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^wh_[0-9a-f-]{36}$"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "invoice.created",
                "invoice.updated",
                "payment.succeeded",
                "payment.failed",
                "payment.refunded",
                "payment.partially_refunded",
                "payment.disputed",
                "payment.review_required"
              ]
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "unverified",
              "active",
              "paused"
            ]
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "verifiedAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "storeId": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          }
        },
        "required": [
          "id",
          "url",
          "description",
          "events",
          "status",
          "createdAt",
          "verifiedAt"
        ],
        "additionalProperties": false
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "event_id": {
            "type": "string"
          },
          "endpoint_id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "invoice.created",
              "invoice.updated",
              "payment.succeeded",
              "payment.failed",
              "payment.refunded",
              "payment.partially_refunded",
              "payment.disputed",
              "payment.review_required"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "delivered",
              "failed",
              "cancelled"
            ]
          },
          "attempts": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6
          },
          "next_attempt_at": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "last_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "delivered_at": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "id",
          "event_id",
          "endpoint_id",
          "type",
          "status",
          "attempts"
        ],
        "additionalProperties": false
      },
      "Application": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^app_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          },
          "websiteUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "businessName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "businessType": {
            "type": "string",
            "enum": [
              "digital_goods",
              "software",
              "services",
              "physical_goods",
              "education",
              "other"
            ]
          },
          "description": {
            "type": "string",
            "minLength": 40,
            "maxLength": 3000
          },
          "contactTelegram": {
            "type": "string",
            "pattern": "^@[A-Za-z][A-Za-z0-9_]{4,31}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "needs_review",
              "approved",
              "rejected"
            ]
          },
          "currentStage": {
            "type": "string",
            "enum": [
              "received",
              "ai_review",
              "technical_review",
              "manual_review"
            ]
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "reason": {
            "type": "string",
            "description": "Сцена для пользователя или причина отклонения, отредактированная модератором. Внутренние доказательства исключаются."
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "stages": {
            "type": "array",
            "minItems": 4,
            "maxItems": 4,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "enum": [
                    "received",
                    "ai_review",
                    "technical_review",
                    "manual_review"
                  ]
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "running",
                    "complete",
                    "review",
                    "rejected"
                  ]
                },
                "message": {
                  "type": "string"
                },
                "updatedAt": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Unix timestamp в миллисекундах, UTC."
                }
              },
              "required": [
                "id",
                "state",
                "message",
                "updatedAt"
              ],
              "additionalProperties": false
            }
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Приватный URL отслеживания с явной локалью. Знание URL не предоставляет доступ."
          },
          "notificationCategory": {
            "type": "string",
            "const": "support"
          },
          "canResume": {
            "type": "boolean"
          },
          "storeId": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          }
        },
        "required": [
          "id",
          "websiteUrl",
          "businessName",
          "businessType",
          "description",
          "contactTelegram",
          "status",
          "currentStage",
          "version",
          "reason",
          "createdAt",
          "updatedAt",
          "stages",
          "url",
          "notificationCategory",
          "canResume"
        ],
        "additionalProperties": false
      },
      "ApplicationEvent": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "stage": {
            "type": "string",
            "enum": [
              "received",
              "ai_review",
              "technical_review",
              "manual_review"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "complete",
              "review",
              "rejected"
            ]
          },
          "message": {
            "type": "string"
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "version",
          "stage",
          "state",
          "message",
          "createdAt"
        ],
        "additionalProperties": false
      },
      "PaymentSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Канонический идентификатор платежа шлюза, если известен; в противном случае локальный идентификатор операции gwp_."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "requires_action",
              "processing",
              "succeeded",
              "failed",
              "expired",
              "review_required",
              "partially_paid",
              "partially_refunded",
              "refunded",
              "disputed"
            ]
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "fulfillmentReady": {
            "type": "boolean"
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "refundedAmountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          }
        },
        "required": [
          "id",
          "method",
          "status",
          "amountMinor",
          "currency",
          "fulfillmentReady",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "CheckoutAvailability": {
        "type": "object",
        "properties": {
          "available": {
            "type": "boolean"
          },
          "code": {
            "type": "string",
            "enum": [
              "ready",
              "not_configured",
              "unsupported_allocation",
              "crypto_requires_usdt",
              "amount_out_of_range",
              "merchant_not_approved"
            ]
          },
          "flow": {
            "type": "string",
            "enum": [
              "encrypted_card",
              "qr",
              "crypto"
            ]
          },
          "minAmountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "maxAmountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "limitsSource": {
            "type": "string",
            "const": "adapter",
            "description": "Консервативные лимиты, накладываемые этой интеграцией, а не утверждение о коммерческих лимитах вышестоящего провайдера."
          }
        },
        "required": [
          "available",
          "code",
          "flow",
          "minAmountMinor",
          "maxAmountMinor",
          "limitsSource"
        ],
        "additionalProperties": false
      },
      "CheckoutAction": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "redirect",
              "qr",
              "crypto"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "qrImage": {
            "type": [
              "string",
              "null"
            ]
          },
          "qrPayload": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": "string"
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]+(?:\\.[0-9]+)?$",
            "description": "Точная сумма перевода в выбранной монете; сохраните десятичную строку без округления или преобразования в число с плавающей запятой."
          },
          "currency": {
            "type": "string"
          },
          "network": {
            "type": "string"
          },
          "networkLabel": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "addressQrImage": {
            "type": [
              "string",
              "null"
            ]
          },
          "amountQrImage": {
            "type": [
              "string",
              "null"
            ]
          },
          "amountQrPayload": {
            "type": [
              "string",
              "null"
            ]
          },
          "networkFeePaidByCustomer": {
            "type": "boolean"
          }
        },
        "required": [
          "type",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "CheckoutPayment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^gwp_[0-9a-f-]{36}$"
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "requires_action",
              "processing",
              "succeeded",
              "failed",
              "expired",
              "review_required",
              "partially_paid",
              "partially_refunded",
              "refunded",
              "disputed"
            ]
          },
          "providerStatus": {
            "type": "string"
          },
          "fulfillmentReady": {
            "type": "boolean",
            "description": "Только true после точной привязки суммы/валюты/заказа и подтверждения успеха провайдером. Перенаправление браузера никогда не является подтверждением платежа."
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "nextAction": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/CheckoutAction"
              },
              {
                "type": "null"
              }
            ]
          },
          "expiresAt": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "authentication": {
            "type": "object",
            "properties": {
              "required": {
                "type": "boolean"
              },
              "expiresAt": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "description": "Unix timestamp в миллисекундах, UTC."
              },
              "attempt": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "required",
              "expiresAt",
              "attempt"
            ],
            "additionalProperties": false
          },
          "reason": {
            "type": "string",
            "enum": [
              "amount_mismatch",
              "confirmation_required",
              "refund_mismatch",
              "settlement_unverified"
            ]
          },
          "refundedAmountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          }
        },
        "required": [
          "id",
          "method",
          "status",
          "providerStatus",
          "fulfillmentReady",
          "amountMinor",
          "currency",
          "createdAt",
          "updatedAt",
          "nextAction",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "SealedCardData": {
        "type": "object",
        "properties": {
          "intent": {
            "type": "string",
            "minLength": 32,
            "maxLength": 8192,
            "description": "Подписанный кратковременный интент операции от /card-intent; передавайте без изменений."
          },
          "jwe": {
            "type": "string",
            "maxLength": 14000,
            "pattern": "^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+){4}$",
            "description": "Компактный JWE с использованием RSA-OAEP-256 и A256GCM. Защищённый заголовок: kid из публичного ключа, typ=kevmi-card+jwe. В Kevmi отправляется только шифротекст. Никогда не отправляйте поля с открытым текстом карты или банковского кода."
          }
        },
        "required": [
          "intent",
          "jwe"
        ],
        "additionalProperties": false
      },
      "CardIntent": {
        "type": "object",
        "properties": {
          "intent": {
            "type": "string",
            "minLength": 32,
            "maxLength": 8192
          },
          "intentId": {
            "type": "string",
            "maxLength": 100
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "key": {
            "type": "object",
            "properties": {
              "kid": {
                "type": "string"
              },
              "kty": {
                "type": "string",
                "const": "RSA"
              },
              "n": {
                "type": "string"
              },
              "e": {
                "type": "string"
              },
              "alg": {
                "type": "string",
                "const": "RSA-OAEP-256"
              },
              "use": {
                "type": "string",
                "const": "enc"
              }
            },
            "required": [
              "kid",
              "kty",
              "n",
              "e",
              "alg",
              "use"
            ],
            "additionalProperties": false
          },
          "algorithm": {
            "type": "string",
            "const": "RSA-OAEP-256"
          },
          "encryption": {
            "type": "string",
            "const": "A256GCM"
          },
          "protocol": {
            "type": "string",
            "const": "kevmi-card-v1"
          }
        },
        "required": [
          "intent",
          "intentId",
          "expiresAt",
          "key",
          "algorithm",
          "encryption",
          "protocol"
        ],
        "additionalProperties": false
      },
      "StartCheckoutPayment": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "const": "card"
              },
              "sealed": {
                "$ref": "#/components/schemas/SealedCardData"
              }
            },
            "required": [
              "method",
              "sealed"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "const": "alipay"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "country": {
                "type": "string",
                "const": "CN"
              },
              "email": {
                "type": "string",
                "format": "email",
                "maxLength": 254
              }
            },
            "required": [
              "method",
              "name",
              "country"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "const": "sbp"
              }
            },
            "required": [
              "method"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "const": "crypto"
              },
              "payerCurrency": {
                "type": "string",
                "pattern": "^[A-Z0-9]{2,16}$"
              },
              "network": {
                "type": "string",
                "pattern": "^[a-z0-9_-]{2,32}$"
              }
            },
            "required": [
              "method",
              "payerCurrency",
              "network"
            ],
            "additionalProperties": false
          }
        ]
      },
      "LegacyGatewayEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string",
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9_.:-]+$"
          },
          "paymentId": {
            "type": "string",
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9_.:-]+$"
          },
          "invoiceId": {
            "type": "string",
            "pattern": "^lnk_[0-9a-f-]{36}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "failed",
              "refunded"
            ]
          },
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "occurredAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "eventId",
          "paymentId",
          "invoiceId",
          "status",
          "amountMinor",
          "currency",
          "method",
          "occurredAt"
        ],
        "additionalProperties": false
      },
      "NativeGatewayEvent": {
        "type": "object",
        "required": [
          "id",
          "api_version",
          "mode",
          "type",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "api_version": {
            "type": "string",
            "const": "3"
          },
          "mode": {
            "type": "string",
            "const": "live"
          },
          "type": {
            "type": "string",
            "pattern": "^[a-z_.]{1,80}$"
          },
          "data": {
            "type": "object",
            "required": [
              "id",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "version": {
                "type": "integer",
                "minimum": 0
              },
              "merchant_order_id": {
                "type": "string"
              }
            }
          }
        }
      },
      "Store": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^sto_[A-Za-z0-9_-]+$"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant"
            ]
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          }
        },
        "required": [
          "id",
          "name",
          "vatPayer",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "ExchangeRate": {
        "type": "object",
        "properties": {
          "rubPerUsdMicros": {
            "type": "integer",
            "minimum": 1000000
          },
          "effectiveAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "fetchedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp в миллисекундах, UTC."
          },
          "source": {
            "type": "string",
            "const": "https://www.cbr.ru/scripts/XML_daily.asp"
          },
          "usdtPerUsd": {
            "type": "string",
            "const": "1.00"
          }
        },
        "required": [
          "rubPerUsdMicros",
          "effectiveAt",
          "fetchedAt",
          "source",
          "usdtPerUsd"
        ],
        "additionalProperties": false
      },
      "SettlementQuote": {
        "type": "object",
        "properties": {
          "amountMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "baseMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "grossMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "percentageFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "fixedFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "nominalFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "feeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "vatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerVatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantVatMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "customerTotalMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantDeductionMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "totalFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "netMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "RUB",
              "USDT"
            ],
            "description": "Единицы счёта: центы USD, копейки RUB или сотые доли USDT. Автоматической конвертации валют нет."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "sbp",
              "crypto"
            ]
          },
          "vatPayer": {
            "type": "string",
            "enum": [
              "customer",
              "merchant",
              "shared"
            ]
          },
          "vatApplies": {
            "type": "boolean"
          },
          "pricingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Версия расчёта, сохранённая вместе со счётом."
          },
          "vatCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё. По умолчанию: устаревшее предпочтение НДС магазина."
          },
          "feeCustomerPercent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Доля покупателя в процентах целым числом. 0 означает, что продавец покрывает всё; 100 — покупатель покрывает всё.",
            "default": 0
          },
          "customerFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          },
          "merchantFeeMinor": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Целое количество минимальных денежных единиц."
          }
        },
        "required": [
          "amountMinor",
          "baseMinor",
          "grossMinor",
          "percentageFeeMinor",
          "fixedFeeMinor",
          "nominalFeeMinor",
          "feeMinor",
          "vatMinor",
          "customerVatMinor",
          "merchantVatMinor",
          "customerTotalMinor",
          "merchantDeductionMinor",
          "totalFeeMinor",
          "netMinor",
          "currency",
          "method",
          "vatPayer",
          "vatApplies",
          "pricingVersion"
        ],
        "additionalProperties": false
      }
    }
  },
  "webhooks": {
    "merchantEvent": {
      "post": {
        "summary": "Проверенная доставка на сервер продавца",
        "description": "Доставляется только на активные, прошедшие проверку challenge конечные точки. Сырой JSON подписан; проверьте метку времени и подпись перед разбором или изменением состояния заказа. Верните 2xx после долговременного принятия события. Сохраняйте идентификаторы событий для обработки дубликатов. Сетевые ошибки, тайм-ауты и статусы, отличные от 2xx, вызывают повторные попытки.",
        "parameters": [
          {
            "name": "Kevmi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Kevmi-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Kevmi-Delivery-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "JSON-объект. Максимум 16 384 байта. Неизвестные поля отклоняются.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerchantEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Принято долговременно сервером продавца."
          }
        }
      }
    }
  }
}
