{
  "openapi": "3.1.0",
  "info": {
    "title": "Hubris API",
    "version": "1.0.0",
    "description": "OpenAI-совместимый API российского LLM-агрегатора. Все цены в рублях.\n\nВерсии и вывод из эксплуатации (deprecation policy): несовместимые изменения — только в новой версии префикса (`/v2`); об отключении эндпоинта или поля предупреждаем не меньше чем за 90 дней заголовками `Deprecation` (RFC 9745) и `Sunset` (RFC 8594), записью в журнале изменений и письмом. Подробно: https://hubris.pw/docs/api/versioning"
  },
  "servers": [
    {
      "url": "https://api.hubris.pw",
      "description": "Production"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk-gw-...",
        "description": "API-ключ в формате `sk-gw-` + 32 hex. Создаётся в дашборде на /keys. Обычный ключ даёт все права, ключ только для чтения не может тратить баланс."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth-токен приложения с ограниченными правами. Регистрация клиента — `POST /oauth/clients` (RFC 7591), PKCE S256 обязателен. Метаданные: `/.well-known/oauth-authorization-server`, `/.well-known/oauth-protected-resource`.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.hubris.pw/oauth/authorize",
            "tokenUrl": "https://api.hubris.pw/oauth/token",
            "refreshUrl": "https://api.hubris.pw/oauth/token",
            "scopes": {
              "chat:write": "Запросы к моделям от имени пользователя (списывают баланс): чат, Responses, Messages, эмбеддинги, реранкеры, модели решений, изображения, распознавание и озвучка речи, расшифровка видео; коннекторы Битрикс24.",
              "models:read": "Видеть цепочки резервных моделей пользователя в `GET /v1/models`.",
              "balance:read": "Видеть остаток баланса пользователя.",
              "videos:write": "Создавать видео от имени пользователя (`POST /v1/videos`, резервирует и списывает баланс).",
              "videos:read": "Узнавать статус и скачивать видео пользователя (`GET /v1/videos/{id}`, `GET /v1/videos/{id}/content`).",
              "offline_access": "Выдать refresh-токен, чтобы подключение жило 90 дней без повторного входа."
            }
          }
        }
      }
    },
    "schemas": {
      "TranscriptionResponse": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "Распознанный текст. Пустая строка — тоже результат: в записи тишина."
          },
          "usage": {
            "type": "object",
            "properties": {
              "seconds": {
                "type": "number",
                "description": "Длительность обработанного аудио в секундах, если модель её сообщает."
              },
              "input_tokens": {
                "type": "integer"
              },
              "output_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              },
              "cost": {
                "type": "integer",
                "description": "Списано с баланса, в копейках."
              }
            }
          }
        },
        "required": [
          "text"
        ]
      },
      "TranscriptionMultipartRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "Аудиофайл: WAV, MP3, FLAC, M4A, OGG, WebM, AAC. До 25 МБ."
          },
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "openai/whisper-1"
          },
          "language": {
            "type": "string",
            "description": "Язык записи в ISO-639-1 (`ru`, `en`). Без поля язык определяется сам."
          },
          "prompt": {
            "type": "string",
            "description": "Подсказка: имена, термины, аббревиатуры, которые встречаются в записи."
          },
          "temperature": {
            "type": "number"
          },
          "response_format": {
            "type": "string",
            "enum": [
              "json",
              "verbose_json"
            ],
            "description": "`text`, `srt` и `vtt` не поддерживаются (400). Поддержка `verbose_json` зависит от модели."
          },
          "timestamp_granularities[]": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "segment",
                "word"
              ]
            },
            "description": "Таймкоды в `verbose_json`; поддерживаются не всеми моделями."
          }
        },
        "required": [
          "file",
          "model"
        ]
      },
      "TranscriptionJsonRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "openai/whisper-1"
          },
          "input_audio": {
            "type": "object",
            "properties": {
              "data": {
                "type": "string",
                "minLength": 1,
                "description": "Аудио в base64 (без data:-префикса)."
              },
              "format": {
                "type": "string",
                "minLength": 1,
                "description": "Формат: wav, mp3, flac, m4a, ogg, webm, aac.",
                "example": "mp3"
              }
            },
            "required": [
              "data",
              "format"
            ],
            "description": "Аудио для распознавания. Прямые URL не поддерживаются."
          }
        },
        "required": [
          "model",
          "input_audio"
        ]
      },
      "SpeechRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "microsoft/mai-voice-2-flash"
          },
          "input": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50000,
            "description": "Текст для озвучки. Цена — по единице модели в каталоге: за символы текста или за токены (у Gemini 25 токенов на секунду звука).",
            "example": "Привет! Это проверка озвучки."
          },
          "voice": {
            "type": "string",
            "minLength": 1,
            "description": "Голос модели. Список — в карточке модели каталога (поле «Голоса»); обязателен, если список есть.",
            "example": "en-US-Harper:MAI-Voice-2"
          },
          "response_format": {
            "type": "string",
            "enum": [
              "mp3",
              "pcm"
            ],
            "description": "Формат аудио: mp3 или pcm (16-bit LE). Без поля формат выбирает модель, как правило pcm."
          }
        },
        "required": [
          "model",
          "input"
        ]
      },
      "VideoJobCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Номер задачи.",
            "example": "b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "polling_url": {
            "type": "string",
            "format": "uri",
            "description": "Адрес опроса статуса — `GET /v1/videos/{id}`."
          },
          "created": {
            "type": "integer",
            "description": "Время создания задачи, Unix-секунды."
          }
        },
        "required": [
          "id",
          "status",
          "polling_url",
          "created"
        ]
      },
      "VideoFrameImage": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "image_url"
            ]
          },
          "image_url": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "url"
            ],
            "additionalProperties": false
          },
          "frame_type": {
            "type": "string",
            "enum": [
              "first_frame",
              "last_frame"
            ]
          }
        },
        "required": [
          "type",
          "image_url",
          "frame_type"
        ],
        "additionalProperties": false
      },
      "VideoInputReference": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "image_url"
                ]
              },
              "image_url": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "type",
              "image_url"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "video_url"
                ]
              },
              "video_url": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "type",
              "video_url"
            ],
            "additionalProperties": false
          }
        ]
      },
      "CreateVideoRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "kwaivgi/kling-v3.0-pro"
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50000
          },
          "duration": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60
          },
          "resolution": {
            "type": "string",
            "maxLength": 10
          },
          "aspect_ratio": {
            "type": "string",
            "maxLength": 10
          },
          "size": {
            "type": "string",
            "maxLength": 16
          },
          "generate_audio": {
            "type": "boolean"
          },
          "seed": {
            "type": "integer"
          },
          "frame_images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VideoFrameImage"
            },
            "maxItems": 2
          },
          "input_references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VideoInputReference"
            },
            "minItems": 1,
            "maxItems": 4
          },
          "upscale_factor": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "creativity": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "provider": {
            "type": "object",
            "properties": {
              "options": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "parameters": {
                      "type": "object",
                      "additionalProperties": {
                        "nullable": true
                      }
                    }
                  },
                  "required": [
                    "parameters"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "required": [
              "options"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "model",
          "prompt"
        ],
        "additionalProperties": false
      },
      "VideoJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_progress",
              "completed",
              "failed"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Время создания задачи, Unix-секунды."
          },
          "unsigned_urls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Только при `completed`: адрес скачивания `GET /v1/videos/{id}/content?index=0`. Несмотря на имя, нужен тот же ключ."
          },
          "usage": {
            "type": "object",
            "properties": {
              "cost": {
                "type": "integer",
                "description": "При `completed`: итоговое списание, копейки."
              },
              "estimated_cost": {
                "type": "integer",
                "description": "Пока задача в работе: сумма, удержанная под задачу, копейки (верхняя оценка; если сверка прошла раньше готовности — уже списанная). После готовности приходит `cost`, разница возвращается на баланс."
              }
            }
          },
          "error": {
            "type": "string",
            "description": "Только при `failed`: нейтральный текст. Удержание возвращается целиком."
          }
        },
        "required": [
          "id",
          "status",
          "created"
        ]
      },
      "VideoTranscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vtr-3f9c1a7b2d4e5f60a1b2c3d4"
          },
          "object": {
            "type": "string",
            "enum": [
              "video.transcription"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Unix-секунды."
          },
          "model": {
            "type": "string",
            "description": "Модель, которая смотрела ролик."
          },
          "video": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "ID ролика на YouTube."
              },
              "title": {
                "type": "string"
              },
              "duration_sec": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "duration_sec"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "exact",
              "fast"
            ]
          },
          "diarize": {
            "type": "boolean",
            "description": "В режиме `fast` всегда `false`."
          },
          "text": {
            "type": "string",
            "description": "Расшифровка или пересказ."
          },
          "truncated": {
            "type": "boolean",
            "description": "`true` — текст оборвался по лимиту длины ответа даже после продолжений, или продолжение не удалось и отдано собранное."
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              },
              "cost": {
                "type": "integer",
                "description": "Списано с баланса за все запросы к модели, копейки."
              },
              "requests": {
                "type": "integer",
                "description": "Сколько запросов к модели понадобилось."
              }
            },
            "required": [
              "prompt_tokens",
              "completion_tokens",
              "total_tokens",
              "cost",
              "requests"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "created",
          "model",
          "video",
          "mode",
          "diarize",
          "text",
          "truncated",
          "usage"
        ]
      },
      "VideoTranscriptionRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "Ссылка на ролик YouTube: `youtube.com/watch?v=…`, `youtu.be/…`, `youtube.com/shorts/…`, `youtube.com/live/…`.",
            "example": "https://youtu.be/ITL6WqcV6sE"
          },
          "mode": {
            "type": "string",
            "enum": [
              "exact",
              "fast"
            ],
            "default": "exact",
            "description": "`exact` — дословная расшифровка, каждая реплика с новой строки и таймкодом `[HH:MM:SS]`. `fast` — пересказ и ключевые мысли с таймкодами: быстрее и дешевле на длинном ролике, таймкоды приблизительные."
          },
          "diarize": {
            "type": "boolean",
            "default": false,
            "description": "Только для `exact`: помечать реплики говорящими («Говорящий 1:» или имя, если оно звучит в ролике)."
          }
        },
        "required": [
          "url"
        ]
      },
      "Bitrix24ConnectorCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "completions_url": {
            "type": "string",
            "format": "uri",
            "description": "Адрес для `completions_url` при регистрации движка в Битрикс24 (`ai.engine.register`). Содержит секрет и показывается один раз."
          },
          "model": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string",
            "description": "Маскированный префикс выпущенного ключа.",
            "example": "sk-gw-a1b2...c3d4"
          }
        },
        "required": [
          "id",
          "completions_url",
          "model",
          "key_prefix"
        ]
      },
      "Bitrix24ConnectorCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Имя подключения: видно в кабинете и в имени выпущенного ключа «Битрикс24 · <имя>».",
            "example": "Отдел продаж"
          },
          "model": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Полный ID модели каталога. Битрикс24 модель не передаёт, она закрепляется за коннектором.",
            "example": "anthropic/claude-sonnet-5"
          },
          "limit_kopecks": {
            "type": "integer",
            "minimum": 100,
            "maximum": 10000000,
            "description": "Дневной лимит расхода выпущенного ключа, копейки.",
            "example": 50000
          }
        },
        "required": [
          "name",
          "model"
        ]
      },
      "Bitrix24Connector": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string",
            "example": "sk-gw-a1b2...c3d4"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "model",
          "key_prefix",
          "created_at",
          "last_used_at"
        ]
      },
      "Bitrix24ConnectorList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Bitrix24Connector"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "Bitrix24ConnectorDeleted": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "deleted"
        ]
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "anthropic/claude-haiku-4.5"
          },
          "object": {
            "type": "string",
            "enum": [
              "model"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Unix-timestamp последнего обновления записи в каталоге Hubris."
          },
          "owned_by": {
            "type": "string",
            "example": "anthropic"
          },
          "display_name": {
            "type": "string",
            "example": "Claude Haiku 4.5"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Описание модели на русском языке (если переведено)."
          },
          "context_window": {
            "type": "integer",
            "example": 200000
          },
          "context_length": {
            "type": "integer",
            "description": "То же, что `context_window`, — под именем, которое читают многие OpenAI-совместимые клиенты (RAGFlow и другие).",
            "example": 200000
          },
          "modalities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Legacy OpenAI поле — равно `output_modalities`. Используйте `output_modalities` / `input_modalities` для точного фильтра.",
            "example": [
              "text",
              "image"
            ]
          },
          "input_modalities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Что модель принимает на вход: `text`, `image`, `audio`, `file`.",
            "example": [
              "text",
              "image"
            ]
          },
          "output_modalities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Что модель возвращает: `text` (chat / responses), `embeddings` (только /v1/embeddings), `image`, `audio`.",
            "example": [
              "text"
            ]
          },
          "supported_parameters": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Параметры запроса, которые поддерживает модель: `tools`, `tool_choice`, `reasoning`, `include_reasoning`, `response_format`, `structured_outputs`, `temperature`, `top_p`, `seed`, `stop`, `web_search_options` и другие. Клиент по этому списку решает, показывать ли настройки инструментов и размышления для конкретной модели, а не включает их вслепую. Пустой массив — список для модели неизвестен.",
            "example": [
              "tools",
              "tool_choice",
              "reasoning",
              "temperature",
              "max_tokens",
              "response_format",
              "structured_outputs"
            ]
          },
          "supported_voices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Голоса модели озвучки (только у моделей с `output_modalities: [\"speech\"]`). Значение для поля `voice` в POST /v1/audio/speech.",
            "example": [
              "en-US-Harper:MAI-Voice-2"
            ]
          },
          "pricing": {
            "type": "object",
            "properties": {
              "unit": {
                "type": "string",
                "enum": [
                  "token",
                  "unit",
                  "unknown"
                ],
                "description": "Единица тарификации. `token` — цены в `input_rub_per_million` / `output_rub_per_million` за 1М токенов. `unit` — тарификация в других единицах (изображение, мегапиксель, минута, секунда видео), реальная цена в `per_unit`, а токенные поля равны нулю. `unknown` — провайдер не публикует тариф, списывается фактическая стоимость запроса. Считайте бюджет по этому полю: у нетокенных моделей нельзя умножать `input_rub_per_million` на число токенов.",
                "example": "token"
              },
              "input_rub_per_million": {
                "type": "number",
                "description": "Цена за 1М входных токенов. Осмысленна только при `unit: \"token\"`; иначе 0 — смотрите `per_unit`.",
                "example": 30.45
              },
              "output_rub_per_million": {
                "type": "number",
                "description": "Цена за 1М выходных токенов. Осмысленна только при `unit: \"token\"`; иначе 0 — смотрите `per_unit`.",
                "example": 152.25
              },
              "currency": {
                "type": "string",
                "enum": [
                  "RUB"
                ]
              },
              "per_unit": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "sku": {
                      "type": "string",
                      "example": "Output Image"
                    },
                    "price_rub": {
                      "type": "number",
                      "example": 3.6
                    },
                    "unit": {
                      "type": "string",
                      "example": "per megapixel"
                    }
                  },
                  "required": [
                    "sku",
                    "price_rub",
                    "unit"
                  ]
                },
                "description": "Цены за единицу (изображение, мегапиксель, reference). Присутствует только для моделей с unit-pricing — Flux, Recraft, Sourceful, Gemini Image."
              },
              "is_free": {
                "type": "boolean",
                "description": "Бесплатна ли модель. Определяет сервер: нулевые цены во ВСЕХ единицах тарификации и немедийный выход. Ориентируйтесь на этот флаг, а не на `input_rub_per_million === 0`: у моделей с оплатой за изображение или секунду видео цена за токены нулевая, но запрос платный.",
                "example": false
              }
            },
            "required": [
              "unit",
              "input_rub_per_million",
              "output_rub_per_million",
              "currency",
              "is_free"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "created",
          "owned_by",
          "display_name",
          "description",
          "context_window",
          "context_length",
          "modalities",
          "input_modalities",
          "output_modalities",
          "supported_parameters",
          "pricing"
        ]
      },
      "ModelsList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Model"
            }
          }
        },
        "required": [
          "object",
          "data"
        ]
      },
      "ErrorCode": {
        "type": "string",
        "enum": [
          "invalid_request",
          "invalid_api_key",
          "insufficient_balance",
          "daily_limit_exceeded",
          "model_not_found",
          "exchange_rate_unavailable",
          "upstream_error",
          "upstream_timeout",
          "too_many_active_jobs",
          "video_not_ready",
          "index_out_of_range",
          "byok_disabled",
          "byok_egress_unavailable",
          "byok_not_configured",
          "byok_insufficient_credits",
          "byok_not_supported_for_videos"
        ]
      },
      "ErrorObject": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "param": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "message",
          "type",
          "code"
        ]
      },
      "ModelsErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      },
      "VideoModel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "kwaivgi/kling-v3.0-pro"
          },
          "object": {
            "type": "string",
            "enum": [
              "video_model"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Unix-timestamp последнего обновления записи в каталоге Hubris."
          },
          "owned_by": {
            "type": "string",
            "example": "kwaivgi"
          },
          "display_name": {
            "type": "string",
            "example": "Kling v3.0 Pro"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Описание модели на русском языке (если переведено)."
          },
          "supported_resolutions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "720p",
              "1080p"
            ]
          },
          "supported_aspect_ratios": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "16:9",
              "9:16"
            ]
          },
          "supported_sizes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "1280x720"
            ]
          },
          "supported_durations": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "example": [
              5,
              8
            ]
          },
          "supported_frame_images": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Какие опорные кадры принимает модель для image-to-video.",
            "example": [
              "first_frame"
            ]
          },
          "generate_audio": {
            "type": "boolean",
            "description": "Поддерживает ли модель генерацию звука."
          },
          "seed": {
            "type": "boolean",
            "description": "Поддерживает ли модель детерминированный seed."
          },
          "required_input": {
            "type": "string",
            "nullable": true,
            "enum": [
              "video",
              "image"
            ],
            "description": "Что модели обязательно передать в input_references: исходное видео или фото. null — вход не нужен."
          },
          "upscale_factor": {
            "type": "object",
            "nullable": true,
            "properties": {
              "min": {
                "type": "number"
              },
              "max": {
                "type": "number"
              }
            },
            "required": [
              "min",
              "max"
            ]
          },
          "creativity": {
            "type": "object",
            "nullable": true,
            "properties": {
              "min": {
                "type": "number"
              },
              "max": {
                "type": "number"
              }
            },
            "required": [
              "min",
              "max"
            ]
          },
          "allowed_passthrough_parameters": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ключи, которые можно передать в provider.options.<поставщик>.parameters."
          },
          "pricing": {
            "type": "object",
            "properties": {
              "per_unit": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "sku": {
                      "type": "string",
                      "example": "video"
                    },
                    "price_rub": {
                      "type": "number",
                      "example": 10.33
                    },
                    "unit": {
                      "type": "string",
                      "example": "second"
                    }
                  },
                  "required": [
                    "sku",
                    "price_rub",
                    "unit"
                  ]
                },
                "description": "Цены за единицу в рублях (секунда/видео). Апстрим-цены в USD не раскрываются."
              },
              "currency": {
                "type": "string",
                "enum": [
                  "RUB"
                ]
              }
            },
            "required": [
              "per_unit",
              "currency"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "created",
          "owned_by",
          "display_name",
          "description",
          "supported_resolutions",
          "supported_aspect_ratios",
          "supported_sizes",
          "supported_durations",
          "supported_frame_images",
          "generate_audio",
          "seed",
          "required_input",
          "upscale_factor",
          "creativity",
          "allowed_passthrough_parameters",
          "pricing"
        ]
      },
      "VideoModelsList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VideoModel"
            }
          }
        },
        "required": [
          "object",
          "data"
        ]
      },
      "VideoModelsErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      },
      "CacheControl": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "ephemeral"
            ]
          },
          "ttl": {
            "type": "string",
            "enum": [
              "5m",
              "1h"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "TextContentPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text"
            ]
          },
          "text": {
            "type": "string"
          },
          "cache_control": {
            "$ref": "#/components/schemas/CacheControl"
          }
        },
        "required": [
          "type",
          "text"
        ]
      },
      "ToolCall": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "function"
            ]
          },
          "function": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "arguments": {
                "type": "string",
                "description": "JSON-строка с аргументами функции."
              }
            },
            "required": [
              "name",
              "arguments"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "function"
        ]
      },
      "GeneratedImage": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "image_url"
            ]
          },
          "image_url": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "description": "Base64 data URL вида `data:image/png;base64,...`",
                "example": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
              }
            },
            "required": [
              "url"
            ]
          }
        },
        "required": [
          "type",
          "image_url"
        ]
      },
      "AudioOutput": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "data": {
            "type": "string",
            "description": "Аудио ответа в base64 (формат — из запроса `audio.format`)."
          },
          "transcript": {
            "type": "string",
            "description": "Текстовая расшифровка сказанного."
          },
          "expires_at": {
            "type": "number"
          }
        }
      },
      "AssistantMessage": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "assistant"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TextContentPart"
                }
              },
              {
                "nullable": true
              }
            ]
          },
          "tool_calls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolCall"
            }
          },
          "name": {
            "type": "string"
          },
          "refusal": {
            "type": "string",
            "nullable": true
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GeneratedImage"
            }
          },
          "audio": {
            "$ref": "#/components/schemas/AudioOutput"
          }
        },
        "required": [
          "role"
        ]
      },
      "FinishReason": {
        "type": "string",
        "nullable": true,
        "enum": [
          "stop",
          "length",
          "tool_calls",
          "content_filter",
          "function_call"
        ]
      },
      "Choice": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "message": {
            "$ref": "#/components/schemas/AssistantMessage"
          },
          "finish_reason": {
            "$ref": "#/components/schemas/FinishReason"
          },
          "logprobs": {
            "nullable": true
          }
        },
        "required": [
          "index",
          "message",
          "finish_reason"
        ]
      },
      "Usage": {
        "type": "object",
        "properties": {
          "prompt_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "completion_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "total_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "completion_tokens_details": {
            "type": "object",
            "properties": {
              "reasoning_tokens": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "prompt_tokens_details": {
            "type": "object",
            "properties": {
              "cached_tokens": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "required": [
          "prompt_tokens",
          "completion_tokens",
          "total_tokens"
        ]
      },
      "ChatCompletionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "chatcmpl-abc123"
          },
          "object": {
            "type": "string",
            "enum": [
              "chat.completion"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Unix-timestamp в секундах."
          },
          "model": {
            "type": "string"
          },
          "choices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Choice"
            },
            "minItems": 1
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          },
          "system_fingerprint": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices",
          "usage"
        ]
      },
      "ChatCompletionErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      },
      "ImageUrlContentPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "image_url"
            ]
          },
          "image_url": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "description": "URL изображения или data:image/<mime>;base64,..."
              },
              "detail": {
                "type": "string",
                "enum": [
                  "auto",
                  "low",
                  "high"
                ]
              }
            },
            "required": [
              "url"
            ]
          },
          "cache_control": {
            "$ref": "#/components/schemas/CacheControl"
          }
        },
        "required": [
          "type",
          "image_url"
        ]
      },
      "InputAudioContentPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "input_audio"
            ]
          },
          "input_audio": {
            "type": "object",
            "properties": {
              "data": {
                "type": "string",
                "minLength": 1,
                "description": "Аудио в base64 БЕЗ префикса `data:` — только сами данные."
              },
              "format": {
                "type": "string",
                "enum": [
                  "wav",
                  "mp3",
                  "aiff",
                  "aac",
                  "ogg",
                  "flac",
                  "m4a",
                  "pcm16",
                  "pcm24"
                ],
                "description": "Формат присланного аудио.",
                "example": "wav"
              }
            },
            "required": [
              "data",
              "format"
            ]
          },
          "cache_control": {
            "$ref": "#/components/schemas/CacheControl"
          }
        },
        "required": [
          "type",
          "input_audio"
        ]
      },
      "VideoUrlContentPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "video_url"
            ]
          },
          "video_url": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "minLength": 1,
                "description": "Ссылка на публичный ролик YouTube или `data:video/<mime>;base64,...`.",
                "example": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
              },
              "processing": {
                "type": "string",
                "enum": [
                  "agentic",
                  "static"
                ],
                "description": "Режим обработки видео у Gemini: `agentic` — модель сама перемещается по ролику (дешевле на длинных видео), `static` — просмотр целиком с фиксированной частотой кадров."
              }
            },
            "required": [
              "url"
            ]
          }
        },
        "required": [
          "type",
          "video_url"
        ]
      },
      "ContentPart": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TextContentPart"
          },
          {
            "$ref": "#/components/schemas/ImageUrlContentPart"
          },
          {
            "$ref": "#/components/schemas/InputAudioContentPart"
          },
          {
            "$ref": "#/components/schemas/VideoUrlContentPart"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "text": "#/components/schemas/TextContentPart",
            "image_url": "#/components/schemas/ImageUrlContentPart",
            "input_audio": "#/components/schemas/InputAudioContentPart",
            "video_url": "#/components/schemas/VideoUrlContentPart"
          }
        }
      },
      "SystemMessage": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "system"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ContentPart"
                }
              }
            ]
          },
          "name": {
            "type": "string"
          },
          "cache_control": {
            "type": "object",
            "nullable": true,
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "ephemeral"
                ]
              },
              "ttl": {
                "type": "string",
                "enum": [
                  "5m",
                  "1h"
                ]
              }
            },
            "required": [
              "type"
            ],
            "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
          }
        },
        "required": [
          "role",
          "content"
        ]
      },
      "UserMessage": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "user"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ContentPart"
                }
              }
            ]
          },
          "name": {
            "type": "string"
          },
          "cache_control": {
            "type": "object",
            "nullable": true,
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "ephemeral"
                ]
              },
              "ttl": {
                "type": "string",
                "enum": [
                  "5m",
                  "1h"
                ]
              }
            },
            "required": [
              "type"
            ],
            "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
          }
        },
        "required": [
          "role",
          "content"
        ]
      },
      "ToolCallInput": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ToolCall"
          },
          {
            "type": "object",
            "properties": {
              "cache_control": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "ephemeral"
                    ]
                  },
                  "ttl": {
                    "type": "string",
                    "enum": [
                      "5m",
                      "1h"
                    ]
                  }
                },
                "required": [
                  "type"
                ],
                "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
              }
            }
          }
        ]
      },
      "AssistantMessageInput": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AssistantMessage"
          },
          {
            "type": "object",
            "properties": {
              "tool_calls": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ToolCallInput"
                }
              },
              "cache_control": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "ephemeral"
                    ]
                  },
                  "ttl": {
                    "type": "string",
                    "enum": [
                      "5m",
                      "1h"
                    ]
                  }
                },
                "required": [
                  "type"
                ],
                "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
              }
            }
          }
        ]
      },
      "ToolMessage": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "tool"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TextContentPart"
                }
              }
            ]
          },
          "tool_call_id": {
            "type": "string"
          },
          "cache_control": {
            "type": "object",
            "nullable": true,
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "ephemeral"
                ]
              },
              "ttl": {
                "type": "string",
                "enum": [
                  "5m",
                  "1h"
                ]
              }
            },
            "required": [
              "type"
            ],
            "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
          }
        },
        "required": [
          "role",
          "content",
          "tool_call_id"
        ]
      },
      "Message": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/SystemMessage"
          },
          {
            "$ref": "#/components/schemas/UserMessage"
          },
          {
            "$ref": "#/components/schemas/AssistantMessageInput"
          },
          {
            "$ref": "#/components/schemas/ToolMessage"
          }
        ],
        "discriminator": {
          "propertyName": "role",
          "mapping": {
            "system": "#/components/schemas/SystemMessage",
            "user": "#/components/schemas/UserMessage",
            "assistant": "#/components/schemas/AssistantMessageInput",
            "tool": "#/components/schemas/ToolMessage"
          }
        }
      },
      "FunctionToolDefinition": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "function"
            ]
          },
          "function": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "parameters": {
                "type": "object",
                "additionalProperties": {
                  "nullable": true
                },
                "default": {
                  "type": "object",
                  "properties": {}
                },
                "description": "JSON Schema объект с описанием параметров функции. Без него — функция без аргументов."
              },
              "strict": {
                "type": "boolean",
                "nullable": true
              }
            },
            "required": [
              "name"
            ]
          },
          "cache_control": {
            "type": "object",
            "nullable": true,
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "ephemeral"
                ]
              },
              "ttl": {
                "type": "string",
                "enum": [
                  "5m",
                  "1h"
                ]
              }
            },
            "required": [
              "type"
            ],
            "description": "Маркер кеша на весь элемент — для клиентов, которые ставят его сюда. Основное место — `cache_control` на content-блоке."
          }
        },
        "required": [
          "type",
          "function"
        ]
      },
      "ServerToolDefinition": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "type"
        ]
      },
      "ToolDefinition": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/FunctionToolDefinition"
          },
          {
            "$ref": "#/components/schemas/ServerToolDefinition"
          }
        ]
      },
      "ToolChoice": {
        "anyOf": [
          {
            "type": "string",
            "enum": [
              "none",
              "auto",
              "required"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "function"
                ]
              },
              "function": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            },
            "required": [
              "type",
              "function"
            ]
          }
        ]
      },
      "ResponseFormat": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "text"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "json_object"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "json_schema"
                ]
              },
              "json_schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "schema": {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  },
                  "strict": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "schema"
                ]
              }
            },
            "required": [
              "type",
              "json_schema"
            ]
          }
        ]
      },
      "StreamOptions": {
        "type": "object",
        "properties": {
          "include_usage": {
            "type": "boolean",
            "description": "Hubris автоматически выставляет true для всех stream-запросов. Указывать необязательно."
          }
        }
      },
      "ChatCompletionRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "anthropic/claude-haiku-4.5"
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "minItems": 1,
            "maxItems": 10,
            "description": "Список fallback-моделей. Если основная (`model`) недоступна — попробует следующие по порядку. Биллинг по фактически использованной (см. `model` в ответе).",
            "example": [
              "anthropic/claude-sonnet-4.6",
              "openai/gpt-4o-mini"
            ]
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            },
            "minItems": 1
          },
          "tools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolDefinition"
            }
          },
          "tool_choice": {
            "$ref": "#/components/schemas/ToolChoice"
          },
          "parallel_tool_calls": {
            "type": "boolean"
          },
          "response_format": {
            "$ref": "#/components/schemas/ResponseFormat"
          },
          "temperature": {
            "type": "number",
            "minimum": 0,
            "maximum": 2
          },
          "top_p": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "n": {
            "type": "integer",
            "minimum": 1
          },
          "stop": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "max_completion_tokens": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "frequency_penalty": {
            "type": "number",
            "minimum": -2,
            "maximum": 2
          },
          "presence_penalty": {
            "type": "number",
            "minimum": -2,
            "maximum": 2
          },
          "logit_bias": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "seed": {
            "type": "integer"
          },
          "logprobs": {
            "type": "boolean"
          },
          "top_logprobs": {
            "type": "integer",
            "minimum": 0,
            "maximum": 20
          },
          "modalities": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "image",
                "audio"
              ]
            },
            "description": "Какие модальности должна вернуть модель. По умолчанию `[\"text\"]`. Для генерации изображений: `[\"image\",\"text\"]` (модели типа gemini-flash-image) либо `[\"image\"]` (модели типа flux/sdxl). Для голосового ответа: `[\"text\",\"audio\"]` вместе с полем `audio` и обязательным `stream: true`. Поддерживается только моделями, у которых соответствующая модальность есть в `output_modalities`.",
            "example": [
              "image",
              "text"
            ]
          },
          "audio": {
            "type": "object",
            "properties": {
              "voice": {
                "type": "string",
                "description": "Голос озвучки, например `alloy`.",
                "example": "alloy"
              },
              "format": {
                "type": "string",
                "description": "Формат аудио ответа: `wav`, `mp3`, `pcm16` и т.п.",
                "example": "wav"
              }
            },
            "required": [
              "voice",
              "format"
            ],
            "description": "Настройки голосового ответа. Требует `modalities: [\"text\",\"audio\"]` и `stream: true`."
          },
          "image_config": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            },
            "description": "Параметры image-gen моделей: aspect_ratio (`1:1`, `16:9`, `9:16` и т.д.), image_size (`0.5K`, `1K`, `2K`, `4K`), а также model-specific поля. Конкретный набор зависит от модели — см. карточку модели в каталоге.",
            "example": {
              "aspect_ratio": "16:9",
              "image_size": "2K"
            }
          },
          "stream": {
            "type": "boolean"
          },
          "stream_options": {
            "$ref": "#/components/schemas/StreamOptions"
          },
          "user": {
            "type": "string"
          },
          "reasoning_effort": {
            "type": "string",
            "enum": [
              "none",
              "minimal",
              "low",
              "medium",
              "high",
              "xhigh",
              "max"
            ]
          }
        },
        "required": [
          "model",
          "messages"
        ]
      },
      "ImageGenerationRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "black-forest-labs/flux.2-pro"
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "example": "a red cube on a plain white background"
          },
          "n": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "description": "Сколько изображений (клиппится по лимиту модели).",
            "example": 1
          },
          "size": {
            "type": "string",
            "description": "Размер, напр. \"1024x1024\" или тир \"2K\".",
            "example": "1024x1024"
          },
          "response_format": {
            "type": "string",
            "enum": [
              "b64_json",
              "url"
            ],
            "description": "MVP всегда отдаёт b64_json."
          }
        },
        "required": [
          "model",
          "prompt"
        ]
      },
      "ResponsesResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "resp_abc123"
          },
          "object": {
            "type": "string",
            "enum": [
              "response"
            ]
          },
          "created_at": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          },
          "output": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "nullable": true
              }
            }
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          },
          "status": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "created_at",
          "model",
          "output"
        ]
      },
      "ResponsesErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      },
      "ResponsesRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "example": "openai/o1-mini"
          },
          "input": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            ],
            "description": "Строка или массив input-блоков (см. OpenAI Responses API)."
          },
          "stream": {
            "type": "boolean"
          }
        },
        "required": [
          "model",
          "input"
        ]
      },
      "AnthropicCacheControl": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "ephemeral"
            ]
          },
          "ttl": {
            "type": "string",
            "enum": [
              "5m",
              "1h"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "AnthropicTextBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text"
            ]
          },
          "text": {
            "type": "string"
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          },
          "citations": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "nullable": true
              }
            }
          }
        },
        "required": [
          "type",
          "text"
        ]
      },
      "AnthropicImageBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "image"
            ]
          },
          "source": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "base64"
                    ]
                  },
                  "media_type": {
                    "type": "string",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/gif",
                      "image/webp"
                    ]
                  },
                  "data": {
                    "type": "string"
                  }
                },
                "required": [
                  "type",
                  "media_type",
                  "data"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "url"
                    ]
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "type",
                  "url"
                ]
              }
            ]
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          }
        },
        "required": [
          "type",
          "source"
        ]
      },
      "AnthropicToolUseBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "tool_use"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "input": {
            "nullable": true
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          }
        },
        "required": [
          "type",
          "id",
          "name"
        ]
      },
      "AnthropicToolResultBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "tool_result"
            ]
          },
          "tool_use_id": {
            "type": "string"
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AnthropicTextBlock"
                    },
                    {
                      "$ref": "#/components/schemas/AnthropicImageBlock"
                    }
                  ]
                }
              }
            ]
          },
          "is_error": {
            "type": "boolean"
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          }
        },
        "required": [
          "type",
          "tool_use_id"
        ]
      },
      "AnthropicDocumentBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "document"
            ]
          },
          "source": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          },
          "title": {
            "type": "string"
          },
          "context": {
            "type": "string"
          },
          "citations": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          }
        },
        "required": [
          "type",
          "source"
        ]
      },
      "AnthropicThinkingBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "thinking"
            ]
          },
          "thinking": {
            "type": "string"
          },
          "signature": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "thinking"
        ]
      },
      "AnthropicRedactedThinkingBlock": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "redacted_thinking"
            ]
          },
          "data": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "data"
        ]
      },
      "AnthropicContentBlock": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/AnthropicTextBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicImageBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicToolUseBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicToolResultBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicDocumentBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicThinkingBlock"
          },
          {
            "$ref": "#/components/schemas/AnthropicRedactedThinkingBlock"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              }
            },
            "required": [
              "type"
            ]
          }
        ]
      },
      "AnthropicStopReason": {
        "type": "string",
        "nullable": true,
        "enum": [
          "end_turn",
          "max_tokens",
          "stop_sequence",
          "tool_use",
          "pause_turn",
          "refusal"
        ]
      },
      "AnthropicResponseUsage": {
        "type": "object",
        "properties": {
          "input_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "output_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "cache_creation_input_tokens": {
            "type": "integer",
            "nullable": true,
            "minimum": 0
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "nullable": true,
            "minimum": 0
          },
          "cache_creation": {
            "nullable": true
          },
          "service_tier": {
            "type": "string",
            "nullable": true
          },
          "server_tool_use": {
            "nullable": true
          }
        },
        "required": [
          "input_tokens",
          "output_tokens"
        ]
      },
      "AnthropicMessagesResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "msg_01XYZ"
          },
          "type": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "assistant"
            ]
          },
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnthropicContentBlock"
            }
          },
          "model": {
            "type": "string"
          },
          "stop_reason": {
            "$ref": "#/components/schemas/AnthropicStopReason"
          },
          "stop_sequence": {
            "type": "string",
            "nullable": true
          },
          "usage": {
            "$ref": "#/components/schemas/AnthropicResponseUsage"
          },
          "container": {
            "nullable": true
          }
        },
        "required": [
          "id",
          "type",
          "role",
          "content",
          "model",
          "stop_reason",
          "stop_sequence",
          "usage"
        ]
      },
      "AnthropicErrorType": {
        "type": "string",
        "enum": [
          "invalid_request_error",
          "authentication_error",
          "permission_error",
          "not_found_error",
          "request_too_large",
          "rate_limit_error",
          "api_error",
          "overloaded_error",
          "billing_error",
          "timeout_error"
        ]
      },
      "AnthropicMessagesError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "$ref": "#/components/schemas/AnthropicErrorType"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "message"
            ]
          }
        },
        "required": [
          "type",
          "error"
        ]
      },
      "AnthropicMessage": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "user",
              "assistant",
              "system"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AnthropicContentBlock"
                }
              }
            ]
          }
        },
        "required": [
          "role",
          "content"
        ]
      },
      "AnthropicSystem": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnthropicTextBlock"
            }
          }
        ],
        "description": "Системный промпт. Строка или массив text-блоков (для гибкого cache_control)."
      },
      "AnthropicServerTool": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "pattern": "^[a-z_]+_\\d{8}$"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "max_uses": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "allowed_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "user_location": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          }
        },
        "required": [
          "type",
          "name"
        ]
      },
      "AnthropicTool": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "description": {
            "type": "string"
          },
          "input_schema": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          },
          "cache_control": {
            "$ref": "#/components/schemas/AnthropicCacheControl"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "input_schema"
        ]
      },
      "AnthropicToolChoice": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "auto"
                ]
              },
              "disable_parallel_tool_use": {
                "type": "boolean"
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "any"
                ]
              },
              "disable_parallel_tool_use": {
                "type": "boolean"
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "tool"
                ]
              },
              "name": {
                "type": "string"
              },
              "disable_parallel_tool_use": {
                "type": "boolean"
              }
            },
            "required": [
              "type",
              "name"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "none"
                ]
              }
            },
            "required": [
              "type"
            ]
          }
        ]
      },
      "AnthropicMessagesRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "description": "Имя модели. Принимаются и Anthropic-имена (`claude-sonnet-4-5`, `claude-3-5-sonnet-20241022`, `claude-haiku-4-5-latest`), и каноничные OR-имена (`anthropic/claude-sonnet-4.6`). См. /docs/integrations/claude-code.",
            "example": "claude-sonnet-4-5"
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "minItems": 1,
            "maxItems": 10,
            "description": "Список резервных моделей (расширение Hubris). Если `model` отвечает 429/5xx или не начинает ответ вовремя — запрос уходит к следующей по порядку. Модель, не принимающая содержимое запроса (картинки, документы), пропускается. Биллинг по фактически ответившей модели.",
            "example": [
              "claude-opus-4-1",
              "anthropic/claude-sonnet-4.6"
            ]
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Максимальное число токенов в ответе. Обязательное поле.",
            "example": 1024
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnthropicMessage"
            },
            "minItems": 1,
            "description": "Массив сообщений диалога. Чередование ролей user/assistant."
          },
          "system": {
            "$ref": "#/components/schemas/AnthropicSystem"
          },
          "metadata": {
            "type": "object",
            "properties": {
              "user_id": {
                "type": "string"
              }
            }
          },
          "stop_sequences": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stream": {
            "type": "boolean"
          },
          "temperature": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "top_p": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "top_k": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "tools": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AnthropicServerTool"
                },
                {
                  "$ref": "#/components/schemas/AnthropicTool"
                }
              ]
            }
          },
          "tool_choice": {
            "$ref": "#/components/schemas/AnthropicToolChoice"
          },
          "thinking": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "enabled",
                  "disabled",
                  "adaptive"
                ]
              },
              "budget_tokens": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "type"
            ],
            "description": "Extended thinking (Claude 4+). enabled + budget_tokens — бюджет на размышления; adaptive — режим Claude 5."
          },
          "service_tier": {
            "type": "string"
          }
        },
        "required": [
          "model",
          "max_tokens",
          "messages"
        ]
      },
      "Embedding": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "embedding"
            ]
          },
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "embedding": {
            "nullable": true,
            "description": "Массив чисел при `encoding_format=float` или base64-строка при `encoding_format=base64`."
          }
        },
        "required": [
          "object",
          "index"
        ]
      },
      "EmbeddingsUsage": {
        "type": "object",
        "properties": {
          "prompt_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "total_tokens": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "prompt_tokens",
          "total_tokens"
        ]
      },
      "EmbeddingsResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Embedding"
            }
          },
          "model": {
            "type": "string"
          },
          "usage": {
            "$ref": "#/components/schemas/EmbeddingsUsage"
          }
        },
        "required": [
          "object",
          "data",
          "model",
          "usage"
        ]
      },
      "EmbeddingsErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      },
      "EmbeddingsRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "description": "ID embedding-модели — например, `openai/text-embedding-3-small`. Полный список: GET /v1/models, отфильтруйте по `output_modalities` содержащему `embeddings`.",
            "example": "openai/text-embedding-3-small"
          },
          "input": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  }
                }
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "content": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "text"
                                ]
                              },
                              "text": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "type",
                              "text"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "image_url"
                                ]
                              },
                              "image_url": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "type": "string",
                                    "minLength": 1
                                  }
                                },
                                "required": [
                                  "url"
                                ]
                              }
                            },
                            "required": [
                              "type",
                              "image_url"
                            ]
                          }
                        ]
                      },
                      "minItems": 1
                    }
                  },
                  "required": [
                    "content"
                  ]
                }
              }
            ],
            "description": "Что превратить в вектор. Принимает: одну строку, массив строк (батч), массив токен-ID, массив массивов токен-ID или массив объектов `{content: [...]}` с частями `text` и `image_url` — для моделей с изображениями на входе (`input_modalities` содержит `image`). Максимум 2048 элементов в батче.",
            "example": "Привет, мир"
          },
          "encoding_format": {
            "type": "string",
            "enum": [
              "float",
              "base64"
            ],
            "description": "`float` (по умолчанию) — массив чисел в `embedding`. `base64` — base64-строка.",
            "example": "float"
          },
          "dimensions": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Уменьшенная размерность вектора. Поддерживается только моделями `text-embedding-3-*`.",
            "example": 256
          },
          "user": {
            "type": "string",
            "description": "Опциональный идентификатор конечного пользователя (для логов абьюза провайдера)."
          }
        },
        "required": [
          "model",
          "input"
        ]
      },
      "DecisionAnswer": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "noul",
              "choice",
              "score"
            ]
          },
          "noul": {
            "type": "number",
            "description": "Для `noul`: вероятность ответа «да», от 0 до 1."
          },
          "choice": {
            "type": "string",
            "description": "Для `choice`: ключ выбранного варианта."
          },
          "score": {
            "type": "number",
            "description": "Для `score`: ожидаемый уровень шкалы, дробное число от 0 до N−1."
          },
          "confidence": {
            "type": "number",
            "description": "Уверенность модели в ответе, от 0 до 1."
          },
          "probabilities": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Вероятность каждого варианта или уровня."
          },
          "legend": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            },
            "description": "Для `score`: номер уровня → его описание из запроса."
          }
        },
        "required": [
          "type"
        ]
      },
      "DecisionsUsage": {
        "type": "object",
        "properties": {
          "input_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "output_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "cost": {
            "type": "number",
            "description": "Списано за запрос, в копейках."
          }
        },
        "required": [
          "input_tokens",
          "output_tokens"
        ]
      },
      "DecisionsResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/DecisionAnswer"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/DecisionsUsage"
          }
        },
        "required": [
          "model",
          "answers",
          "usage"
        ]
      },
      "DecisionQuestion": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "noul"
                ]
              },
              "instructions": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  },
                  {
                    "type": "array",
                    "items": {
                      "nullable": true
                    }
                  }
                ]
              },
              "criteria": {
                "type": "object",
                "properties": {
                  "true": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "object",
                        "additionalProperties": {
                          "nullable": true
                        }
                      },
                      {
                        "type": "array",
                        "items": {
                          "nullable": true
                        }
                      }
                    ]
                  },
                  "false": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "object",
                        "additionalProperties": {
                          "nullable": true
                        }
                      },
                      {
                        "type": "array",
                        "items": {
                          "nullable": true
                        }
                      }
                    ]
                  }
                },
                "required": [
                  "true",
                  "false"
                ]
              }
            },
            "required": [
              "type",
              "instructions"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "choice"
                ]
              },
              "instructions": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  },
                  {
                    "type": "array",
                    "items": {
                      "nullable": true
                    }
                  }
                ]
              },
              "criteria": {
                "type": "object",
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object",
                      "additionalProperties": {
                        "nullable": true
                      }
                    },
                    {
                      "type": "array",
                      "items": {
                        "nullable": true
                      }
                    }
                  ]
                }
              }
            },
            "required": [
              "type",
              "instructions",
              "criteria"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "score"
                ]
              },
              "instructions": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  },
                  {
                    "type": "array",
                    "items": {
                      "nullable": true
                    }
                  }
                ]
              },
              "criteria": {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object",
                      "additionalProperties": {
                        "nullable": true
                      }
                    },
                    {
                      "type": "array",
                      "items": {
                        "nullable": true
                      }
                    }
                  ]
                },
                "minItems": 1
              }
            },
            "required": [
              "type",
              "instructions",
              "criteria"
            ]
          }
        ],
        "description": "Вопрос к модели. `noul` — да или нет, ответ — вероятность «да» от 0 до 1. `choice` — один вариант из `criteria` (объект «ключ → описание»). `score` — уровень на шкале из `criteria` (массив описаний уровней по порядку)."
      },
      "DecisionsRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "description": "ID модели решений, например `typesafe/jev-1.13`. Полный список: GET /v1/models, отфильтруйте по `output_modalities`, содержащему `decisions`.",
            "example": "typesafe/jev-1.13"
          },
          "state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": {
                  "nullable": true
                }
              },
              {
                "type": "array",
                "items": {
                  "nullable": true
                }
              }
            ],
            "description": "Данные, о которых задаются вопросы: строка, объект или массив.",
            "example": "Третий день не проходит оплата на сайте, клиенты уходят."
          },
          "questions": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/DecisionQuestion"
            },
            "description": "Вопросы по ключам. Ключ возвращается в `answers`. Все вопросы решаются за один запрос."
          },
          "user": {
            "type": "string",
            "maxLength": 256,
            "description": "Опциональный идентификатор конечного пользователя."
          }
        },
        "required": [
          "model",
          "state",
          "questions"
        ]
      },
      "RerankResult": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0,
            "description": "Номер документа во входном списке."
          },
          "relevance_score": {
            "type": "number",
            "description": "Насколько документ подходит к запросу: чем больше, тем лучше."
          },
          "document": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "image": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "index",
          "relevance_score"
        ]
      },
      "RerankUsage": {
        "type": "object",
        "properties": {
          "total_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "search_units": {
            "type": "integer",
            "minimum": 0,
            "description": "Поисковые единицы — у моделей с оплатой за поиск (Cohere)."
          },
          "cost": {
            "type": "number",
            "description": "Списано за запрос, в копейках."
          }
        }
      },
      "RerankResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RerankResult"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/RerankUsage"
          }
        },
        "required": [
          "model",
          "results",
          "usage"
        ]
      },
      "RerankDocument": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "image": {
                "type": "string",
                "description": "URL или data URI картинки."
              }
            }
          }
        ]
      },
      "RerankRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "minLength": 1,
            "description": "ID реранкера, например `cohere/rerank-v3.5`. Полный список: GET /v1/models?output_modalities=rerank.",
            "example": "cohere/rerank-v3.5"
          },
          "query": {
            "type": "string",
            "minLength": 1,
            "description": "Поисковый запрос, по которому сортируются документы.",
            "example": "Как вернуть деньги за заказ?"
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RerankDocument"
            },
            "minItems": 1,
            "maxItems": 1000,
            "description": "Документы для сортировки: строки или объекты `{ text, image }`.",
            "example": [
              "Возврат оформляется в личном кабинете.",
              "Доставка занимает 3–5 дней."
            ]
          },
          "top_n": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Сколько самых подходящих документов вернуть. По умолчанию все.",
            "example": 3
          },
          "user": {
            "type": "string",
            "maxLength": 256,
            "description": "Опциональный идентификатор конечного пользователя."
          }
        },
        "required": [
          "model",
          "query",
          "documents"
        ]
      },
      "UsagePeriod": {
        "type": "string",
        "nullable": true,
        "enum": [
          "today",
          "24h",
          "7d",
          "30d",
          "mtd"
        ],
        "description": "Шорткат, если запрос был сделан через `?period=`. Иначе null."
      },
      "UsageGranularity": {
        "type": "string",
        "nullable": true,
        "enum": [
          "hour",
          "day"
        ],
        "description": "Если `granularity` был задан, тут он же. Иначе null."
      },
      "UsageBucket": {
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time",
            "description": "Начало интервала в ISO 8601 (UTC).",
            "example": "2026-05-14T00:00:00.000Z"
          },
          "cost_rub": {
            "type": "number",
            "description": "Стоимость за интервал в рублях. cost_kopecks/100.",
            "example": 12.34
          },
          "cost_kopecks": {
            "type": "string",
            "description": "Стоимость за интервал в копейках (строка — чтобы пережить JSON без потери точности).",
            "example": "1234"
          },
          "requests": {
            "type": "integer",
            "minimum": 0,
            "example": 42
          }
        },
        "required": [
          "bucket",
          "cost_rub",
          "cost_kopecks",
          "requests"
        ]
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "usage"
            ]
          },
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time",
                "description": "Начало периода (UTC, ISO 8601). Включительно.",
                "example": "2026-05-13T00:00:00.000Z"
              },
              "to": {
                "type": "string",
                "format": "date-time",
                "description": "Конец периода (UTC, ISO 8601). Включительно.",
                "example": "2026-05-14T00:00:00.000Z"
              },
              "shortcut": {
                "$ref": "#/components/schemas/UsagePeriod"
              }
            },
            "required": [
              "from",
              "to",
              "shortcut"
            ]
          },
          "scope": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "key_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "key_prefix": {
                    "type": "string",
                    "example": "sk-gw-a1b2...c3d4"
                  }
                },
                "required": [
                  "key_id",
                  "key_prefix"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "account": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "key_id": {
                    "type": "string",
                    "nullable": true,
                    "format": "uuid"
                  }
                },
                "required": [
                  "account",
                  "key_id"
                ]
              }
            ],
            "description": "Обычный ключ: расход только по нему. OAuth-токен: расход всего подключения приложения, `key_id` — текущий токен. Management-ключ: весь аккаунт (`account: true`), опционально суженный параметром `key_id`."
          },
          "totals": {
            "type": "object",
            "properties": {
              "requests": {
                "type": "integer",
                "minimum": 0,
                "example": 137
              },
              "prompt_tokens": {
                "type": "integer",
                "minimum": 0,
                "example": 18420
              },
              "completion_tokens": {
                "type": "integer",
                "minimum": 0,
                "example": 9610
              },
              "total_tokens": {
                "type": "integer",
                "minimum": 0,
                "example": 28030
              },
              "cost_rub": {
                "type": "number",
                "description": "Итоговая стоимость за период в рублях. Эквивалент cost_kopecks/100.",
                "example": 42.17
              },
              "cost_kopecks": {
                "type": "string",
                "description": "Итоговая стоимость в копейках (строка для точности при сериализации bigint).",
                "example": "4217"
              },
              "cache_read_tokens": {
                "type": "integer"
              },
              "cache_write_tokens": {
                "type": "integer"
              },
              "reasoning_tokens": {
                "type": "integer"
              },
              "cache_hit_rate": {
                "type": "number"
              },
              "cache_savings_kopecks": {
                "type": "string"
              },
              "cache_savings_rub": {
                "type": "number"
              }
            },
            "required": [
              "requests",
              "prompt_tokens",
              "completion_tokens",
              "total_tokens",
              "cost_rub",
              "cost_kopecks",
              "cache_read_tokens",
              "cache_write_tokens",
              "reasoning_tokens",
              "cache_hit_rate",
              "cache_savings_kopecks",
              "cache_savings_rub"
            ]
          },
          "granularity": {
            "$ref": "#/components/schemas/UsageGranularity"
          },
          "buckets": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/UsageBucket"
            },
            "description": "Точки графика. Null, если `granularity` не запрошен."
          },
          "by_key": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": {
                "key_id": {
                  "type": "string",
                  "nullable": true,
                  "format": "uuid"
                },
                "key_prefix": {
                  "type": "string",
                  "nullable": true
                },
                "name": {
                  "type": "string",
                  "nullable": true
                },
                "requests": {
                  "type": "integer",
                  "minimum": 0
                },
                "total_tokens": {
                  "type": "integer",
                  "minimum": 0
                },
                "cost_kopecks": {
                  "type": "string",
                  "description": "Копейки строкой — как в totals.",
                  "example": "1234"
                }
              },
              "required": [
                "key_id",
                "key_prefix",
                "name",
                "requests",
                "total_tokens",
                "cost_kopecks"
              ]
            },
            "description": "Разбивка по ключам аккаунта (`group_by=key`, только management-ключом). Иначе отсутствует."
          },
          "by_model": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": {
                "model": {
                  "type": "string"
                },
                "requests": {
                  "type": "integer",
                  "minimum": 0
                },
                "prompt_tokens": {
                  "type": "integer",
                  "minimum": 0
                },
                "completion_tokens": {
                  "type": "integer",
                  "minimum": 0
                },
                "cost_kopecks": {
                  "type": "string",
                  "description": "Копейки строкой — как в totals.",
                  "example": "1234"
                }
              },
              "required": [
                "model",
                "requests",
                "prompt_tokens",
                "completion_tokens",
                "cost_kopecks"
              ]
            },
            "description": "Разбивка по моделям (`group_by=model`, только management-ключом). Иначе отсутствует."
          }
        },
        "required": [
          "object",
          "period",
          "scope",
          "totals",
          "granularity",
          "buckets"
        ]
      },
      "UsageErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorObject"
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/v1/audio/transcriptions": {
      "post": {
        "operationId": "createTranscription",
        "tags": [
          "Audio"
        ],
        "summary": "Распознать речь в аудио",
        "description": "OpenAI-совместимое распознавание речи: аудиозапись на входе, текст на выходе. Работает официальный SDK OpenAI (`audio.transcriptions.create`).\n\nДва формата тела с одинаковым результатом: `multipart/form-data` с файлом, как у OpenAI, или `application/json` с аудио в base64 (`input_audio`). Ссылки на аудио не принимаются.\n\nСтрима нет: `stream: true` — 400. `response_format` — только `json` или `verbose_json`.\n\nОплата по факту запроса: `usage.cost` — списано в копейках. Часть моделей тарифицируется по длительности записи, часть по токенам. Список моделей: `GET /v1/models?output_modalities=transcription`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TranscriptionMultipartRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscriptionJsonRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Распознанный текст.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело: нет `model`, `file` или `input_audio`, `stream: true`, неподдерживаемый `response_format`; ключ BYOK."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "402": {
            "description": "Недостаточно средств на балансе (`insufficient_balance`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Модель не найдена или это не модель распознавания (`model_not_found`)."
          },
          "413": {
            "description": "Тело запроса больше лимита (`request_too_large`)."
          },
          "429": {
            "description": "Исчерпан лимит расхода ключа (`daily_limit_exceeded`, `key_limit_exceeded`) или провайдер временно ограничил запросы. Пауза — в `Retry-After`."
          },
          "502": {
            "description": "Ошибка провайдера или не удалось определить стоимость (`pricing_unavailable`). Списания нет."
          },
          "503": {
            "description": "Курс ЦБ РФ временно недоступен (`exchange_rate_unavailable`)."
          },
          "504": {
            "description": "Таймаут распознавания (`upstream_timeout`)."
          }
        }
      }
    },
    "/v1/audio/speech": {
      "post": {
        "operationId": "createSpeech",
        "tags": [
          "Audio"
        ],
        "summary": "Озвучить текст",
        "description": "OpenAI-совместимая озвучка (TTS): текст на входе, байты аудио на выходе, а не JSON. Работает официальный SDK OpenAI (`audio.speech.create`).\n\nФормат — `response_format`: `mp3` (`audio/mpeg`) или `pcm` (`audio/pcm` с частотой и числом каналов в `Content-Type`, 16-bit LE без заголовка WAV). Без поля формат выбирает модель. Стрима нет.\n\n`voice` обязателен, если у модели в каталоге есть список голосов; голос не из списка отклоняется до обращения к модели.\n\nЦена — по единице модели в каталоге: символы или байты текста, секунды звука, токены. Списание по факту запроса; `usage` в ответе нет, расход — в журнале запросов. Перед запросом баланс сверяется с оценкой цены. Список моделей: `GET /v1/models?output_modalities=speech`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpeechRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Аудио целиком.",
            "headers": {
              "Content-Length": {
                "description": "Размер аудио в байтах.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/pcm": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело (`invalid_request`), не выбран голос (`voice_required`), голоса нет у модели (`voice_not_supported`); ключ BYOK. В тексте ошибки — доступные голоса."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "402": {
            "description": "Баланса не хватает на оценку цены запроса (`insufficient_balance`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Модель не найдена или это не модель озвучки (`model_not_found`)."
          },
          "413": {
            "description": "Тело запроса больше 1 МБ (`request_too_large`)."
          },
          "429": {
            "description": "Исчерпан лимит расхода ключа (`daily_limit_exceeded`, `key_limit_exceeded`) или провайдер временно ограничил запросы. Пауза — в `Retry-After`."
          },
          "502": {
            "description": "Нечем посчитать цену (`pricing_unavailable`), модель вернула пустой ответ (`no_audio_returned`), не удалось перекодировать в mp3 (`transcode_failed`) или ошибка провайдера. Списания нет."
          },
          "503": {
            "description": "Курс ЦБ РФ временно недоступен (`exchange_rate_unavailable`)."
          },
          "504": {
            "description": "Таймаут озвучки (`upstream_timeout`)."
          }
        }
      }
    },
    "/v1/videos": {
      "post": {
        "operationId": "createVideo",
        "tags": [
          "Videos"
        ],
        "summary": "Создать задачу генерации видео",
        "description": "Асинхронная генерация: ответ 202 сразу приносит номер задачи и `polling_url`. Статус — `GET /v1/videos/{id}`, готовый ролик — `GET /v1/videos/{id}/content`.\n\nПеред запуском с баланса удерживается не меньше наибольшей возможной стоимости ролика. После готовности списывается факт (`usage.cost`), разница возвращается; при сбое удержание возвращается целиком. Готовый ролик хранится 72 часа.\n\nНужен обычный ключ: ключ только для чтения задачу не создаст. Модели, их оси и цены — `GET /v1/videos/models`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "videos:write"
            ]
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Повтор с тем же ключом от того же аккаунта вернёт уже созданную задачу без нового удержания. Ключ длиннее 255 знаков не учитывается."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVideoRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Задача создана (или найдена по `Idempotency-Key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJobCreated"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело (`invalid_request`): ось, которой нет у модели, `callback_url`, неподходящие `input_references` или `provider.options`; ключ BYOK. Отказ модели принять вход приходит с её текстом."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "402": {
            "description": "Не хватает средств на удержание под задачу (`insufficient_balance`)."
          },
          "403": {
            "description": "Нет права создавать задачи: ключ только для чтения (`key_read_only`). OAuth-токен без права `videos:write` (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Модель не найдена или это не видеомодель (`model_not_found`)."
          },
          "413": {
            "description": "Тело запроса больше лимита (`request_too_large`)."
          },
          "429": {
            "description": "Достигнут лимит одновременных видеозадач аккаунта или уже готовится другой исходник (`too_many_active_jobs`); удержание не помещается в остаток лимита расхода ключа или OAuth-приложения (`daily_limit_exceeded`, `key_limit_exceeded`)."
          },
          "500": {
            "description": "Внутренняя ошибка (`internal_error`)."
          },
          "502": {
            "description": "Провайдер не принял задачу (`upstream_error`). Удержание возвращается."
          },
          "503": {
            "description": "Курс ЦБ РФ временно недоступен — не посчитать удержание (`exchange_rate_unavailable`)."
          },
          "504": {
            "description": "Провайдер не ответил вовремя (`upstream_error`). Удержание возвращается."
          }
        }
      }
    },
    "/v1/videos/{id}": {
      "get": {
        "operationId": "getVideo",
        "tags": [
          "Videos"
        ],
        "summary": "Статус задачи генерации видео",
        "description": "Статус: `pending`, `in_progress`, `completed` или `failed`. При `completed` — `unsigned_urls` (адрес скачивания, нужен тот же ключ или токен) и `usage.cost`, итоговое списание в копейках; пока задача в работе — `usage.estimated_cost`, удержанная сумма.\n\nСтатус у провайдера запрашивается не чаще раза в 5 секунд на задачу, опрашивать чаще смысла нет. Подходит и ключ только для чтения.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "videos:read"
            ]
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Номер задачи из ответа `POST /v1/videos`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Задача.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJob"
                }
              }
            }
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "OAuth-токен без права `videos:read` (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Задачи нет или она принадлежит другому аккаунту (`not_found`)."
          }
        }
      }
    },
    "/v1/videos/{id}/content": {
      "get": {
        "operationId": "getVideoContent",
        "tags": [
          "Videos"
        ],
        "summary": "Скачать готовое видео",
        "description": "Байты готового ролика для задачи в статусе `completed` — только владельцу, тем же ключом или OAuth-токеном. Тип — сохранённый `video/*` (обычно `video/mp4`), иначе `application/octet-stream`; `Content-Disposition: attachment`. Range-запросы не поддерживаются.\n\nРолик хранится 72 часа с создания задачи. До готовности и после срока хранения — одинаково 404 `video_not_ready`. Подходит и ключ только для чтения.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "videos:read"
            ]
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Номер задачи из ответа `POST /v1/videos`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 0,
              "default": 0,
              "description": "Номер ролика задачи. В v1 у задачи один ролик — `0`; больше нуля — 400 `index_out_of_range`."
            },
            "required": false,
            "name": "index",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Ролик целиком.",
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный `index` (`invalid_request`) или больше нуля (`index_out_of_range`)."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "OAuth-токен без права `videos:read` (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Задачи нет или она чужая (`not_found`); ролик ещё не готов или срок хранения истёк (`video_not_ready`)."
          }
        }
      }
    },
    "/v1/video/transcriptions": {
      "post": {
        "operationId": "createVideoTranscription",
        "tags": [
          "Videos"
        ],
        "summary": "Расшифровать ролик YouTube по ссылке",
        "description": "Дословная расшифровка с таймкодами (`exact`) или пересказ (`fast`) публичного ролика YouTube. Ролик по ссылке смотрит модель `google/gemini-3.8-flash`, скачивать видео не нужно. Не путать с `/v1/videos` — там генерация.\n\nДо запроса к модели ролик проверяется: удалённый, приватный, открытый только по ссылке, прямой эфир и ролик длиннее 4 часов отклоняются без списания.\n\nОплата по токенам, как у запроса к модели: `usage.cost` — сумма в копейках. Если ответ в режиме `exact` упирается в лимит длины, Hubris сам запрашивает продолжение и склеивает куски — до 5 запросов к модели (`usage.requests`). Стрима нет, ответ приходит целиком.\n\nОшибки самого запроса к модели (402, 429, 5xx) приходят в том же виде, что у `/v1/chat/completions`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoTranscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Расшифровка или пересказ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoTranscription"
                }
              }
            }
          },
          "400": {
            "description": "Невалидный JSON (`invalid_json`) или параметр (`invalid_parameter`), ссылка не на ролик YouTube (`invalid_video_url`), прямой эфир или премьера (`video_is_live`), ролик длиннее 4 часов (`video_too_long`)."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "402": {
            "description": "Недостаточно средств на балансе (`insufficient_balance`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Ролик удалён, приватный или открыт только по ссылке (`video_unavailable`)."
          },
          "413": {
            "description": "Тело запроса больше 64 КБ (`request_too_large`)."
          },
          "429": {
            "description": "Исчерпан лимит расхода ключа (`daily_limit_exceeded`, `key_limit_exceeded`) или провайдер временно ограничил запросы. Пауза — в `Retry-After`."
          },
          "502": {
            "description": "Сбой модели (`upstream_error`)."
          },
          "503": {
            "description": "Проверка ролика временно недоступна (`video_lookup_unavailable`) или курс ЦБ РФ недоступен."
          }
        }
      }
    },
    "/v1/metrics": {
      "get": {
        "operationId": "getMetrics",
        "tags": [
          "Metrics"
        ],
        "summary": "Метрики аккаунта для Prometheus",
        "description": "Баланс, расход, число запросов, токены, время ответа и лимиты ключей аккаунта в текстовом формате Prometheus 0.0.4. Его читают Prometheus, Grafana Agent, VictoriaMetrics и Zabbix.\n\nПодходит любой обычный ключ, в том числе только для чтения — его и стоит класть в конфиг мониторинга. Management-ключ не подходит.\n\nЗначения обновляются раз в 45 секунд; не больше 30 запросов в минуту на аккаунт.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Метрики, `Content-Type: text/plain; version=0.0.4; charset=utf-8`.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "# HELP hubris_balance_kopecks Остаток на балансе аккаунта, копейки.\n# TYPE hubris_balance_kopecks gauge\nhubris_balance_kopecks 128400\n"
                }
              }
            }
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "Отказ в доступе: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "429": {
            "description": "Больше 30 запросов в минуту (`rate_limit_exceeded`).",
            "headers": {
              "Retry-After": {
                "description": "Секунды до повтора.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/bitrix24/connectors": {
      "post": {
        "operationId": "createBitrix24Connector",
        "tags": [
          "Integrations"
        ],
        "summary": "Создать коннектор Битрикс24",
        "description": "Коннектор подключает модель Hubris к CoPilot (BitrixGPT) портала Битрикс24 как собственный движок. Под коннектор выпускается отдельный API-ключ «Битрикс24 · <имя>»: расход по нему виден отдельно, отзыв ключа выключает коннектор.\n\n`completions_url` из ответа передайте порталу в `ai.engine.register`. Адрес содержит секрет и показывается один раз.\n\nМодель закрепляется за коннектором; нужна другая — создайте второй коннектор. Сам вызов ничего не списывает, но требует права тратить: выпущенный ключ тратит баланс аккаунта.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Bitrix24ConnectorCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Коннектор создан.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bitrix24ConnectorCreated"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело. Ответ — результат проверки схемы (`success: false`, `error.issues`), а не `{ error: { message, type, code } }`."
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Модель не найдена (`model_not_found`)."
          },
          "429": {
            "description": "Исчерпан лимит расхода ключа, которым сделан запрос (`daily_limit_exceeded`, `key_limit_exceeded`)."
          },
          "503": {
            "description": "Коннекторы временно недоступны (`bitrix24_unavailable`)."
          }
        }
      },
      "get": {
        "operationId": "listBitrix24Connectors",
        "tags": [
          "Integrations"
        ],
        "summary": "Список коннекторов Битрикс24",
        "description": "Действующие коннекторы аккаунта, новые первыми: имя, модель, префикс выпущенного ключа, время создания и последнего использования. `completions_url` не возвращается — он показывается только при создании.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Коннекторы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bitrix24ConnectorList"
                }
              }
            }
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          }
        }
      }
    },
    "/v1/integrations/bitrix24/connectors/{id}": {
      "delete": {
        "operationId": "deleteBitrix24Connector",
        "tags": [
          "Integrations"
        ],
        "summary": "Удалить коннектор Битрикс24",
        "description": "Удаляет коннектор и отзывает выпущенный им ключ. Движок в портале уберите сами (`ai.engine.unregister`), иначе CoPilot продолжит слать запросы на несуществующий адрес.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "ID коннектора из ответа создания или списка."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Коннектор удалён.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bitrix24ConnectorDeleted"
                }
              }
            }
          },
          "401": {
            "description": "Ключ не передан, невалиден, отозван или заморожен (`invalid_api_key`, `key_frozen_spike`)."
          },
          "403": {
            "description": "Нет права `chat:write`: ключ только для чтения (`key_read_only`) или OAuth-токен без него (`insufficient_scope`). Ещё причины: management-ключ (`inference_key_required`), запрос не с адреса, к которому привязан ключ (`key_ip_not_allowed`), или заблокированный аккаунт (`account_blocked`)."
          },
          "404": {
            "description": "Коннектора нет, он чужой или уже удалён (`not_found`)."
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "listModels",
        "tags": [
          "Models"
        ],
        "summary": "Список доступных моделей",
        "description": "Возвращает активные модели с ценами в рублях за 1М токенов.\n\nБез параметра — только модели, которые отвечают текстом (в том числе с картинкой или голосом в ответе). Остальные категории — по фильтру `?output_modalities=`: `embeddings`, `image`, `video`, `speech`, `transcription`, `decisions`, `rerank`; весь каталог — `?output_modalities=all`.\n\nЕдиницу тарификации даёт `pricing.unit`: `token` — цены за 1М токенов, `unit` — оплата в других единицах (реальная цена в `pricing.per_unit`, токенные поля нулевые), `unknown` — тариф не публикуется, списывается фактическая стоимость. Не умножайте `input_rub_per_million` на токены, не проверив `unit`.\n\nКлюч необязателен: без него отдаётся публичный каталог, с ключом — тот же каталог плюс ваши цепочки резервных моделей `route/<slug>`.\n\nБесплатные модели помечены флагом `pricing.is_free`. Не определяйте бесплатность по `input_rub_per_million === 0`: у моделей с оплатой в других единицах (за изображение, за секунду видео) цена за токены нулевая, а запрос платный. У бесплатных есть лимиты на стороне провайдера модели, которые провайдер не публикует, поэтому в пиковые часы возможны ответы 429. Подробности: /docs/concepts/free-models.",
        "security": [
          {},
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "models:read"
            ]
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 100,
              "description": "Фильтр по выходной модальности (CSV). Без параметра — `text`; `all` — весь каталог.",
              "example": "decisions"
            },
            "required": false,
            "name": "output_modalities",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OpenAI-совместимый список моделей.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelsList"
                }
              }
            }
          },
          "401": {
            "description": "Передан невалидный API-ключ (без ключа каталог отдаётся публично).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelsErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelsErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Не удалось получить курс ЦБ РФ — каталог временно недоступен.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/videos/models": {
      "get": {
        "operationId": "listVideoModels",
        "tags": [
          "Videos"
        ],
        "summary": "Каталог видео-моделей",
        "description": "Активные видео-модели с ценами в рублях за единицу (секунда/видео).\nАпстрим-цены в USD и внутренние SKU не раскрываются.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Список видео-моделей.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoModelsList"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный или отсутствующий API-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoModelsErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Не удалось получить курс ЦБ РФ — каталог временно недоступен.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoModelsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "tags": [
          "Chat"
        ],
        "summary": "Создать chat completion",
        "description": "OpenAI-совместимый chat completions endpoint.\n\nПри `stream: true` возвращает Server-Sent Events стрим из chunk-ов в формате `chat.completion.chunk`.\nПодробности SSE-формата — на странице [Streaming](/docs/api/streaming).\n\nHubris автоматически добавляет `stream_options: { include_usage: true }` ко всем stream-запросам, поэтому usage приходит в последнем chunk-е перед `[DONE]`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешный ответ. При `stream: false` — `chat.completion`. При `stream: true` — `text/event-stream` с chunk-ами `chat.completion.chunk`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE-stream chunk-ов. См. /docs/api/streaming."
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный API-ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно средств на балансе",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Модель не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Ошибка апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Курс ЦБ РФ временно недоступен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Таймаут апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/images/generations": {
      "post": {
        "operationId": "createImage",
        "tags": [
          "Images"
        ],
        "summary": "Сгенерировать изображение",
        "description": "OpenAI Images API-совместимая генерация картинок по текстовому описанию. Картинки приходят в base64 (`b64_json`).\n\nМодели с генерацией изображений: `GET /v1/models?output_modalities=image`. Провайдер-специфичные поля (`aspect_ratio`, `resolution`, `seed`, `input_references`) передаются как есть. Списание — по итоговой стоимости картинок.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImageGenerationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Сгенерированные изображения: `{ created, data: [{ b64_json }] }`"
          },
          "400": {
            "description": "Невалидный запрос"
          },
          "402": {
            "description": "Недостаточно средств"
          },
          "404": {
            "description": "Модель не найдена"
          },
          "502": {
            "description": "Ошибка апстрима / не удалось определить стоимость"
          },
          "503": {
            "description": "Курс валют недоступен"
          }
        }
      }
    },
    "/v1/responses": {
      "post": {
        "operationId": "createResponse",
        "tags": [
          "Responses"
        ],
        "summary": "Создать response (beta)",
        "description": "OpenAI-совместимый Responses API endpoint. **BETA** — schema нестабильна, поля могут меняться.\n\nПри `stream: true` возвращает Server-Sent Events стрим. Usage приходит в `response.completed` event.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResponsesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешный ответ. При `stream: false` — JSON. При `stream: true` — `text/event-stream`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE-stream events (см. /docs/api/responses, beta)."
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный API-ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно средств",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Модель не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Ошибка апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Курс ЦБ РФ недоступен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Таймаут апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponsesErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "post": {
        "operationId": "createMessage",
        "tags": [
          "Messages"
        ],
        "summary": "Создать сообщение (Anthropic Messages API)",
        "description": "Anthropic-совместимый endpoint. Принимает как Anthropic-имена моделей\n(`claude-sonnet-4-5`, `claude-3-5-sonnet-20241022`, `claude-haiku-4-5-latest`),\nтак и каноничные (`anthropic/claude-sonnet-4.6`). Поддерживает Bearer и\nx-api-key заголовки. Используется Claude Code и любыми Anthropic SDK\nчерез `ANTHROPIC_BASE_URL=https://api.hubris.pw`.\n\nПри `stream: true` — Server-Sent Events в нативном Anthropic-формате\n(`message_start` / `content_block_*` / `message_delta` / `message_stop`).\n\nPrivacy Mode на этом эндпоинте не поддерживается. Для маскирования PII\nиспользуйте `/v1/chat/completions`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnthropicMessagesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешный ответ. При `stream: false` — JSON. При `stream: true` — `text/event-stream`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Anthropic SSE-stream events (см. /docs/api/messages)."
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный API-ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно средств",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "404": {
            "description": "Модель не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "502": {
            "description": "Ошибка апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "503": {
            "description": "Курс ЦБ РФ недоступен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          },
          "504": {
            "description": "Таймаут апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicMessagesError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/embeddings": {
      "post": {
        "operationId": "createEmbedding",
        "tags": [
          "Embeddings"
        ],
        "summary": "Создать эмбеддинги",
        "description": "OpenAI-совместимый embeddings endpoint. Превращает текст в вектор фиксированной длины — для семантического поиска, RAG, классификации.\n\nПринимает строку, массив строк (батч до 2048), массив токен-ID или массив массивов токен-ID. Биллинг — только по `prompt_tokens` (output всегда 0).\n\nСтрима нет. Полный список embedding-моделей: `GET /v1/models` с фильтром `output_modalities=embeddings`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmbeddingsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешный ответ — список эмбеддингов в порядке `input`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный API-ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно средств на балансе",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Модель не найдена или не поддерживает embeddings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Ошибка апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Курс ЦБ РФ временно недоступен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Таймаут апстрима",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/decisions": {
      "post": {
        "operationId": "createDecision",
        "tags": [
          "Decisions"
        ],
        "summary": "Задать вопросы модели решений",
        "description": "Модели решений (например, `typesafe/jev-1.13`) не пишут текст. Вы передаёте данные (`state`) и вопросы (`questions`), модель возвращает ответы с вероятностями.\n\nТипы вопросов: `noul` — да или нет, `choice` — вариант из списка, `score` — уровень на шкале. Все вопросы решаются за один запрос.\n\nПлатится только вход (`usage.input_tokens`), выход бесплатный. `usage.cost` — списано в копейках. Стрима нет.\n\nСписок моделей: `GET /v1/models`, фильтр по `output_modalities`, содержащему `decisions`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DecisionsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ответы на все вопросы.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecisionsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса"
          },
          "401": {
            "description": "Невалидный API-ключ"
          },
          "402": {
            "description": "Недостаточно средств на балансе"
          },
          "404": {
            "description": "Модель не найдена или это не модель решений"
          },
          "429": {
            "description": "Превышен лимит запросов"
          },
          "502": {
            "description": "Ошибка апстрима"
          },
          "503": {
            "description": "Курс валют временно недоступен"
          },
          "504": {
            "description": "Таймаут апстрима"
          }
        }
      }
    },
    "/v1/rerank": {
      "post": {
        "operationId": "createRerank",
        "tags": [
          "Rerank"
        ],
        "summary": "Отсортировать документы по запросу",
        "description": "Реранкер (например, `cohere/rerank-v3.5`) сортирует документы по тому, насколько они отвечают на запрос: `results` — номера документов во входном списке и оценка `relevance_score`, лучшие первыми.\n\nОплата у Cohere — за поиск (`usage.search_units`), у остальных — за токены входа. `usage.cost` — списано в копейках. Стрима нет.\n\nСписок моделей: `GET /v1/models?output_modalities=rerank`.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "chat:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RerankRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Документы, отсортированные по близости к запросу.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RerankResponse"
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса"
          },
          "401": {
            "description": "Невалидный API-ключ"
          },
          "402": {
            "description": "Недостаточно средств на балансе"
          },
          "404": {
            "description": "Модель не найдена или это не реранкер"
          },
          "429": {
            "description": "Превышен лимит запросов"
          },
          "502": {
            "description": "Ошибка апстрима"
          },
          "503": {
            "description": "Курс валют временно недоступен"
          },
          "504": {
            "description": "Таймаут апстрима"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Usage"
        ],
        "summary": "Расход по API-ключу за период",
        "description": "Возвращает итоговые расходы (рубли + копейки + токены + количество запросов) по тому API-ключу, которым сделан запрос; OAuth-токену — по всему подключению приложения (токен меняется каждый час, сумма — по всем токенам подключения). По умолчанию — последние 24 часа. Можно передать шорткат `?period=` либо явные `?from=&to=` (ISO 8601, UTC). Опциональный `?granularity=` добавит массив `buckets` для построения графика.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "mtd"
              ],
              "description": "Шорткат периода. `today` = с 00:00 UTC текущих суток. `24h` = последние 24ч. `7d`/`30d` = последние N суток. `mtd` = с 1-го числа текущего месяца UTC. Несовместим с `from`/`to`."
            },
            "required": false,
            "name": "period",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Начало периода, ISO 8601. Если задан — `to` тоже обязателен."
            },
            "required": false,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Конец периода, ISO 8601. Если задан — `from` тоже обязателен."
            },
            "required": false,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day"
              ],
              "description": "Если указан — в ответе появится массив `buckets` с агрегатами по этому шагу."
            },
            "required": false,
            "name": "granularity",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Только management-ключом: сузить аккаунт-скоуп до одного API-ключа."
            },
            "required": false,
            "name": "key_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "key",
                "model"
              ],
              "description": "Только management-ключом: добавить разбивку `by_key` или `by_model`."
            },
            "required": false,
            "name": "group_by",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Расход по ключу за указанный период.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Невалидные параметры периода (range_invalid / range_too_long / period_invalid).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Невалидный или отсутствующий API-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Превышен дневной лимит ключа.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys": {
      "get": {
        "operationId": "listApiKeys",
        "tags": [
          "Management"
        ],
        "summary": "Список API-ключей аккаунта",
        "description": "Возвращает активные inference-ключи аккаунта. Требует management-ключ (sk-gw-mgmt-...). Полные ключи не возвращаются — только маскированные префиксы.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Страница ключей.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "list"
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "key_prefix": {
                            "type": "string",
                            "example": "sk-gw-ab12...cd34"
                          },
                          "disabled": {
                            "type": "boolean"
                          },
                          "limit_kopecks": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Лимит расхода ключа в копейках за период `limit_period`. null = без лимита."
                          },
                          "limit_period": {
                            "type": "string",
                            "enum": [
                              "day",
                              "week",
                              "month",
                              "none"
                            ],
                            "description": "Период сброса лимита: day — календарные сутки (00:00 МСК), week — с понедельника, month — с 1-го числа, none — без сброса (лимит на весь расход ключа)."
                          },
                          "spent_period_kopecks": {
                            "type": "integer",
                            "description": "Потрачено этим ключом в текущем периоде, в копейках."
                          },
                          "limit_remaining_kopecks": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Сколько ещё можно потратить в текущем периоде: лимит минус траты минус резервы роликов в работе, не меньше 0. null — без лимита."
                          },
                          "period_reset_at": {
                            "type": "string",
                            "nullable": true,
                            "description": "Момент следующего сброса (ISO 8601); null для limit_period=none."
                          },
                          "daily_limit_kopecks": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Устаревшее. Равно limit_kopecks при limit_period=day, иначе null. Используйте limit_kopecks."
                          },
                          "spent_24h_kopecks": {
                            "type": "integer",
                            "description": "Устаревшее. Равно spent_period_kopecks. Используйте spent_period_kopecks."
                          },
                          "read_only": {
                            "type": "boolean",
                            "description": "Ключ только для чтения: каталог моделей, баланс и статистика доступны, запросы к моделям (всё, что тратит баланс) — 403 key_read_only."
                          },
                          "allowed_ips": {
                            "type": "array",
                            "nullable": true,
                            "items": {
                              "type": "string"
                            },
                            "description": "Привязка к адресу: IPv4/IPv6-адреса и подсети (CIDR), с которых ключ принимает запросы; null — с любого адреса. Запрос с другого адреса — 403 key_ip_not_allowed.",
                            "example": [
                              "203.0.113.5",
                              "198.51.100.0/24"
                            ]
                          },
                          "disabled_reason": {
                            "type": "string",
                            "nullable": true,
                            "enum": [
                              "manual",
                              "spike"
                            ],
                            "description": "Почему ключ отключён: manual — вручную, spike — заморозка при всплеске трат; null — включён."
                          },
                          "disabled_until": {
                            "type": "string",
                            "nullable": true,
                            "description": "Момент автоматического включения после заморозки (ISO 8601); null — до ручного включения или ключ включён."
                          },
                          "spike_limit_kopecks": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Защита от всплеска: порог расхода в копейках за окно spike_window_minutes; null — выключена."
                          },
                          "spike_window_minutes": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Окно защиты от всплеска: 1, 5, 15, 30 или 60 минут."
                          },
                          "spike_cooldown_minutes": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Период охлаждения: через сколько минут ключ включится снова (15, 60, 360, 1440); null — до ручного включения."
                          },
                          "privacy_mask_default": {
                            "type": "string",
                            "enum": [
                              "inherit",
                              "off",
                              "on",
                              "required"
                            ]
                          },
                          "last_used_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "key_prefix",
                          "disabled",
                          "limit_kopecks",
                          "limit_period",
                          "spent_period_kopecks",
                          "limit_remaining_kopecks",
                          "period_reset_at",
                          "daily_limit_kopecks",
                          "spent_24h_kopecks",
                          "read_only",
                          "allowed_ips",
                          "disabled_reason",
                          "disabled_until",
                          "spike_limit_kopecks",
                          "spike_window_minutes",
                          "spike_cooldown_minutes",
                          "privacy_mask_default",
                          "last_used_at",
                          "created_at"
                        ]
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit (60/мин).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "tags": [
          "Management"
        ],
        "summary": "Создать API-ключ",
        "description": "Создаёт новый inference-ключ. Полный ключ возвращается один раз в поле `key` — сохраните его сразу, повторно получить его нельзя. Лимиты: 30 созданий в час, не более 500 активных ключей на аккаунт.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "limit_kopecks": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 10000000000
                  },
                  "limit_period": {
                    "type": "string",
                    "enum": [
                      "day",
                      "week",
                      "month",
                      "none"
                    ],
                    "description": "Период сброса лимита: day (по умолчанию), week, month, none — без сброса."
                  },
                  "daily_limit_kopecks": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 10000000000
                  },
                  "read_only": {
                    "type": "boolean",
                    "description": "Ключ только для чтения — без запросов к моделям. По умолчанию false."
                  },
                  "allowed_ips": {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    },
                    "maxItems": 100,
                    "description": "Привязка к адресу: до 32 записей — IPv4/IPv6-адрес или подсеть (CIDR). null или [] — снять привязку (любой адрес).",
                    "example": [
                      "203.0.113.5",
                      "198.51.100.0/24"
                    ]
                  },
                  "privacy_mask_default": {
                    "type": "string",
                    "enum": [
                      "inherit",
                      "off",
                      "on",
                      "required"
                    ]
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Ключ создан. Поле `key` — полный ключ, показывается один раз.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "key_prefix": {
                      "type": "string",
                      "example": "sk-gw-ab12...cd34"
                    },
                    "disabled": {
                      "type": "boolean"
                    },
                    "limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Лимит расхода ключа в копейках за период `limit_period`. null = без лимита."
                    },
                    "limit_period": {
                      "type": "string",
                      "enum": [
                        "day",
                        "week",
                        "month",
                        "none"
                      ],
                      "description": "Период сброса лимита: day — календарные сутки (00:00 МСК), week — с понедельника, month — с 1-го числа, none — без сброса (лимит на весь расход ключа)."
                    },
                    "spent_period_kopecks": {
                      "type": "integer",
                      "description": "Потрачено этим ключом в текущем периоде, в копейках."
                    },
                    "limit_remaining_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Сколько ещё можно потратить в текущем периоде: лимит минус траты минус резервы роликов в работе, не меньше 0. null — без лимита."
                    },
                    "period_reset_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент следующего сброса (ISO 8601); null для limit_period=none."
                    },
                    "daily_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Устаревшее. Равно limit_kopecks при limit_period=day, иначе null. Используйте limit_kopecks."
                    },
                    "spent_24h_kopecks": {
                      "type": "integer",
                      "description": "Устаревшее. Равно spent_period_kopecks. Используйте spent_period_kopecks."
                    },
                    "read_only": {
                      "type": "boolean",
                      "description": "Ключ только для чтения: каталог моделей, баланс и статистика доступны, запросы к моделям (всё, что тратит баланс) — 403 key_read_only."
                    },
                    "allowed_ips": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "string"
                      },
                      "description": "Привязка к адресу: IPv4/IPv6-адреса и подсети (CIDR), с которых ключ принимает запросы; null — с любого адреса. Запрос с другого адреса — 403 key_ip_not_allowed.",
                      "example": [
                        "203.0.113.5",
                        "198.51.100.0/24"
                      ]
                    },
                    "disabled_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "manual",
                        "spike"
                      ],
                      "description": "Почему ключ отключён: manual — вручную, spike — заморозка при всплеске трат; null — включён."
                    },
                    "disabled_until": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент автоматического включения после заморозки (ISO 8601); null — до ручного включения или ключ включён."
                    },
                    "spike_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Защита от всплеска: порог расхода в копейках за окно spike_window_minutes; null — выключена."
                    },
                    "spike_window_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Окно защиты от всплеска: 1, 5, 15, 30 или 60 минут."
                    },
                    "spike_cooldown_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Период охлаждения: через сколько минут ключ включится снова (15, 60, 360, 1440); null — до ручного включения."
                    },
                    "privacy_mask_default": {
                      "type": "string",
                      "enum": [
                        "inherit",
                        "off",
                        "on",
                        "required"
                      ]
                    },
                    "last_used_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "key": {
                      "type": "string",
                      "description": "Полный API-ключ. Показывается ТОЛЬКО в этом ответе — сохраните его сразу.",
                      "example": "sk-gw-…"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "key_prefix",
                    "disabled",
                    "limit_kopecks",
                    "limit_period",
                    "spent_period_kopecks",
                    "limit_remaining_kopecks",
                    "period_reset_at",
                    "daily_limit_kopecks",
                    "spent_24h_kopecks",
                    "read_only",
                    "allowed_ips",
                    "disabled_reason",
                    "disabled_until",
                    "spike_limit_kopecks",
                    "spike_window_minutes",
                    "spike_cooldown_minutes",
                    "privacy_mask_default",
                    "last_used_at",
                    "created_at",
                    "key"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Ключ не найден (гонка с параллельным отзывом).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен лимит созданий или потолок ключей.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys/{id}": {
      "get": {
        "operationId": "getApiKey",
        "tags": [
          "Management"
        ],
        "summary": "Один API-ключ",
        "description": "Ключ аккаунта по id: имя, префикс, лимит расхода и период его сброса, расход в текущем периоде, статус. Полный ключ не возвращается никогда — только при создании. Требует management-ключ (sk-gw-mgmt-...).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "key_prefix": {
                      "type": "string",
                      "example": "sk-gw-ab12...cd34"
                    },
                    "disabled": {
                      "type": "boolean"
                    },
                    "limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Лимит расхода ключа в копейках за период `limit_period`. null = без лимита."
                    },
                    "limit_period": {
                      "type": "string",
                      "enum": [
                        "day",
                        "week",
                        "month",
                        "none"
                      ],
                      "description": "Период сброса лимита: day — календарные сутки (00:00 МСК), week — с понедельника, month — с 1-го числа, none — без сброса (лимит на весь расход ключа)."
                    },
                    "spent_period_kopecks": {
                      "type": "integer",
                      "description": "Потрачено этим ключом в текущем периоде, в копейках."
                    },
                    "limit_remaining_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Сколько ещё можно потратить в текущем периоде: лимит минус траты минус резервы роликов в работе, не меньше 0. null — без лимита."
                    },
                    "period_reset_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент следующего сброса (ISO 8601); null для limit_period=none."
                    },
                    "daily_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Устаревшее. Равно limit_kopecks при limit_period=day, иначе null. Используйте limit_kopecks."
                    },
                    "spent_24h_kopecks": {
                      "type": "integer",
                      "description": "Устаревшее. Равно spent_period_kopecks. Используйте spent_period_kopecks."
                    },
                    "read_only": {
                      "type": "boolean",
                      "description": "Ключ только для чтения: каталог моделей, баланс и статистика доступны, запросы к моделям (всё, что тратит баланс) — 403 key_read_only."
                    },
                    "allowed_ips": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "string"
                      },
                      "description": "Привязка к адресу: IPv4/IPv6-адреса и подсети (CIDR), с которых ключ принимает запросы; null — с любого адреса. Запрос с другого адреса — 403 key_ip_not_allowed.",
                      "example": [
                        "203.0.113.5",
                        "198.51.100.0/24"
                      ]
                    },
                    "disabled_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "manual",
                        "spike"
                      ],
                      "description": "Почему ключ отключён: manual — вручную, spike — заморозка при всплеске трат; null — включён."
                    },
                    "disabled_until": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент автоматического включения после заморозки (ISO 8601); null — до ручного включения или ключ включён."
                    },
                    "spike_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Защита от всплеска: порог расхода в копейках за окно spike_window_minutes; null — выключена."
                    },
                    "spike_window_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Окно защиты от всплеска: 1, 5, 15, 30 или 60 минут."
                    },
                    "spike_cooldown_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Период охлаждения: через сколько минут ключ включится снова (15, 60, 360, 1440); null — до ручного включения."
                    },
                    "privacy_mask_default": {
                      "type": "string",
                      "enum": [
                        "inherit",
                        "off",
                        "on",
                        "required"
                      ]
                    },
                    "last_used_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "key_prefix",
                    "disabled",
                    "limit_kopecks",
                    "limit_period",
                    "spent_period_kopecks",
                    "limit_remaining_kopecks",
                    "period_reset_at",
                    "daily_limit_kopecks",
                    "spent_24h_kopecks",
                    "read_only",
                    "allowed_ips",
                    "disabled_reason",
                    "disabled_until",
                    "spike_limit_kopecks",
                    "spike_window_minutes",
                    "spike_cooldown_minutes",
                    "privacy_mask_default",
                    "last_used_at",
                    "created_at"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Ключ не найден.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateApiKey",
        "tags": [
          "Management"
        ],
        "summary": "Изменить API-ключ",
        "description": "Частичное обновление: имя, обратимое отключение (`disabled`), лимит расхода (`limit_kopecks`, null — снять) и период его сброса (`limit_period`), режим «только чтение», привязка к адресу (`allowed_ips`, null — снять), защита от всплеска, режим приватности. Устаревшее `daily_limit_kopecks` = лимит с периодом day.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "disabled": {
                    "type": "boolean"
                  },
                  "limit_kopecks": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 10000000000
                  },
                  "limit_period": {
                    "type": "string",
                    "enum": [
                      "day",
                      "week",
                      "month",
                      "none"
                    ],
                    "description": "Период сброса лимита: day (по умолчанию), week, month, none — без сброса."
                  },
                  "daily_limit_kopecks": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 10000000000
                  },
                  "read_only": {
                    "type": "boolean",
                    "description": "Переключить «только чтение»; обратимо."
                  },
                  "allowed_ips": {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    },
                    "maxItems": 100,
                    "description": "Привязка к адресу: до 32 записей — IPv4/IPv6-адрес или подсеть (CIDR). null или [] — снять привязку (любой адрес).",
                    "example": [
                      "203.0.113.5",
                      "198.51.100.0/24"
                    ]
                  },
                  "spike_limit_kopecks": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 100,
                    "maximum": 10000000,
                    "description": "Защита от всплеска: порог в копейках; null — выключить. Вместе с ним обязателен spike_window_minutes."
                  },
                  "spike_window_minutes": {
                    "type": "integer",
                    "description": "Окно защиты: 1, 5, 15, 30 или 60 минут."
                  },
                  "spike_cooldown_minutes": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Охлаждение: 15, 60, 360, 1440 минут или null — до ручного включения."
                  },
                  "privacy_mask_default": {
                    "type": "string",
                    "enum": [
                      "inherit",
                      "off",
                      "on",
                      "required"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Обновлённый ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "key_prefix": {
                      "type": "string",
                      "example": "sk-gw-ab12...cd34"
                    },
                    "disabled": {
                      "type": "boolean"
                    },
                    "limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Лимит расхода ключа в копейках за период `limit_period`. null = без лимита."
                    },
                    "limit_period": {
                      "type": "string",
                      "enum": [
                        "day",
                        "week",
                        "month",
                        "none"
                      ],
                      "description": "Период сброса лимита: day — календарные сутки (00:00 МСК), week — с понедельника, month — с 1-го числа, none — без сброса (лимит на весь расход ключа)."
                    },
                    "spent_period_kopecks": {
                      "type": "integer",
                      "description": "Потрачено этим ключом в текущем периоде, в копейках."
                    },
                    "limit_remaining_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Сколько ещё можно потратить в текущем периоде: лимит минус траты минус резервы роликов в работе, не меньше 0. null — без лимита."
                    },
                    "period_reset_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент следующего сброса (ISO 8601); null для limit_period=none."
                    },
                    "daily_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Устаревшее. Равно limit_kopecks при limit_period=day, иначе null. Используйте limit_kopecks."
                    },
                    "spent_24h_kopecks": {
                      "type": "integer",
                      "description": "Устаревшее. Равно spent_period_kopecks. Используйте spent_period_kopecks."
                    },
                    "read_only": {
                      "type": "boolean",
                      "description": "Ключ только для чтения: каталог моделей, баланс и статистика доступны, запросы к моделям (всё, что тратит баланс) — 403 key_read_only."
                    },
                    "allowed_ips": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "string"
                      },
                      "description": "Привязка к адресу: IPv4/IPv6-адреса и подсети (CIDR), с которых ключ принимает запросы; null — с любого адреса. Запрос с другого адреса — 403 key_ip_not_allowed.",
                      "example": [
                        "203.0.113.5",
                        "198.51.100.0/24"
                      ]
                    },
                    "disabled_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "manual",
                        "spike"
                      ],
                      "description": "Почему ключ отключён: manual — вручную, spike — заморозка при всплеске трат; null — включён."
                    },
                    "disabled_until": {
                      "type": "string",
                      "nullable": true,
                      "description": "Момент автоматического включения после заморозки (ISO 8601); null — до ручного включения или ключ включён."
                    },
                    "spike_limit_kopecks": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Защита от всплеска: порог расхода в копейках за окно spike_window_minutes; null — выключена."
                    },
                    "spike_window_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Окно защиты от всплеска: 1, 5, 15, 30 или 60 минут."
                    },
                    "spike_cooldown_minutes": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Период охлаждения: через сколько минут ключ включится снова (15, 60, 360, 1440); null — до ручного включения."
                    },
                    "privacy_mask_default": {
                      "type": "string",
                      "enum": [
                        "inherit",
                        "off",
                        "on",
                        "required"
                      ]
                    },
                    "last_used_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "key_prefix",
                    "disabled",
                    "limit_kopecks",
                    "limit_period",
                    "spent_period_kopecks",
                    "limit_remaining_kopecks",
                    "period_reset_at",
                    "daily_limit_kopecks",
                    "spent_24h_kopecks",
                    "read_only",
                    "allowed_ips",
                    "disabled_reason",
                    "disabled_until",
                    "spike_limit_kopecks",
                    "spike_window_minutes",
                    "spike_cooldown_minutes",
                    "privacy_mask_default",
                    "last_used_at",
                    "created_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Невалидное тело запроса.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Ключ не найден.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteApiKey",
        "tags": [
          "Management"
        ],
        "summary": "Отозвать API-ключ",
        "description": "Необратимый отзыв. Идемпотентно: повторный вызов по уже отозванному ключу тоже вернёт 200.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Ключ отозван.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "deleted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Ключ не найден.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/key": {
      "get": {
        "operationId": "getCurrentKey",
        "tags": [
          "Management"
        ],
        "summary": "Информация о текущем ключе",
        "description": "Самоинтроспекция ключа, которым сделан запрос: имя, лимит расхода и период его сброса, расход в текущем периоде, остаток лимита и баланс аккаунта. Работает с обычным API-ключом — management-ключ не нужен.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Данные текущего ключа.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "key_prefix": {
                          "type": "string",
                          "example": "sk-gw-ab12...cd34"
                        },
                        "key_type": {
                          "type": "string",
                          "enum": [
                            "inference",
                            "management"
                          ]
                        },
                        "disabled": {
                          "type": "boolean"
                        },
                        "limit_kopecks": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Лимит расхода ключа в копейках за период limit_period. null = без лимита."
                        },
                        "limit_period": {
                          "type": "string",
                          "enum": [
                            "day",
                            "week",
                            "month",
                            "none"
                          ]
                        },
                        "spent_period_kopecks": {
                          "type": "integer",
                          "description": "Потрачено ключом в текущем периоде, в копейках."
                        },
                        "limit_remaining_kopecks": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Сколько ещё можно потратить в текущем периоде: лимит минус траты минус резервы роликов в работе, не меньше 0. null — без лимита."
                        },
                        "period_reset_at": {
                          "type": "string",
                          "nullable": true,
                          "description": "Момент следующего сброса (ISO 8601); null для limit_period=none."
                        },
                        "daily_limit_kopecks": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Устаревшее: limit_kopecks при limit_period=day, иначе null."
                        },
                        "spent_24h_kopecks": {
                          "type": "integer",
                          "description": "Устаревшее: равно spent_period_kopecks."
                        },
                        "read_only": {
                          "type": "boolean",
                          "description": "Ключ только для чтения: запросы к моделям ему запрещены (403 key_read_only)."
                        },
                        "allowed_ips": {
                          "type": "array",
                          "nullable": true,
                          "items": {
                            "type": "string"
                          },
                          "description": "Привязка к адресу: адреса и подсети, с которых ключ принимает запросы; null — с любого."
                        },
                        "balance_kopecks": {
                          "type": "integer",
                          "description": "Текущий баланс аккаунта в копейках."
                        },
                        "created_at": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "name",
                        "key_prefix",
                        "key_type",
                        "disabled",
                        "limit_kopecks",
                        "limit_period",
                        "spent_period_kopecks",
                        "limit_remaining_kopecks",
                        "period_reset_at",
                        "daily_limit_kopecks",
                        "spent_24h_kopecks",
                        "read_only",
                        "allowed_ips",
                        "balance_kopecks",
                        "created_at"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "OAuth-токены не поддерживаются этим эндпоинтом.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/credits": {
      "get": {
        "operationId": "getCredits",
        "tags": [
          "Management"
        ],
        "summary": "Баланс аккаунта",
        "description": "Основной и бонусный балансы аккаунта в копейках. Требует management-ключ (sk-gw-mgmt-...).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Балансы аккаунта.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "balance_kopecks": {
                          "type": "integer",
                          "description": "Основной баланс в копейках."
                        },
                        "bonus_balance_kopecks": {
                          "type": "integer",
                          "description": "Доступный для списания бонусный баланс в копейках (невыводимые кредиты; реферальная часть может быть временно недоступна до первой оплаты аккаунта)."
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "RUB"
                          ]
                        }
                      },
                      "required": [
                        "balance_kopecks",
                        "bonus_balance_kopecks",
                        "currency"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit (60/мин).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/transactions": {
      "get": {
        "operationId": "listTransactions",
        "tags": [
          "Management"
        ],
        "summary": "История транзакций",
        "description": "Пополнения, списания, возвраты и бонусные операции аккаунта, свежие сверху. Требует management-ключ (sk-gw-mgmt-...).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "topup",
                "usage",
                "refund",
                "adjustment",
                "mcp_debit",
                "mcp_refund",
                "referral_bonus",
                "bonus_accrual",
                "bonus_spend",
                "bonus_expire",
                "bonus",
                "video_precharge",
                "video_reconcile"
              ]
            },
            "required": false,
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Начало периода, ISO 8601."
            },
            "required": false,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Конец периода, ISO 8601."
            },
            "required": false,
            "name": "to",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Страница транзакций.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "list"
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "topup",
                              "usage",
                              "refund",
                              "adjustment",
                              "mcp_debit",
                              "mcp_refund",
                              "referral_bonus",
                              "bonus_accrual",
                              "bonus_spend",
                              "bonus_expire",
                              "bonus",
                              "video_precharge",
                              "video_reconcile"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "succeeded",
                              "failed",
                              "cancelled"
                            ]
                          },
                          "amount_kopecks": {
                            "type": "integer",
                            "description": "Сумма операции в копейках: положительная — зачисление, отрицательная — списание."
                          },
                          "balance_after_kopecks": {
                            "type": "integer"
                          },
                          "payment_method": {
                            "type": "string",
                            "nullable": true,
                            "enum": [
                              "sbp",
                              "card",
                              "invoice"
                            ],
                            "description": "Способ пополнения; null для не-topup операций."
                          },
                          "created_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "status",
                          "amount_kopecks",
                          "balance_after_kopecks",
                          "payment_method",
                          "created_at"
                        ]
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Невалидные параметры.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Невалидный ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Нужен management-ключ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Превышен rate limit (60/мин).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "type",
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
