{
  "openapi": "3.0.3",
  "info": {
    "title": "SupplyMe Client API",
    "version": "1.5.0",
    "description": "Клиентский API SupplyMe: состояние API, каталог, собственный баланс, покупки и выдача. Создайте ключ в Профиль → API после входа через Telegram. Чтение shop_read включено, покупки shop_purchase разрешаются отдельно и списывают реальный баланс аккаунта. Полный ключ показывается при создании; управление ключами доступно только в авторизованном профиле. Новый ключ из профиля — новый API-клиент с независимой историей и областью Idempotency-Key. Сначала восстановите результат неопределённой покупки; повтор с новым API-клиентом может списать баланс ещё раз. Методы активации CDK, массовой проверки и обновления сторонних подписок отключены и возвращают 410 feature_retired. Суточные квоты учитывают принятые авторизованные запросы, включая ошибки и повторы; граница суток — UTC. Без административного доступа и доступа к чужим заказам."
  },
  "servers": [
    {
      "url": "https://supply-me.ru/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/status": {
      "get": {
        "operationId": "status",
        "summary": "Состояние API и доступ текущего ключа",
        "description": "Проверяет авторизацию без покупки и списания баланса; возвращает состояние API SupplyMe, права ключа, лимиты и признак привязки аккаунта. Разрешено с shop_read или check у старых административных ключей. Не проверяет сторонних провайдеров и не гарантирует наличие товара. Запрос расходует квоту.",
        "tags": [
          "Reseller"
        ],
        "parameters": [
          {
            "name": "X-Request-ID",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            },
            "description": "Необязательный идентификатор для поддержки. Не является ключом идемпотентности."
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Имеет приоритет над language, X-Language и Accept-Language."
          }
        ],
        "x-permission": "shop_read OR check",
        "responses": {
          "200": {
            "description": "API доступен; права и лимиты относятся к текущему ключу.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Отсутствующий, отключённый, истёкший или неверный API-ключ.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод или IP, либо аккаунт владельца отключён.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Минутный или суточный лимит запросов. Соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Секунды до следующей попытки."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "При технических работах — shop.maintenance с data.status=maintenance и data.api.status=maintenance. При временном сбое — shop.temporarily_unavailable; data может отсутствовать.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusError"
                }
              }
            }
          }
        }
      }
    },
    "/catalog": {
      "get": {
        "operationId": "shopCatalog",
        "summary": "Каталог автоматической выдачи",
        "description": "Текущая розничная цена в сотых USDT и свободные остатки. Текст и ссылки; ручные и Telegram-file_id товары исключены. Цена и остаток не резервируются чтением.",
        "tags": [
          "Reseller"
        ],
        "x-permission": "shop_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-ID",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            }
          },
          {
            "in": "header",
            "name": "Accept-Language",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          },
          {
            "in": "query",
            "name": "after_id",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "default": 0,
              "maximum": 9223372036854775807
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Язык ответа. Приоритет: lang, language, X-Language, Accept-Language; по умолчанию ru."
          }
        ],
        "responses": {
          "200": {
            "description": "Результат получен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopCatalogResponse"
                }
              }
            }
          },
          "400": {
            "description": "Неверный ID или параметры пагинации.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод, IP или аккаунт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Лимит запросов, соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность API. Повторите чтение с паузой.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "get": {
        "operationId": "shopBalance",
        "summary": "Баланс аккаунта партнёра",
        "description": "Только баланс привязанного аккаунта. 1234 = 12.34 USDT.",
        "tags": [
          "Reseller"
        ],
        "x-permission": "shop_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-ID",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            }
          },
          {
            "in": "header",
            "name": "Accept-Language",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Язык ответа. Приоритет: lang, language, X-Language, Accept-Language; по умолчанию ru."
          }
        ],
        "responses": {
          "200": {
            "description": "Результат получен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopBalanceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Неверный ID или параметры пагинации.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод, IP или аккаунт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Лимит запросов, соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность API. Повторите чтение с паузой.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          }
        }
      }
    },
    "/orders": {
      "get": {
        "operationId": "shopOrders",
        "summary": "Заказы этого API-клиента",
        "description": "С возрастанием ID. Нет заказов сайта/бота или других API-клиентов, даже привязанных к тому же аккаунту. Неудачные попытки без заказа не включаются.",
        "tags": [
          "Reseller"
        ],
        "x-permission": "shop_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-ID",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            }
          },
          {
            "in": "header",
            "name": "Accept-Language",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          },
          {
            "in": "query",
            "name": "after_id",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "default": 0,
              "maximum": 9223372036854775807
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Язык ответа. Приоритет: lang, language, X-Language, Accept-Language; по умолчанию ru."
          }
        ],
        "responses": {
          "200": {
            "description": "Результат получен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopOrdersResponse"
                }
              }
            }
          },
          "400": {
            "description": "Неверный ID или параметры пагинации.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод, IP или аккаунт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Лимит запросов, соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность API. Повторите чтение с паузой.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "shopPurchase",
        "summary": "Купить товар с баланса",
        "description": "Атомарно списывает баланс и выдаёт товар. 201 — новая покупка, 200 — прежний результат. expected_total_usdt_cents обязателен. Нет ручной/оптовой выдачи, внешней оплаты, промокодов или смены владельца. Необходимы shop_purchase и shop_read. Ключ и тело повторяются неизменно до определённого результата. Ошибки shop.terms_required, shop.email_required и shop.balance_disabled сохраняются за Idempotency-Key; после устранения причины используйте новый ключ только для осознанной новой попытки.",
        "tags": [
          "Reseller"
        ],
        "x-permission": "shop_purchase",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-ID",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            }
          },
          {
            "in": "header",
            "name": "Accept-Language",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_.:-]{8,128}$"
            },
            "description": "Сохраните один ключ на один оплаченный заказ в своей БД до запроса. При повторах ключ и тело неизменны. Область уникальности — API-клиент, сохраняется после перевыпуска токена. Новый ключ, созданный в профиле, создаёт отдельного API-клиента; его идемпотентность независима."
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Язык ответа. Приоритет: lang, language, X-Language, Accept-Language; по умолчанию ru."
          }
        ],
        "responses": {
          "200": {
            "description": "Прежний результат покупки.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopOrderResponse"
                }
              }
            }
          },
          "201": {
            "description": "Новый заказ оплачен и выдан.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopOrderResponse"
                }
              }
            }
          },
          "400": {
            "description": "Неверный JSON/параметры/Idempotency-Key.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод, IP или аккаунт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "404": {
            "description": "Товар недоступен / нет заказа этого API-клиента.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "409": {
            "description": "Конфликт ключа запроса, цены, остатков, баланса или выдачи.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "413": {
            "description": "Тело больше 8192 байт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "415": {
            "description": "Требуется application/json или тип с окончанием +json.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Лимит запросов, соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "Временный сбой. Повтор покупки — с тем же Idempotency-Key и телом.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShopPurchaseRequest"
              }
            }
          }
        }
      }
    },
    "/orders/{order_id}": {
      "get": {
        "operationId": "shopOrder",
        "summary": "Получить заказ и его выдачу",
        "description": "Только заказ, созданный этим API-клиентом. Чужой ID возвращает 404.",
        "tags": [
          "Reseller"
        ],
        "x-permission": "shop_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-ID",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,64}$"
            }
          },
          {
            "in": "header",
            "name": "Accept-Language",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ],
              "default": "ru"
            }
          },
          {
            "in": "path",
            "name": "order_id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1,
              "maximum": 9223372036854775807
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ru",
                "en"
              ]
            },
            "description": "Язык ответа. Приоритет: lang, language, X-Language, Accept-Language; по умолчанию ru."
          }
        ],
        "responses": {
          "200": {
            "description": "Результат получен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopOrderResponse"
                }
              }
            }
          },
          "400": {
            "description": "Неверный ID или параметры пагинации.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "403": {
            "description": "Не разрешён метод, IP или аккаунт.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "404": {
            "description": "Товар недоступен / нет заказа этого API-клиента.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "429": {
            "description": "Лимит запросов, соблюдайте Retry-After.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          },
          "503": {
            "description": "Временная недоступность API. Повторите чтение с паузой.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShopError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "supplyme_live_*",
        "description": "Персональный ключ из Профиль → API. Передавайте только в Authorization: Bearer; храните на сервере. shop_read разрешает чтение, shop_purchase — покупки. Управление ключами требует сессии сайта и не входит в этот API."
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "request_id": {
            "type": "string",
            "maxLength": 64
          },
          "code": {
            "type": "string",
            "description": "Стабильный код; используйте его, а не message, в логике интеграции."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "request_id",
          "code",
          "message"
        ]
      },
      "StatusResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/StatusData"
              }
            },
            "required": [
              "data"
            ]
          }
        ]
      },
      "ShopProduct": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category_id": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "price_usdt_cents": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "enum": [
              "USDT"
            ]
          },
          "delivery_type": {
            "type": "string",
            "enum": [
              "text",
              "link"
            ]
          },
          "available_quantity": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "max_quantity_per_order": {
            "type": "integer",
            "enum": [
              10
            ]
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "category_id",
          "price_usdt_cents",
          "currency",
          "delivery_type",
          "available_quantity",
          "max_quantity_per_order"
        ]
      },
      "ShopOrder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "idempotency_key": {
            "type": "string"
          },
          "product_id": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "product_title": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "status": {
            "type": "string",
            "description": "Новый API-заказ — delivered. После действий поддержки возможны cancelled и другие состояния. Выдавайте только delivered с delivery != null."
          },
          "total_usdt_cents": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "enum": [
              "USDT"
            ]
          },
          "balance_after_usdt_cents": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Баланс сразу после этого списания, не текущий остаток."
          },
          "delivery": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "text",
                  "link"
                ]
              },
              "content": {
                "type": "string"
              },
              "items": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "nullable": true,
                "description": "Выданные единицы с сохранением переносов строк. null, если поддержка заменила содержимое заказа; используйте content."
              },
              "post_purchase_info": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "content",
              "items",
              "post_purchase_info"
            ],
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "idempotency_key",
          "product_id",
          "product_title",
          "quantity",
          "status",
          "total_usdt_cents",
          "currency",
          "balance_after_usdt_cents",
          "delivery",
          "created_at"
        ]
      },
      "ShopPurchaseRequest": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "maximum": 9223372036854775807
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1
          },
          "expected_total_usdt_cents": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "maximum": 1000000000000,
            "description": "Точная ожидаемая цена × количество. При несовпадении — 409 без списания."
          }
        },
        "required": [
          "product_id",
          "expected_total_usdt_cents"
        ],
        "additionalProperties": false
      },
      "ShopCatalogResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "products": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ShopProduct"
                    }
                  },
                  "next_after_id": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 1,
                    "nullable": true
                  }
                },
                "required": [
                  "products",
                  "next_after_id"
                ]
              }
            },
            "required": [
              "data"
            ]
          }
        ]
      },
      "ShopBalanceResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "balance_usdt_cents": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "USDT"
                    ]
                  }
                },
                "required": [
                  "balance_usdt_cents",
                  "currency"
                ]
              }
            },
            "required": [
              "data"
            ]
          }
        ]
      },
      "ShopOrderResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "order": {
                    "$ref": "#/components/schemas/ShopOrder"
                  },
                  "replayed": {
                    "type": "boolean",
                    "description": "Присутствует в ответе POST; true означает ранее сохранённый результат."
                  }
                },
                "required": [
                  "order"
                ]
              }
            },
            "required": [
              "data"
            ]
          }
        ]
      },
      "ShopOrdersResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "orders": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ShopOrder"
                    }
                  },
                  "next_after_id": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 1,
                    "nullable": true
                  }
                },
                "required": [
                  "orders",
                  "next_after_id"
                ]
              }
            },
            "required": [
              "data"
            ]
          }
        ]
      },
      "ShopError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "data": {
                "type": "object",
                "properties": {
                  "replayed": {
                    "type": "boolean"
                  },
                  "retry_after": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  },
                  "available_quantity": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  },
                  "current_total_usdt_cents": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  },
                  "balance_usdt_cents": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  },
                  "required_usdt_cents": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0
                  }
                },
                "required": []
              }
            },
            "required": []
          }
        ]
      },
      "StatusData": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "normal",
              "maintenance"
            ],
            "description": "Сводное состояние SupplyMe."
          },
          "api": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "enum": [
                  "v1"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "operational",
                  "maintenance"
                ]
              },
              "currency": {
                "type": "string",
                "enum": [
                  "USDT"
                ]
              }
            },
            "required": [
              "version",
              "status",
              "currency"
            ]
          },
          "permissions": {
            "type": "object",
            "properties": {
              "shop_read": {
                "type": "boolean"
              },
              "shop_purchase": {
                "type": "boolean"
              }
            },
            "required": [
              "shop_read",
              "shop_purchase"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "rate_limit_per_minute": {
                "type": "integer",
                "minimum": 1
              },
              "daily_limit": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "rate_limit_per_minute",
              "daily_limit"
            ]
          },
          "account": {
            "type": "object",
            "properties": {
              "bound": {
                "type": "boolean",
                "description": "Ключ привязан к аккаунту магазина."
              }
            },
            "required": [
              "bound"
            ]
          }
        },
        "required": [
          "status",
          "api",
          "permissions",
          "limits",
          "account"
        ]
      },
      "StatusError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "data": {
                "$ref": "#/components/schemas/StatusData"
              }
            }
          }
        ]
      }
    }
  },
  "externalDocs": {
    "description": "Руководство по подключению и восстановлению покупок",
    "url": "https://supply-me.ru/api/docs"
  }
}
