{"openapi":"3.0.3","info":{"title":"AI Hub · Local prototype","version":"0.16.0","description":"Закрытый локальный API: владелец и приглашённые тестировщики, PostgreSQL-сессия в HttpOnly cookie. Для POST/DELETE нужен X-CSRF-Token из auth/me, кроме login/accept-invite с X-Requested-With: AIHub. Публичной регистрации нет. Сервер слушает только 127.0.0.1."},"servers":[{"url":"/"}],"security":[{"SessionCookie":[]}],"paths":{"/api/v1/account/usage":{"get":{"summary":"Свой тестовый бюджет и учтённые оценки, не фактические списания","responses":{"200":{"description":"budget_usd (null у владельца), committed_estimate_usd, max_pending, storage_limit_bytes, billing."},"401":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/admin/accounts":{"get":{"summary":"Аккаунты и лимиты — только владелец","responses":{"200":{"description":"items: id, email, role, disabled и поля account/usage."},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/admin/accounts/{id}":{"post":{"summary":"Изменить лимиты/отключить тестировщика — только владелец","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["budget_usd","disabled","max_pending"],"properties":{"budget_usd":{"type":"number","minimum":0,"maximum":100},"disabled":{"type":"boolean"},"max_pending":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"204":{"description":"Настройки сохранены; при отключении сессии отозваны. Уже запущенная генерация может завершиться."},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/admin/invites":{"post":{"summary":"Одноразовое приглашение на 48 часов — только владелец","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","budget_usd"],"properties":{"email":{"type":"string","format":"email"},"budget_usd":{"type":"number","minimum":0,"maximum":100}}}}}},"responses":{"201":{"description":"invite_path содержит секрет во фрагменте ссылки. Повтор для email отзывает прежние приглашения. Отправка email не выполняется."},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/admin/invites/revoke":{"post":{"summary":"Отозвать неиспользованные приглашения по email — только владелец","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"204":{"description":"Приглашения отозваны."},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/auth/accept-invite":{"post":{"security":[],"summary":"Создать тестовый аккаунт по приглашению","parameters":[{"name":"X-Requested-With","in":"header","required":true,"schema":{"type":"string","enum":["AIHub"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password","token"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password","minLength":15},"token":{"type":"string","minLength":64,"maxLength":64}}}}}},"responses":{"201":{"description":"Аккаунт создан, нужен обычный вход."},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/auth/login":{"post":{"security":[],"summary":"Вход владельца","parameters":[{"name":"X-Requested-With","in":"header","required":true,"schema":{"type":"string","enum":["AIHub"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password"}}}}}},"responses":{"200":{"description":"Устанавливает сессионную cookie; возвращает account и csrf_token."},"401":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/auth/me":{"get":{"summary":"Текущий аккаунт и CSRF-токен","responses":{"200":{"description":"account: id/email/role; csrf_token для изменяющих запросов."},"401":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/auth/logout":{"post":{"summary":"Отозвать текущую сессию","responses":{"204":{"description":"Сессия отозвана, cookie очищена."},"401":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/auth/logout-all":{"post":{"summary":"Отозвать все сессии владельца","responses":{"204":{"description":"Все сессии отозваны."},"401":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/storage/cleanup-report":{"get":{"operationId":"getCleanupReport","summary":"Кандидаты на очистку: только отчёт, без удаления","responses":{"200":{"description":"Снимок зарегистрированных исходников. Первые 100 кандидатов, общие суммы по всем. Связанные, неготовые и неизвестные размеры исключены; S3 не вызывается.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleanupReport"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/storage/usage":{"get":{"operationId":"getStorageUsage","summary":"Учёт исходников и результатов по PostgreSQL","responses":{"200":{"description":"Зарегистрированные байты всех сохранённых назначений S3, состояния и правила. Не фактический объём бакета.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageUsage"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/storage/bucket":{"get":{"operationId":"getBucketUsage","summary":"Прочитать объём текущих объектов настроенного бакета","responses":{"200":{"description":"Полный обход до 10 страниц, кеш 60 секунд. Без старых версий и multipart; не биллинг и не квота.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BucketUsage"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/files":{"post":{"operationId":"uploadImage","summary":"Проверить JPEG/PNG и сохранить подготовленный исходник в S3","description":"До 10 МБ, 16 Мп, стороны 64–8192 пикселей, без анимации. Проверяется полным декодированием и сохраняется в исходном формате без изменения байтов и метаданных. Один файловый запрос за раз. Повтор того же ключа и байтов возвращает тот же ID.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Повтор загрузки.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InputFile"}}}},"201":{"description":"Файл готов.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InputFile"}}}},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listInputFiles","summary":"До 100 неудалённых исходников","responses":{"200":{"description":"Исходники, новые сначала.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InputFile"}}}}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/files/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getInputFile","summary":"Состояние исходника","responses":{"200":{"description":"Файл.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InputFile"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteInputFile","summary":"Удалить исходник, не связанный с заданиями","responses":{"200":{"description":"Удалён.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InputFile"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/files/{id}/asset":{"get":{"operationId":"getInputAsset","summary":"Предпросмотр подготовленного исходника","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"302":{"description":"Ссылка S3 на 300 секунд, no-store.","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/health":{"get":{"operationId":"getHealth","summary":"Состояние сервера","responses":{"200":{"description":"Сервер и локальная база доступны.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/v1/models":{"get":{"operationId":"listModels","summary":"Каталог и схема входных параметров","responses":{"200":{"description":"Две тестовые модели и двенадцать вариантов fal; редактирование и upscale дополнительно требуют загрузок S3/PostgreSQL. Каталог содержит размеры, схемы параметров и оценки цен.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}}}}}}}}},"/api/v1/generations":{"post":{"operationId":"createGeneration","summary":"Создать задание","description":"Новый ключ = новое задание. Повтор того же ключа и нормализованного тела возвращает прежнее задание. Другое тело с прежним ключом даёт 409. При неизвестном результате сетевого запроса повторяйте тот же ключ и тело.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"},"example":"demo-request-0001"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationInput"},"example":{"model_id":"demo/image","inputs":{"prompt":"Вымышленный остров среди облаков"}}}}},"responses":{"200":{"description":"Повтор запроса: возвращено уже существующее задание.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"202":{"description":"Новое задание принято. Статус можно опрашивать по Location.","headers":{"Location":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listGenerations","summary":"История, новые задания сначала","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":1000000,"default":0}}],"responses":{"200":{"description":"Одна страница истории.","content":{"application/json":{"schema":{"type":"object","required":["items","total","limit","offset"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Generation"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}},"400":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/generations/{id}/resume":{"post":{"operationId":"resumeGeneration","summary":"Продолжить получение результата сохранённого запроса или локального ответа без новой генерации","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Задание.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/generations/{id}/asset":{"get":{"operationId":"getAsset","summary":"Сохранённое изображение поставщика","parameters":[{"name":"download","in":"query","required":false,"schema":{"type":"string","enum":["1"]},"description":"Скачать вложением через сервер; обычный растровый предпросмотр использует редирект S3."},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"JPEG, PNG, WebP или проверенный SVG","content":{"image/svg+xml":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"Временная ссылка S3 на 300 секунд; ответ не кешируется.","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/generations/{id}":{"get":{"operationId":"getGeneration","summary":"Статус, результат или ошибка задания","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Задание.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"404":{"description":"Ошибка с кодом и объяснением.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"securitySchemes":{"SessionCookie":{"type":"apiKey","in":"cookie","name":"ai_hub_session"}},"schemas":{"GenerationInput":{"oneOf":[{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["demo/image"]},"inputs":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["demo/error"]},"inputs":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/flux-schnell","fal-ai/flux/schnell"]},"inputs":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."},"image_size":{"type":"string","enum":["square","landscape","portrait"],"default":"square","description":"Один из разрешённых размеров из image_sizes модели."},"seed":{"type":"integer","minimum":0,"maximum":2147483647,"description":"Необязательное число для повторяемости при тех же настройках и версии модели. Без него fal выбирает случайное."}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/flux-dev","fal-ai/flux/dev"]},"inputs":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."},"image_size":{"type":"string","enum":["square","landscape","portrait"],"default":"square","description":"Один из разрешённых размеров из image_sizes модели."},"seed":{"type":"integer","minimum":0,"maximum":2147483647,"description":"Необязательное число для повторяемости при тех же настройках и версии модели. Без него fal выбирает случайное."}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/flux-dev-edit","fal-ai/flux/dev/image-to-image"]},"inputs":{"type":"object","required":["prompt","image_file_id"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."},"seed":{"type":"integer","minimum":0,"maximum":2147483647,"description":"Необязательное число для повторяемости при тех же настройках и версии модели. Без него fal выбирает случайное."},"image_file_id":{"type":"string","format":"uuid","description":"ID готового исходника из POST /api/v1/files."},"strength":{"type":"number","minimum":0.1,"maximum":1,"default":0.85,"description":"Сила преобразования. Чем выше, тем сильнее меняется исходник."}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/recraft-vectorize"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/topaz-precision"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"scale":{"type":"integer","title":"Увеличение","enum":[2,4],"default":2},"output_format":{"type":"string","title":"Формат результата","enum":["png","jpeg"],"default":"png"},"variant":{"type":"string","title":"Режим Topaz","enum":["Standard V2","High Fidelity V3","High Fidelity V2","Low Resolution V2","CGI","Text Refine","Faces"],"default":"Standard V2"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/topaz-generative"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"scale":{"type":"integer","title":"Увеличение","enum":[2,4],"default":2},"output_format":{"type":"string","title":"Формат результата","enum":["png","jpeg"],"default":"png"},"variant":{"type":"string","title":"Режим Topaz","enum":["Wonder 3.5","Wonder 3","Wonder 2","Wonder","Recover 3","Standard MAX","Redefine","Recovery V2","Recovery"],"default":"Wonder 3.5"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/topaz-creative"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"scale":{"type":"integer","title":"Увеличение","enum":[2,4],"default":2},"output_format":{"type":"string","title":"Формат результата","enum":["png","jpeg"],"default":"png"},"variant":{"type":"string","title":"Режим Topaz","enum":["Bloom 2","Bloom","Bloom Realism"],"default":"Bloom 2"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/nano-banana-2"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"seed":{"type":"integer","title":"Seed","minimum":0,"maximum":2147483647},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Разрешение","enum":["0.5K","1K","2K","4K"],"default":"1K"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png","webp"],"default":"jpeg"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/nano-banana-2-edit"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt","image_file_id"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"seed":{"type":"integer","title":"Seed","minimum":0,"maximum":2147483647},"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Разрешение","enum":["0.5K","1K","2K","4K"],"default":"1K"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png","webp"],"default":"jpeg"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/flux-2-turbo"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"seed":{"type":"integer","title":"Seed","minimum":0,"maximum":2147483647},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Длинная сторона, пиксели","enum":["512","1024","2048"],"default":"1024"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png","webp"],"default":"jpeg"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/flux-2-turbo-edit"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt","image_file_id"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"seed":{"type":"integer","title":"Seed","minimum":0,"maximum":2147483647},"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Длинная сторона, пиксели","enum":["512","1024","2048"],"default":"1024"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png","webp"],"default":"jpeg"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/esrgan"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"scale":{"type":"integer","title":"Увеличение","enum":[2,4],"default":2},"output_format":{"type":"string","title":"Формат результата","enum":["png","jpeg"],"default":"png"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/esrgan-anime"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"scale":{"type":"integer","title":"Увеличение","enum":[2,4],"default":2},"output_format":{"type":"string","title":"Формат результата","enum":["png","jpeg"],"default":"png"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/seedream-5-pro"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Длинная сторона, пиксели","enum":["1024","1536","2048"],"default":"1024"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png"],"default":"jpeg"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/ideogram-4"]},"inputs":{"type":"object","additionalProperties":false,"required":["prompt"],"properties":{"prompt":{"type":"string","title":"Описание","minLength":1,"maxLength":2000},"seed":{"type":"integer","title":"Seed","minimum":0,"maximum":2147483647},"aspect_ratio":{"type":"string","title":"Пропорции кадра","enum":["1:1","4:3","3:4","16:9","9:16","3:2","2:3"],"default":"1:1"},"resolution":{"type":"string","title":"Длинная сторона, пиксели","enum":["512","1024","2048"],"default":"1024"},"output_format":{"type":"string","title":"Формат результата","enum":["jpeg","png"],"default":"jpeg"},"quality":{"type":"string","title":"Режим качества","enum":["fast","balanced","quality"],"default":"balanced"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/birefnet-v2"]},"inputs":{"type":"object","additionalProperties":false,"required":["image_file_id"],"properties":{"image_file_id":{"type":"string","title":"Исходное изображение","format":"uuid"},"output_format":{"type":"string","title":"Формат результата","enum":["png","webp"],"default":"png"}}}}},{"type":"object","additionalProperties":false,"required":["model_id","inputs"],"properties":{"model_id":{"type":"string","enum":["image/gemini-flash"]},"inputs":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000,"description":"Описание изображения."},"image_size":{"type":"string","enum":["square"],"default":"square"}}}}}]},"Model":{"type":"object","required":["id","aliases","name","category","provider","mock","description","input_schema"],"properties":{"id":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"},"description":"Старые идентификаторы, принимаемые для совместимости."},"name":{"type":"string"},"category":{"type":"string"},"task":{"type":"string","enum":["text-to-image","image-to-image","upscale","background-removal"]},"pricing_basis":{"type":"string","enum":["estimate","engineering-reserve"]},"provider":{"type":"string","enum":["mock","fal","google"]},"mock":{"type":"boolean"},"description":{"type":"string"},"input_schema":{"type":"object","additionalProperties":true},"estimated_cost_usd":{"type":"number","description":"Оценка размера по умолчанию, не счёт поставщика."},"quality_multipliers":{"type":"object","additionalProperties":{"type":"number"},"description":"Множитель оценки output_options по выбранному режиму quality."},"output_size_tolerance_px":{"type":"integer","description":"Допуск каждой стороны относительно ожидаемого размера; результат содержит фактические размеры."},"output_options":{"type":"array","description":"Разрешённые сочетания пропорций и разрешений; нельзя использовать произвольное декартово произведение enum.","items":{"type":"object","properties":{"aspect_ratio":{"type":"string"},"resolution":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"estimated_cost_usd":{"type":"number"}}}},"image_sizes":{"type":"array","items":{"$ref":"#/components/schemas/ImageSizeOption"}}}},"ImageSizeOption":{"type":"object","required":["id","label","width","height","estimated_cost_usd"],"properties":{"id":{"type":"string","enum":["square","landscape","portrait"]},"label":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"estimated_cost_usd":{"type":"number"}}},"Generation":{"type":"object","required":["id","model_id","provider","inputs","status","result","error","created_at","updated_at","mock","cost_usd"],"properties":{"id":{"type":"string","format":"uuid"},"model_id":{"type":"string","description":"Собственный ID; старые записи сохраняют прежний ID fal."},"provider":{"type":"string","enum":["mock","fal","google"]},"inputs":{"type":"object","description":"Нормализованные параметры по input_schema модели; у upscale в сохранённой записи prompt может быть пустой строкой."},"status":{"type":"string","enum":["queued","running","succeeded","failed","needs_review"]},"result":{"type":"object","nullable":true,"required":["assets"],"properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/Asset"}},"seed":{"type":"integer","minimum":0,"description":"Фактический seed, если fal вернул его."}}},"error":{"type":"object","nullable":true,"required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"diagnostic":{"$ref":"#/components/schemas/FalDiagnostic"}}},"cost_calculation":{"$ref":"#/components/schemas/GoogleCost"},"can_resume":{"type":"boolean","description":"Можно продолжить сохранение/получение без новой платной отправки."},"operation":{"type":"object","properties":{"submission_started":{"type":"boolean"},"response_saved":{"type":"boolean"},"request_id":{"type":"string"},"usage":{"$ref":"#/components/schemas/GoogleUsage"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"mock":{"type":"boolean"},"cost_usd":{"type":"number","nullable":true,"description":"0 для mock; null для внешних поставщиков: фактическое списание неизвестно."},"estimated_cost_usd":{"type":"number","description":"Оценка, не подтверждённое списание."},"fal":{"type":"object","properties":{"submission_started":{"type":"boolean"},"endpoint_id":{"type":"string","description":"Сохранённый endpoint новых заданий; старые записи могут не содержать его."},"request_id":{"type":"string"},"status_url":{"type":"string"},"response_url":{"type":"string"}}}}},"TokenDetail":{"type":"object","properties":{"modality":{"type":"string"},"tokens":{"type":"integer","minimum":0}}},"GoogleUsage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"total_tokens":{"type":"integer"},"thought_tokens":{"type":"integer"},"cached_input_tokens":{"type":"integer"},"tool_input_tokens":{"type":"integer"},"service_tier":{"type":"string"},"invalid_metadata":{"type":"boolean"},"input_token_details":{"type":"array","items":{"$ref":"#/components/schemas/TokenDetail"}},"output_token_details":{"type":"array","items":{"$ref":"#/components/schemas/TokenDetail"}}}},"GoogleCost":{"type":"object","required":["status","source","billing_confirmed","credits_applied","tariff"],"properties":{"status":{"type":"string","enum":["calculated","unavailable"]},"reason":{"type":"string","enum":["missing_usage","inconsistent_usage","incomplete_breakdown","unsupported_usage","unsupported_model"]},"source":{"type":"string","enum":["provider_usage"]},"billing_confirmed":{"type":"boolean","enum":[false]},"credits_applied":{"type":"boolean","enum":[false]},"model_version":{"type":"string"},"amount_usd":{"type":"number"},"amount_nano_usd":{"type":"integer","description":"USD × 1 000 000 000; сумма без ошибок двоичного округления."},"known_subtotal_usd":{"type":"number","description":"Только известные компоненты; НЕ полная стоимость."},"unclassified_output_tokens":{"type":"integer"},"thoughts_basis":{"type":"string","enum":["reported","total_minus_input_output"]},"tariff":{"type":"object","properties":{"version":{"type":"string"},"model":{"type":"string"},"currency":{"type":"string","enum":["USD"]},"service_tier":{"type":"string"},"source":{"type":"string","format":"uri"},"checked_at":{"type":"string","format":"date"},"input_usd_per_million":{"type":"number"},"text_usd_per_million":{"type":"number"},"image_usd_per_million":{"type":"number"}}},"lines":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string","enum":["input","output_image","output_text","thinking"]},"tokens":{"type":"integer"},"usd_per_million":{"type":"number"},"amount_nano_usd":{"type":"integer"}}}}}},"FalDiagnostic":{"type":"object","additionalProperties":false,"required":["stage","reason","elapsed_ms"],"properties":{"stage":{"type":"string","enum":["submit","status","result","download"]},"reason":{"type":"string","enum":["dns","connect_timeout","response_timeout","request_timeout","connection","tls","aborted","invalid_response","http","provider","unknown"]},"elapsed_ms":{"type":"integer","minimum":0,"description":"Длительность этапа, на котором обнаружен сбой."},"transport_code":{"type":"string","description":"Безопасный машинный код из разрешённого списка; произвольный текст ошибки не передаётся."},"http_status":{"type":"integer","minimum":100,"maximum":599}}},"CleanupReport":{"type":"object","required":["observed_at","automatic_deletion","scope","total","known_bytes","truncated","items","excluded"],"properties":{"observed_at":{"type":"string","format":"date-time"},"automatic_deletion":{"type":"boolean","enum":[false]},"scope":{"type":"string","enum":["registered_inputs_only"]},"total":{"type":"integer","minimum":0},"known_bytes":{"type":"integer","minimum":0},"truncated":{"type":"boolean"},"items":{"type":"array","maxItems":100,"items":{"type":"object","required":["id","created_at","expires_at","size_bytes","reason"],"properties":{"id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"},"size_bytes":{"type":"integer","minimum":0},"reason":{"type":"string","enum":["expired_unused_input"]}}}},"excluded":{"type":"object","required":["linked","not_expired","needs_review"],"properties":{"linked":{"type":"integer","minimum":0},"not_expired":{"type":"integer","minimum":0},"needs_review":{"type":"integer","minimum":0}}}}},"FileTotals":{"type":"object","required":["count","bytes"],"properties":{"count":{"type":"integer","minimum":0},"bytes":{"type":"integer","minimum":0}}},"BucketUsage":{"type":"object","required":["observed_at","scope","total","inputs","results","other","cached"],"properties":{"observed_at":{"type":"string","format":"date-time"},"scope":{"type":"string","enum":["current_objects_only"]},"total":{"$ref":"#/components/schemas/FileTotals"},"inputs":{"$ref":"#/components/schemas/FileTotals"},"results":{"$ref":"#/components/schemas/FileTotals"},"other":{"$ref":"#/components/schemas/FileTotals"},"cached":{"type":"boolean"}}},"StorageQuota":{"type":"object","required":["limit_bytes","used_bytes","reserved_bytes","available_bytes","over_limit_bytes","result_reservation_bytes"],"properties":{"limit_bytes":{"type":"integer","minimum":0},"used_bytes":{"type":"integer","minimum":0},"reserved_bytes":{"type":"integer","minimum":0},"available_bytes":{"type":"integer","minimum":0},"over_limit_bytes":{"type":"integer","minimum":0},"result_reservation_bytes":{"type":"integer","minimum":0}}},"StorageUsage":{"type":"object","required":["registered","bucket_scan_available","policy"],"properties":{"registered":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time"},"scope":{"type":"string","enum":["database_all_destinations"]},"total_known_bytes":{"type":"integer"},"quota":{"$ref":"#/components/schemas/StorageQuota"},"legacy_local_results_count":{"type":"integer"},"inputs":{"allOf":[{"$ref":"#/components/schemas/FileTotals"},{"type":"object","properties":{"unknown_size_count":{"type":"integer","minimum":0},"ready":{"type":"integer","minimum":0},"uploading":{"type":"integer","minimum":0},"deleting":{"type":"integer","minimum":0},"linked":{"type":"integer","minimum":0},"unused":{"type":"integer","minimum":0},"expired_unused":{"type":"integer","minimum":0},"expired_unused_bytes":{"type":"integer","minimum":0}}}]},"results":{"allOf":[{"$ref":"#/components/schemas/FileTotals"},{"type":"object","properties":{"unknown_size_count":{"type":"integer","minimum":0}}}]}}},"bucket_scan_available":{"type":"boolean"},"policy":{"type":"object","properties":{"automatic_deletion":{"type":"boolean","enum":[false]},"input_limit":{"type":"integer"},"input_eligibility_hours":{"type":"integer"},"quota_enforced":{"type":"boolean","enum":[true]}}}}},"InputFile":{"type":"object","required":["id","status","created_at","expires_at","width","height","mime_type","url"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["uploading","ready","deleting","deleted"]},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time","description":"Срок допуска к новым заданиям, не время автоматического удаления."},"width":{"type":"integer"},"height":{"type":"integer"},"representation":{"type":"string","enum":["original","legacy_prepared"]},"orientation":{"type":"integer","minimum":1,"maximum":8},"mime_type":{"type":"string","enum":["image/jpeg","image/png"]},"size_bytes":{"type":"integer"},"url":{"type":"string"}}},"ApiError":{"type":"object","required":["error","request_id"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}},"request_id":{"type":"string"}}},"Asset":{"type":"object","required":["kind","url","mime_type","width","height"],"properties":{"file_id":{"type":"string","format":"uuid","description":"ID нового результата; пока один файл на задание, совпадает с ID задания."},"kind":{"type":"string","enum":["image"]},"url":{"type":"string","description":"Относительно адреса API. Постоянный адрес: локальный SVG/JPEG или перенаправление на свежую ссылку S3. Не сохраняйте Location как постоянную ссылку."},"mime_type":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"}}},"Health":{"type":"object","properties":{"providers":{"type":"array","items":{"type":"string","enum":["fal","google"]}},"status":{"type":"string","enum":["ok","degraded"]},"provider":{"type":"string","description":"Совместимое текстовое представление; используйте массив providers."},"storage":{"type":"string","enum":["sqlite","postgres"]},"asset_storage":{"type":"string","enum":["local","s3"],"description":"Режим записи новых результатов, не проверка доступности S3."},"version":{"type":"string"}}}}}}