{
  "openapi": "3.1.0",
  "info": {
    "title": "Clipia API",
    "version": "v1",
    "summary": "Публичный HTTP API для генерации изображений и видео.",
    "description": "Публичный HTTP API Clipia для генерации изображений и видео.\n\nAPI работает **только в асинхронном режиме (очередь)**: `submit → status →\nresult` плюс вебхуки.\n\n## Поток работы\n\n1. **Submit** — `POST /v1/models/{model}` ставит генерацию в очередь и сразу\n   возвращает `request_id` вместе с готовыми ссылками (`status_url`,\n   `response_url`, `cancel_url`) и стоимостью операции в кредитах.\n2. **Status** — `GET /v1/requests/{request_id}/status` отдаёт текущий статус,\n   позицию в очереди и прогресс.\n3. **Result** — `GET /v1/requests/{request_id}` отдаёт результат (`200`) когда\n   генерация завершена, либо `202` пока она ещё в очереди/выполняется.\n4. **Cancel** — `POST /v1/requests/{request_id}/cancel` отменяет ещё не\n   завершённую генерацию и возвращает зарезервированные кредиты.\n\nАльтернатива опросу `status_url` — передать `webhook_url` в теле `submit`.\nПо завершении Clipia пришлёт подписанный `POST` (см. секцию **webhooks**).\n\n## Аутентификация\n\nВсе запросы к `/v1/*` требуют API-ключ в заголовке `Authorization` со схемой\n`Key`:\n\n```\nAuthorization: Key clipia_live_xxxxxxxxxxxxxxxxxxxxxx\n```\n\nКлюч создаётся в личном кабинете (Настройки → API-ключи) и показывается один\nраз. Это серверный секрет — не размещайте его в браузере, мобильных\nприложениях или публичных репозиториях.\n\n## Тарификация\n\nСтоимость вызова — **фиксированная цена за операцию в кредитах**,\nдетерминированно вычисляемая из модели и параметров и известная заранее.\nКредиты резервируются при `submit` и окончательно списываются при успехе;\nпри фейле или отмене возвращаются полностью.\n",
    "termsOfService": "https://clipia.ai/terms",
    "contact": {
      "name": "Clipia API Support",
      "url": "https://clipia.ai"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://clipia.ai/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.clipia.ai",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Queue",
      "description": "Очередь генераций — submit, status, result, cancel."
    },
    {
      "name": "Models",
      "description": "Каталог моделей и их схемы входа."
    },
    {
      "name": "Account",
      "description": "Аккаунт, баланс и использование."
    }
  ],
  "paths": {
    "/v1/models/{model}": {
      "post": {
        "tags": [
          "Queue"
        ],
        "operationId": "submitGeneration",
        "summary": "Поставить генерацию в очередь (submit)",
        "description": "Ставит генерацию в очередь и сразу возвращает `request_id` со ссылками на\nстатус, результат и отмену. Требует scope `generate`.\n\n**Sandbox.** При вызове с тестовым ключом (`clipia_test_…`) запрос не\nсписывает кредиты и не запускает реальную генерацию: ответ сразу содержит\n`status: COMPLETED` и `queue_position: 0`, а `GET /v1/requests/{request_id}`\nвернёт детерминированный mock-output (фиксированный sample-ассет на\n`media.clipia.ai`). `cost` показывает расчётную стоимость, но не списывается.\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ModelSlug"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitRequest"
              },
              "examples": {
                "textToImage": {
                  "summary": "Text-to-image (Nano Banana 2)",
                  "value": {
                    "input": {
                      "prompt": "a sunset over mountains, cinematic",
                      "aspect_ratio": "16:9"
                    },
                    "webhook_url": "https://your-server.com/clipia/webhook"
                  }
                },
                "imageToVideo": {
                  "summary": "Image-to-video",
                  "value": {
                    "input": {
                      "image_url": "https://media.clipia.ai/uploads/ref-001.png",
                      "prompt": "gentle camera push-in, golden hour",
                      "duration": 4,
                      "resolution": "720p",
                      "aspect_ratio": "16:9"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Генерация принята и поставлена в очередь.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitResponse"
                },
                "examples": {
                  "queued": {
                    "summary": "Поставлено в очередь (боевой ключ)",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "IN_QUEUE",
                      "queue_position": 2,
                      "status_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b/status",
                      "response_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "cancel_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b/cancel",
                      "cost": 12
                    }
                  },
                  "sandbox": {
                    "summary": "Песочница (тестовый ключ clipia_test_…) — сразу COMPLETED",
                    "value": {
                      "request_id": "9c2f7a10-3e44-4b1a-bb9d-77e5c0a1d2e3",
                      "status": "COMPLETED",
                      "queue_position": 0,
                      "status_url": "https://api.clipia.ai/v1/requests/9c2f7a10-3e44-4b1a-bb9d-77e5c0a1d2e3/status",
                      "response_url": "https://api.clipia.ai/v1/requests/9c2f7a10-3e44-4b1a-bb9d-77e5c0a1d2e3",
                      "cancel_url": "https://api.clipia.ai/v1/requests/9c2f7a10-3e44-4b1a-bb9d-77e5c0a1d2e3/cancel",
                      "cost": 12
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "tags": [
          "Models"
        ],
        "operationId": "getModel",
        "summary": "Схема модели",
        "description": "Возвращает схему входа (`input_schema`) и тарификацию конкретной модели.\nДоступно любому валидному ключу (scope не требуется).\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ModelSlug"
          }
        ],
        "responses": {
          "200": {
            "description": "Детали модели.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelDetail"
                },
                "examples": {
                  "imageModel": {
                    "summary": "Image-модель",
                    "value": {
                      "slug": "nano-banana-2",
                      "type": "image",
                      "name": "Nano Banana 2",
                      "modalities": [
                        "text-to-image",
                        "image-to-image"
                      ],
                      "input_schema": {
                        "prompt": {
                          "type": "string",
                          "required": true
                        },
                        "image_url": {
                          "type": "string",
                          "required": false
                        },
                        "aspect_ratio": {
                          "type": "string",
                          "enum": [
                            "1:1",
                            "16:9",
                            "9:16"
                          ]
                        }
                      },
                      "pricing": {
                        "credits_base": 12
                      }
                    }
                  },
                  "videoModel": {
                    "summary": "Video-модель",
                    "value": {
                      "slug": "seedance-2-fast-i2v",
                      "type": "video",
                      "name": "Seedance 2 Fast",
                      "modalities": [
                        "image-to-video"
                      ],
                      "input_schema": {
                        "image_url": {
                          "type": "string",
                          "required": true
                        },
                        "prompt": {
                          "type": "string",
                          "required": false
                        },
                        "duration": {
                          "type": "number",
                          "enum": [
                            4,
                            8
                          ],
                          "default": 4
                        },
                        "resolution": {
                          "type": "string",
                          "enum": [
                            "480p",
                            "720p",
                            "1080p"
                          ],
                          "default": "720p"
                        },
                        "aspect_ratio": {
                          "type": "string",
                          "enum": [
                            "16:9",
                            "9:16",
                            "1:1"
                          ]
                        }
                      },
                      "pricing": {
                        "credits_base": 40,
                        "multipliers": {
                          "resolution": {
                            "720p": 1,
                            "1080p": 1.5
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/requests/{request_id}/status": {
      "get": {
        "tags": [
          "Queue"
        ],
        "operationId": "getRequestStatus",
        "summary": "Статус запроса",
        "description": "Возвращает текущий статус генерации, позицию в очереди и прогресс.\nДоступно любому валидному ключу (scope не требуется).\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Текущий статус запроса.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                },
                "examples": {
                  "inProgress": {
                    "summary": "Выполняется",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "IN_PROGRESS",
                      "queue_position": null,
                      "progress": 45,
                      "logs": []
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/requests/{request_id}": {
      "get": {
        "tags": [
          "Queue"
        ],
        "operationId": "getRequestResult",
        "summary": "Результат запроса",
        "description": "Возвращает результат генерации (`200`) когда статус терминальный\n(`COMPLETED` / `FAILED` / `CANCELED`), либо `202` пока запрос ещё в очереди\nили выполняется. Доступно любому валидному ключу (scope не требуется).\n\nВсе медиа-URL ведут на CDN `media.clipia.ai`.\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Терминальный результат. Для `COMPLETED` содержит `output`;\nдля `FAILED` — санитизированный `error`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultResponse"
                },
                "examples": {
                  "completedImage": {
                    "summary": "Готово (изображение)",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "COMPLETED",
                      "model": "nano-banana-2",
                      "output": {
                        "images": [
                          {
                            "url": "https://media.clipia.ai/works/8f3a1c7e.png",
                            "width": 1024,
                            "height": 1024
                          }
                        ]
                      },
                      "cost": 12,
                      "created_at": "2026-06-01T12:00:00Z",
                      "completed_at": "2026-06-01T12:00:18Z"
                    }
                  },
                  "completedVideo": {
                    "summary": "Готово (видео)",
                    "value": {
                      "request_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
                      "status": "COMPLETED",
                      "model": "seedance-2-fast-i2v",
                      "output": {
                        "video": {
                          "url": "https://media.clipia.ai/works/a1b2c3d4.mp4",
                          "width": 1280,
                          "height": 720,
                          "duration": 4
                        }
                      },
                      "cost": 40,
                      "created_at": "2026-06-01T12:00:00Z",
                      "completed_at": "2026-06-01T12:00:42Z"
                    }
                  },
                  "failed": {
                    "summary": "Ошибка (кредиты возвращены)",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "FAILED",
                      "model": "nano-banana-2",
                      "output": {},
                      "cost": 0,
                      "created_at": "2026-06-01T12:00:00Z",
                      "error": {
                        "code": "GENERATION_FAILED",
                        "message": "Генерация не удалась. Кредиты возвращены."
                      }
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Запрос ещё выполняется (`IN_QUEUE` / `IN_PROGRESS`). Продолжайте\nопрашивать `status_url`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                },
                "examples": {
                  "pending": {
                    "summary": "Ещё в работе",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "IN_PROGRESS",
                      "queue_position": null,
                      "progress": 70,
                      "logs": []
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/requests/{request_id}/cancel": {
      "post": {
        "tags": [
          "Queue"
        ],
        "operationId": "cancelRequest",
        "summary": "Отменить запрос",
        "description": "Отменяет запрос, если он ещё `IN_QUEUE` или `IN_PROGRESS`.\nЗарезервированные кредиты возвращаются. Требует scope `generate`.\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Запрос отменён.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                },
                "examples": {
                  "canceled": {
                    "summary": "Отменено",
                    "value": {
                      "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                      "status": "CANCELED"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "tags": [
          "Models"
        ],
        "operationId": "listModels",
        "summary": "Список моделей",
        "description": "Возвращает каталог активных моделей Clipia — изображения и видео.\nДоступно любому валидному ключу (scope не требуется).\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Каталог моделей.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                },
                "examples": {
                  "catalog": {
                    "summary": "Каталог",
                    "value": {
                      "data": [
                        {
                          "slug": "nano-banana-2",
                          "type": "image",
                          "name": "Nano Banana 2",
                          "modalities": [
                            "text-to-image",
                            "image-to-image"
                          ],
                          "pricing": {
                            "credits": 12
                          }
                        },
                        {
                          "slug": "seedance-2-fast-i2v",
                          "type": "video",
                          "name": "Seedance 2 Fast",
                          "modalities": [
                            "image-to-video"
                          ],
                          "pricing": {
                            "credits": 40,
                            "note": "зависит от длительности/разрешения"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getAccount",
        "summary": "Аккаунт и баланс",
        "description": "Возвращает баланс в кредитах и использование за 30 дней.\nСтоимость 1 кредита в деньгах через API не раскрывается.\nДоступно любому валидному ключу (scope не требуется).\n",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Сведения об аккаунте.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "examples": {
                  "account": {
                    "summary": "Аккаунт",
                    "value": {
                      "account_id": "acct_8f3a1c7e",
                      "balance": {
                        "credits": 1840
                      },
                      "usage_30d": {
                        "requests": 512,
                        "credits_spent": 6120
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "webhooks": {
    "generation.completed": {
      "post": {
        "operationId": "webhookGenerationCompleted",
        "summary": "Генерация завершена успешно",
        "description": "Если при `submit` был передан `webhook_url`, Clipia отправит `POST` на\nэтот URL по успешном завершении генерации.\n\n**Заголовки подписи** (HMAC-SHA256):\n- `X-Clipia-Webhook-Id` — UUID доставки.\n- `X-Clipia-Timestamp` — Unix-время (секунды).\n- `X-Clipia-Signature` — формат `t=<ts>,v1=<hmac>`, где\n  `hmac = HMAC_SHA256(secret, \"{timestamp}.{raw_body}\")` в hex.\n  `secret` — webhook signing secret из личного кабинета.\n\nПроверяйте подпись timing-safe сравнением и отбрасывайте доставки старше\nокна свежести (по умолчанию 300 секунд). Обрабатывайте идемпотентно по\n`request_id` (возможна повторная доставка). Ожидается ответ `2xx` в\nтечение 10 секунд; иначе — ретраи с экспоненциальной задержкой до 6 попыток.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Payload успешной доставки.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSuccess"
              },
              "examples": {
                "completed": {
                  "summary": "Успех",
                  "value": {
                    "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                    "status": "OK",
                    "payload": {
                      "model": "nano-banana-2",
                      "output": {
                        "images": [
                          {
                            "url": "https://media.clipia.ai/works/8f3a1c7e.png",
                            "width": 1024,
                            "height": 1024
                          }
                        ]
                      },
                      "cost": 12
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Доставка принята получателем."
          }
        }
      }
    },
    "generation.failed": {
      "post": {
        "operationId": "webhookGenerationFailed",
        "summary": "Генерация завершилась ошибкой",
        "description": "Если при `submit` был передан `webhook_url`, Clipia отправит `POST` на\nэтот URL при ошибке генерации. Кредиты при этом возвращены.\n\nЗаголовки подписи и правила доставки идентичны `generation.completed`\n(HMAC-SHA256, `X-Clipia-Signature`, окно свежести, ретраи).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Payload доставки об ошибке.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookError"
              },
              "examples": {
                "failed": {
                  "summary": "Ошибка",
                  "value": {
                    "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
                    "status": "ERROR",
                    "error": {
                      "code": "GENERATION_FAILED",
                      "message": "Генерация не удалась. Кредиты возвращены."
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Доставка принята получателем."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "API-ключ в заголовке `Authorization` со схемой `Key`:\n\n```\nAuthorization: Key clipia_live_xxxxxxxxxxxxxxxxxxxxxx\n```\n\nПередавайте полную строку, включая префикс схемы `Key ` и пробел.\nКлюч создаётся в личном кабинете (Настройки → API-ключи) и показывается\nодин раз. Формат: `clipia_live_…` (боевой), `clipia_test_…` (песочница).\n\n**Sandbox / тестовый режим.** Ключ с префиксом `clipia_test_…` работает в\nпесочнице: `submit` не списывает кредиты и не запускает реальную\nгенерацию — он мгновенно возвращает `status: COMPLETED` с детерминированным\nmock-результатом (фиксированный sample-ассет на `media.clipia.ai`). Поле\n`cost` показывает расчётную стоимость, но она не списывается. Вебхуки\nприходят тем же подписанным механизмом (HMAC-SHA256). Режим предназначен\nдля отладки интеграции до подключения боевого ключа.\n",
        "x-sandbox": {
          "keyPrefix": "clipia_test_",
          "chargesCredits": false,
          "callsGeneration": false,
          "immediateStatus": "COMPLETED",
          "sampleImageUrl": "https://media.clipia.ai/sandbox/sample-image.png",
          "sampleVideoUrl": "https://media.clipia.ai/sandbox/sample-video.mp4"
        }
      }
    },
    "parameters": {
      "ModelSlug": {
        "name": "model",
        "in": "path",
        "required": true,
        "description": "Slug модели, напр. `nano-banana-2`, `seedance-2-fast-i2v`. Список — `GET /v1/models`.",
        "schema": {
          "type": "string",
          "examples": [
            "nano-banana-2",
            "seedance-2-fast-i2v"
          ]
        }
      },
      "RequestId": {
        "name": "request_id",
        "in": "path",
        "required": true,
        "description": "Идентификатор запроса генерации, полученный при `submit`.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "examples": [
            "764cabcf-b745-4b3e-ae38-1200304cf45b"
          ]
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "UUID v4 для безопасных ретраев `POST`. Тот же ключ с теми же параметрами\nвернёт тот же `request_id` (без повторного списания). Срок хранения — 24 часа.\nТот же ключ с другими параметрами → `409`.\n",
        "schema": {
          "type": "string",
          "format": "uuid",
          "examples": [
            "8f3a1c7e-2b4d-4e6f-9a01-23456789abcd"
          ]
        }
      },
      "WebhookId": {
        "name": "X-Clipia-Webhook-Id",
        "in": "header",
        "required": true,
        "description": "UUID доставки вебхука.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WebhookTimestamp": {
        "name": "X-Clipia-Timestamp",
        "in": "header",
        "required": true,
        "description": "Unix-время доставки (секунды). Используется для проверки свежести.",
        "schema": {
          "type": "integer",
          "format": "int64",
          "examples": [
            1717243200
          ]
        }
      },
      "WebhookSignature": {
        "name": "X-Clipia-Signature",
        "in": "header",
        "required": true,
        "description": "Подпись доставки в формате `t=<ts>,v1=<hmac>`, где\n`hmac = HMAC_SHA256(secret, \"{timestamp}.{raw_body}\")` в hex.\n",
        "schema": {
          "type": "string",
          "examples": [
            "t=1717243200,v1=5257a869e7d1f3..."
          ]
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Ключ отсутствует, неверный или отозван.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "invalidApiKey": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "invalid_api_key",
                    "message": "API-ключ отсутствует, неверный или отозван."
                  }
                }
              }
            }
          }
        }
      },
      "InsufficientCredits": {
        "description": "Недостаточно кредитов на балансе.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "insufficientCredits": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "insufficient_credits",
                    "message": "Недостаточно кредитов для генерации. Пополните баланс."
                  }
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "У ключа нет нужного scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "insufficientScope": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "insufficient_scope",
                    "message": "У ключа нет scope `generate`."
                  }
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Неизвестный `request_id` или `model`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "notFound": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "not_found",
                    "message": "Запрос с таким идентификатором не найден."
                  }
                }
              }
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Параметры `input` не подходят выбранной модели.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "modelInputInvalid": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "model_input_invalid",
                    "message": "Параметр `resolution` не поддерживается этой моделью."
                  }
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Превышен лимит запросов.",
        "headers": {
          "Retry-After": {
            "description": "Через сколько секунд можно повторить запрос.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Limit": {
            "description": "Лимит запросов в минуту.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Remaining": {
            "description": "Остаток запросов в текущем окне.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Через сколько секунд сбросится окно лимита.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "rateLimited": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "rate_limit_exceeded",
                    "message": "Превышен лимит запросов. Повторите позже."
                  }
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "GenerationStatus": {
        "type": "string",
        "description": "Статус генерации в очереди.",
        "enum": [
          "IN_QUEUE",
          "IN_PROGRESS",
          "COMPLETED",
          "FAILED",
          "CANCELED"
        ]
      },
      "SubmitRequest": {
        "type": "object",
        "required": [
          "input"
        ],
        "additionalProperties": false,
        "properties": {
          "input": {
            "type": "object",
            "description": "Параметры генерации. Состав зависит от модели — точную схему смотрите в\n`GET /v1/models/{model}` (`input_schema`). Распространённые ключи:\n`prompt`, `image_url`, `image_urls`, `aspect_ratio`, `duration`,\n`resolution`.\n",
            "additionalProperties": true,
            "examples": [
              {
                "prompt": "a sunset over mountains, cinematic",
                "aspect_ratio": "16:9"
              }
            ]
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "URL для POST-уведомления о завершении генерации (опционально).",
            "examples": [
              "https://your-server.com/clipia/webhook"
            ]
          }
        }
      },
      "SubmitResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status",
          "status_url",
          "response_url",
          "cancel_url",
          "cost"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор запроса генерации."
          },
          "status": {
            "$ref": "#/components/schemas/GenerationStatus"
          },
          "queue_position": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Позиция в очереди (если запрос в очереди)."
          },
          "status_url": {
            "type": "string",
            "format": "uri",
            "description": "Ссылка для проверки статуса."
          },
          "response_url": {
            "type": "string",
            "format": "uri",
            "description": "Ссылка для получения результата."
          },
          "cancel_url": {
            "type": "string",
            "format": "uri",
            "description": "Ссылка для отмены генерации."
          },
          "cost": {
            "type": "number",
            "description": "Фиксированная стоимость операции в кредитах (резервируется при submit)."
          }
        }
      },
      "StatusResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор запроса генерации."
          },
          "status": {
            "$ref": "#/components/schemas/GenerationStatus"
          },
          "queue_position": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Позиция в очереди (для `IN_QUEUE`), иначе `null`."
          },
          "progress": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Прогресс выполнения 0..100 (для `IN_PROGRESS`)."
          },
          "logs": {
            "type": "array",
            "description": "Логи выполнения (если запрошены).",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ResultResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status",
          "model",
          "output",
          "cost",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор запроса генерации."
          },
          "status": {
            "$ref": "#/components/schemas/GenerationStatus"
          },
          "model": {
            "type": "string",
            "description": "Slug модели, выполнившей генерацию.",
            "examples": [
              "nano-banana-2"
            ]
          },
          "output": {
            "type": "object",
            "description": "Результат генерации. Для изображений — `images: [{ url, width, height }]`;\nдля видео — `video: { url, width, height, duration }`. Все медиа-URL\nведут на CDN `media.clipia.ai`.\n",
            "additionalProperties": true
          },
          "cost": {
            "type": "number",
            "description": "Итоговая стоимость генерации в кредитах (0 при FAILED/CANCELED)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Время создания запроса (ISO 8601)."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "Время завершения генерации (ISO 8601)."
          },
          "error": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GenerationError"
              }
            ],
            "description": "Информация об ошибке (только при `status = FAILED`). Санитизирована."
          }
        }
      },
      "GenerationError": {
        "type": "object",
        "description": "Санитизированная ошибка генерации — без деталей внутренней инфраструктуры.",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "examples": [
              "GENERATION_FAILED"
            ]
          },
          "message": {
            "type": "string",
            "examples": [
              "Генерация не удалась. Кредиты возвращены."
            ]
          }
        }
      },
      "CancelResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/GenerationStatus"
          }
        }
      },
      "ModelSummary": {
        "type": "object",
        "required": [
          "slug",
          "type",
          "name"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "description": "Slug модели для использования в `POST /v1/models/{model}`.",
            "examples": [
              "nano-banana-2"
            ]
          },
          "type": {
            "type": "string",
            "description": "Тип выходного контента.",
            "enum": [
              "image",
              "video"
            ]
          },
          "name": {
            "type": "string",
            "description": "Отображаемое имя модели.",
            "examples": [
              "Nano Banana 2"
            ]
          },
          "modalities": {
            "type": "array",
            "description": "Поддерживаемые модальности.",
            "items": {
              "type": "string",
              "examples": [
                "text-to-image",
                "image-to-image",
                "image-to-video"
              ]
            }
          },
          "pricing": {
            "type": "object",
            "description": "Краткая тарификация модели.",
            "properties": {
              "credits": {
                "type": "number",
                "description": "Базовая стоимость в кредитах."
              },
              "note": {
                "type": "string",
                "description": "Пояснение к тарификации."
              }
            },
            "additionalProperties": true
          }
        }
      },
      "ModelList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelSummary"
            }
          }
        }
      },
      "ModelDetail": {
        "type": "object",
        "required": [
          "slug",
          "type",
          "name",
          "input_schema",
          "pricing"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "examples": [
              "seedance-2-fast-i2v"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "name": {
            "type": "string",
            "examples": [
              "Seedance 2 Fast"
            ]
          },
          "modalities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "input_schema": {
            "type": "object",
            "description": "Схема входных параметров: ключ → дескриптор (`type`, `required`,\n`enum`, `default`). Передавайте эти ключи внутри `input` при submit.\n",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "examples": [
                    "string",
                    "number",
                    "boolean"
                  ]
                },
                "required": {
                  "type": "boolean"
                },
                "enum": {
                  "type": "array",
                  "items": {}
                },
                "default": {}
              },
              "additionalProperties": true
            }
          },
          "pricing": {
            "type": "object",
            "description": "Детерминированная тарификация модели в кредитах.",
            "properties": {
              "credits_base": {
                "type": "number",
                "description": "Базовая стоимость в кредитах."
              },
              "multipliers": {
                "type": "object",
                "description": "Множители по параметрам (напр. по разрешению).",
                "additionalProperties": true
              }
            },
            "additionalProperties": true
          }
        }
      },
      "Account": {
        "type": "object",
        "required": [
          "balance",
          "usage_30d"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "description": "Идентификатор аккаунта.",
            "examples": [
              "acct_8f3a1c7e"
            ]
          },
          "balance": {
            "type": "object",
            "required": [
              "credits"
            ],
            "properties": {
              "credits": {
                "type": "number",
                "description": "Текущий баланс в кредитах.",
                "examples": [
                  1840
                ]
              }
            }
          },
          "usage_30d": {
            "type": "object",
            "description": "Использование за последние 30 дней.",
            "required": [
              "requests",
              "credits_spent"
            ],
            "properties": {
              "requests": {
                "type": "integer",
                "description": "Число запросов.",
                "examples": [
                  512
                ]
              },
              "credits_spent": {
                "type": "number",
                "description": "Списано кредитов.",
                "examples": [
                  6120
                ]
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Единый JSON-формат ошибки. Сообщения санитизированы.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "Категория ошибки.",
                "examples": [
                  "invalid_request_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string",
                "description": "Машиночитаемый код ошибки.",
                "examples": [
                  "invalid_api_key",
                  "insufficient_credits",
                  "insufficient_scope",
                  "not_found",
                  "idempotency_key_reuse",
                  "request_in_progress",
                  "model_input_invalid",
                  "rate_limit_exceeded",
                  "internal_error",
                  "service_unavailable"
                ]
              },
              "message": {
                "type": "string",
                "description": "Человекочитаемое описание ошибки."
              }
            }
          }
        }
      },
      "WebhookSuccess": {
        "type": "object",
        "description": "Payload вебхука об успешном завершении генерации.",
        "required": [
          "request_id",
          "status",
          "payload"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "const": "OK",
            "description": "Признак успеха."
          },
          "payload": {
            "type": "object",
            "required": [
              "model",
              "output",
              "cost"
            ],
            "properties": {
              "model": {
                "type": "string",
                "examples": [
                  "nano-banana-2"
                ]
              },
              "output": {
                "type": "object",
                "description": "Результат генерации (медиа-URL на `media.clipia.ai`).",
                "additionalProperties": true
              },
              "cost": {
                "type": "number",
                "description": "Итоговая стоимость в кредитах."
              }
            }
          }
        }
      },
      "WebhookError": {
        "type": "object",
        "description": "Payload вебхука об ошибке генерации (кредиты возвращены).",
        "required": [
          "request_id",
          "status",
          "error"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "const": "ERROR",
            "description": "Признак ошибки."
          },
          "error": {
            "$ref": "#/components/schemas/GenerationError"
          }
        }
      }
    }
  }
}
