Генерация видео (API)
Асинхронный /v1/videos — создание, опрос статуса, скачивание mp4. Оплата в рублях по факту, хранение результата 72 часа.
/v1/videos — асинхронный API генерации видео. Вы создаёте задачу, опрашиваете её статус и, когда видео готово, скачиваете mp4. Тот же Bearer-ключ sk-gw-..., что и для остального API. Цена — в рублях, списывается по факту.
Идентификатор задачи (id), polling_url и unsigned_urls указывают только на эндпоинты Hubris (https://api.hubris.pw).
Scope ключа
POST /v1/videosтребует scopevideos:write(денежно-мутирующий — создаёт задачу и резервирует средства).GET /v1/videos/{id}иGET /v1/videos/{id}/contentтребуютvideos:read.GET /v1/videos/modelsтребуетmodels:read— тот же scope, что и обычный каталогGET /v1/models, потому что это тоже просто листинг каталога.
Полноправные ключи sk-gw- (без ограничения scope) покрывают все три. У scoped-ключей и OAuth-токенов проверьте, что нужный scope выдан на /keys.
Жизненный цикл
POST /v1/videos → 202 { id, status: "pending", polling_url }
│
▼ (опрос раз в несколько секунд)
GET /v1/videos/{id} → 200 { status: "pending" | "in_progress" | "completed" | "failed" }
│
▼ (когда status = "completed")
GET /v1/videos/{id}/content?index=0 → video/mp4 (сырые байты)Статусы наружу: pending, in_progress, completed, failed. Промежуточные внутренние состояния схлопываются в in_progress.
Создание — POST /v1/videos
https://api.hubris.pw/v1/videosОбязательны model (из каталога видео-моделей, см. GET /v1/videos/models) и prompt. Ответ — HTTP 202.
curl -s https://api.hubris.pw/v1/videos \-H "Authorization: Bearer $HUBRIS_API_KEY" \-H "Content-Type: application/json" \-d '{ "model": "kwaivgi/kling-v3.0-pro", "prompt": "Кот в скафандре катается на скейтборде по Луне", "duration": 8, "resolution": "720p", "aspect_ratio": "16:9", "generate_audio": true}'import os, requestsr = requests.post( "https://api.hubris.pw/v1/videos", headers={"Authorization": f"Bearer {os.environ['HUBRIS_API_KEY']}"}, json={ "model": "kwaivgi/kling-v3.0-pro", "prompt": "Кот в скафандре катается на скейтборде по Луне", "duration": 8, "resolution": "720p", "aspect_ratio": "16:9", "generate_audio": True, },)job = r.json()print(job["id"], job["status"])const r = await fetch("https://api.hubris.pw/v1/videos", {method: "POST",headers: { Authorization: `Bearer ${process.env.HUBRIS_API_KEY}`, "Content-Type": "application/json",},body: JSON.stringify({ model: "kwaivgi/kling-v3.0-pro", prompt: "Кот в скафандре катается на скейтборде по Луне", duration: 8, resolution: "720p", aspect_ratio: "16:9", generate_audio: true,}),});const job = await r.json();console.log(job.id, job.status);{
"id": "b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a",
"status": "pending",
"polling_url": "https://api.hubris.pw/v1/videos/b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a",
"created": 1752192000
}Опциональные поля: size ("1280x720", шорткат к resolution+aspect_ratio; при явном resolution и/или aspect_ratio они перекрывают size), seed (int, только если модель поддерживает детерминизм), frame_images[] — до двух опорных кадров, чтобы оживить картинку первым и/или последним кадром:
{
"frame_images": [
{
"type": "image_url",
"image_url": { "url": "https://example.com/frame.png" },
"frame_type": "first_frame"
}
]
}image_url.url принимает https://-ссылку (без логина/пароля в URL) или data:image/png;base64,... / data:image/jpeg;base64,... (до 10 МБ в base64). Поля callback_url и input_references в v1 не поддерживаются — запрос с ними вернёт 400 invalid_request (не молчаливый дроп).
Идемпотентность
Передайте заголовок Idempotency-Key: <ваш-ключ> — повторный POST с тем же ключом от того же аккаунта вернёт уже созданную задачу, не создавая вторую и не резервируя средства повторно. Используйте при сетевых ретраях создания.
Опрос статуса — GET /v1/videos/{id}
https://api.hubris.pw/v1/videos/{id}curl -s https://api.hubris.pw/v1/videos/b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a \
-H "Authorization: Bearer $HUBRIS_API_KEY"{
"id": "b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a",
"status": "completed",
"created": 1752192000,
"unsigned_urls": [
"https://api.hubris.pw/v1/videos/b0f2c1a4-3e9d-4b7a-9c2e-8f1a6d5c4b3a/content?index=0"
],
"usage": { "cost": 4200 }
}usage.cost— стоимость в копейках (integer), появляется только приstatus: "completed".4200= 42,00 ₽. Это итоговая сумма, списанная с баланса — не оценка.unsigned_urlsпоявляются только приstatus: "completed"и, несмотря на имя (унаследовано от формата апстрима), требуют тот же Bearer-ключ — это эндпоинты Hubris, не публичные подписанные ссылки.- При
status: "failed"приходит полеerrorс нейтральным текстом.
Пример полного цикла (bash)
ID=$(curl -s https://api.hubris.pw/v1/videos \
-H "Authorization: Bearer $HUBRIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"kwaivgi/kling-v3.0-pro","prompt":"Закат над океаном, дрон"}' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
while true; do
STATUS=$(curl -s "https://api.hubris.pw/v1/videos/$ID" \
-H "Authorization: Bearer $HUBRIS_API_KEY" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["status"])')
echo "status=$STATUS"
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && { echo "generation failed"; exit 1; }
sleep 5
done
curl -s "https://api.hubris.pw/v1/videos/$ID/content?index=0" \
-H "Authorization: Bearer $HUBRIS_API_KEY" -o result.mp4Опрашивайте не чаще раза в несколько секунд — частые повторы одного и того же GET не ускорят генерацию.
Скачивание — GET /v1/videos/{id}/content
https://api.hubris.pw/v1/videos/{id}/content?index=0Отдаёт сырые байты video/mp4. Требует Bearer-ключ и доступен только владельцу задачи. В v1 доступен единственный клип — index=0 (параметр можно не передавать, по умолчанию тот же); index больше нуля вернёт 400 index_out_of_range. Запрос до готовности видео или после истечения хранения — 404 video_not_ready.
Хранение результата — 72 часа
Готовый ролик хранится у Hubris 72 часа с момента создания задачи, затем удаляется без возможности восстановления. Скачайте и сохраните файл у себя в течение этого окна. Запрос /content после удаления вернёт 404 video_not_ready — так же, как если бы видео ещё не было готово (Hubris не палит разницу между «протухло» и «не готово»).
Каталог видео-моделей — GET /v1/videos/models
https://api.hubris.pw/v1/videos/modelscurl -s https://api.hubris.pw/v1/videos/models \
-H "Authorization: Bearer $HUBRIS_API_KEY"Возвращает { "object": "list", "data": [...] } — активные видео-модели с поддерживаемыми разрешениями, соотношениями сторон, длительностями, доступностью звука/seed/опорных кадров и ценами в рублях за единицу (секунда или видео). Видео-модели скрыты из обычного GET /v1/models — получить их там тоже можно, но отдельным запросом: GET /v1/models?output_modalities=video.
Коды ошибок
| HTTP | code | type | Когда |
|---|---|---|---|
| 400 | invalid_request | invalid_request_error | Кривой запрос, неподдерживаемая ось (длительность/разрешение/пропорции не из каталога модели), callback_url/input_references |
| 400 | index_out_of_range | invalid_request_error | index в /content вне диапазона (v1 — только index=0) |
| 402 | insufficient_balance | invalid_request_error | Недостаточно средств для резерва под задачу |
| 404 | model_not_found | invalid_request_error | Модель с таким id не видео-модель или неактивна |
| 404 | not_found | invalid_request_error | Задачи с таким id не существует или она принадлежит другому аккаунту |
| 404 | video_not_ready | invalid_request_error | /content до completed или после 72-часового TTL |
| 413 | request_too_large | invalid_request_error | Тело запроса (обычно — frame_images в base64) превышает лимит |
| 429 | too_many_active_jobs | rate_limit_error | Достигнут лимит одновременных видео-задач аккаунта |
| 502 / 504 | upstream_error | api_error | Провайдер модели не принял задачу (502) или не ответил вовремя (504) |
| 503 | exchange_rate_unavailable | api_error | Курс ЦБ РФ временно недоступен — нельзя посчитать резерв под задачу |
Полный формат ошибок и стратегия retry — на странице Ошибки.
Приватность и хранение данных
Видео-генерация выполняется на инфраструктуре внешних провайдеров моделей и не покрывается режимом Zero Data Retention: провайдеры временно хранят входные данные (промпт, кадры frame_images) и результат на своей стороне на время генерации. У Hubris готовый ролик хранится 72 часа, затем удаляется.
Privacy Mode на видео не распространяется. Автоматическое маскирование персональных данных (Privacy Mode) работает только для текстовых запросов Chat Completions; промпты и кадры видео уходят провайдеру как есть — не передавайте туда персональные данные третьих лиц.
Трансграничная передача (152-ФЗ). Если вы вызываете /v1/videos от имени своих пользователей, вы отвечаете за наличие их согласия на обработку и трансграничную передачу входов и выходов (промпты, кадры, результат) за пределы РФ, а также на 72-часовое хранение результата у Hubris. Условия использования API фиксируют это в оферте.
Hubris не логирует содержимое ваших запросов: prompt, байты видео и frame_images не попадают в логи — только метаданные (модель, стоимость, статус, латентность).
Что дальше
- Ошибки — таблица всех кодов и retry-стратегий.
- Биллинг — как считается
usage.cost. - Privacy Mode — что покрывает маскирование, а что нет.
- Студия видео в личном кабинете — тот же API под UI, без curl.
Обновлено: