API Окна: говорящий аватар по фото и звуку
Тот же функционал, что в интерфейсе: загрузить портрет и звук, собрать заказ, следить за очередью, забрать видео. Оплата — с баланса аккаунта в кредитах.
Загрузка файлов
Сначала загрузите портрет и звук — получите id загрузок. Картинка до 10 МБ (JPG, PNG, WebP; от 128 до 8192 пикселей по стороне, пропорции от 1:4 до 4:1), звук до 25 МБ и до 60 сек (WAV, MP3, M4A). Загрузка без заказа хранится 24 часа; один id можно указать в нескольких роликах.
curl https://api.okno.tools/v1/uploads \
-H "Authorization: Bearer $OKNO_KEY" \
-F kind=audio -F file=@news_1002.mp3
→ 200
{ "id": "up_8Jq2…", "kind": "audio", "name": "news_1002.mp3", "size": 227244, "duration_seconds": 14.2 }Расчёт стоимости
То же тело, что у создания заказа, но ничего не списывает: сколько секунд и кредитов уйдёт и хватает ли баланса.
→ 200
{ "total_seconds": 15, "billed_seconds": 20, "cost_credits": 800,
"balance_credits": 1240, "enough": true, "min_order_seconds": 20,
"clips": [ { "duration_seconds": 15, "cost_credits": 800 } ] }Создать заказ
Передайте один или несколько роликов — все ролики заказа обрабатываются одним пакетом. 720p — 40 кредитов за секунду звука, 480p — 28. Сумма длительностей меньше 20 сек списывается как 20 сек. Кредиты резервируются сразу; за ролик, который не сгенерировался, возвращаются.
Для одного ролика можно не загружать файлы заранее: multipart/form-data с файлами image и audio и полями resolution, prompt, negative_prompt, seed, webhook_url, speed.
curl https://api.okno.tools/v1/avatars/orders \
-H "Authorization: Bearer $OKNO_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c…" \
-d '{
"clips": [
{ "image": "up_Hx41…", "audio": "up_8Jq2…", "resolution": "720p", "seed": 829104 }
]
}'
→ 202
{ "order": { "id": 1042, "status": "active", "stage": "queued", "queue_position": 1,
"total_seconds": 15, "billed_seconds": 20, "cost_credits": 800, "cancellable": true,
"clips": [ { "id": 5121, "status": "queued", "progress": 0, … } ] } }Статус заказа
stage: queued → generating → done. status заказа: active, затем done, partial (часть роликов не удалась) или failed. У ролика status: queued, processing, done или failed; progress 0–100, eta_seconds — оценка до готовности. Когда ролик готов — video_url и expires_at: видео хранится 7 дней. Опрашивать раз в 10–30 секунд или ждать вебхук.
→ 200
{ "order": { "id": 1042, "status": "active", "stage": "generating",
"clips": [
{ "id": 5121, "status": "processing", "progress": 64, "eta_seconds": 180, … },
{ "id": 5122, "status": "queued", "progress": 0, … }
] } }Список заказов
Заказы аккаунта, новые сверху. Если есть ещё, в ответе next — передайте его в before для следующей страницы.
curl "https://api.okno.tools/v1/avatars/orders?limit=20" \
-H "Authorization: Bearer $OKNO_KEY"
→ 200
{ "orders": [ { "id": 1042, "status": "done", … } ], "next": 1023 }Отмена заказа
Пока заказ ждёт в очереди (cancellable: true), его можно отменить — резерв вернётся на баланс. Когда генерация началась — 409 not_cancellable.
→ 200
{ "order": { "id": 1042, "status": "failed", "refunded_credits": 800,
"clips": [ { "id": 5121, "status": "failed", "cancelled": true, … } ] } }Смена приоритета заказа
Пока генерация заказа не началась (speed_changeable: true), приоритет можно сменить. При повышении доплата резервируется на балансе (не хватает — 402 insufficient_balance), при понижении разница возвращается. Когда генерация началась — 409 speed_not_changeable.
curl https://api.okno.tools/v1/avatars/orders/1042/speed \
-H "Authorization: Bearer $OKNO_KEY" \
-H "Content-Type: application/json" \
-d '{ "speed": 2 }'
→ 200
{ "order": { "id": 1042, "speed": 2, "speed_changeable": true, "queue_position": 1, … } }Ролик и скачивание
Статус одного ролика. Само видео — GET /avatars/clips/{id}/download с тем же ключом: MP4, поддерживается Range. До готовности — 409 not_ready, после срока хранения — 410 expired.
→ 200
{ "clip": { "id": 5121, "order_id": 1042, "status": "done", "progress": 100,
"image": "up_Hx41…", "audio": "up_8Jq2…", "resolution": "720p", "seed": 829104,
"duration_seconds": 15, "cost_credits": 800,
"video_url": "https://api.okno.tools/v1/avatars/clips/5121/download", "expires_at": "2026-10-18T12:04:31Z" } }
curl -L -o 5121.mp4 https://api.okno.tools/v1/avatars/clips/5121/download \
-H "Authorization: Bearer $OKNO_KEY"Вебхуки
Если указан webhook_url (в запросе или в кабинете), по завершении заказа мы отправим POST с заказом в том же виде, что GET /avatars/orders/{id}. Подпись — в заголовке X-Okno-Signature: sha256= и HMAC-SHA256 тела секретом из кабинета; сравнивайте с подписью сырого тела. Ответьте 2xx; иначе повторим через 30 сек и через 2 мин. Запросы приходят с IP 82.202.173.145 — его можно внести в список разрешённых.
X-Okno-Signature: sha256=5d41402abc4b2a76b9719d911017c592…
{ "event": "order.finished",
"order": { "id": 1042, "status": "done",
"clips": [ { "id": 5121, "status": "done", "video_url": "https://api.okno.tools/v1/avatars/clips/5121/download", … } ] } }Баланс
Свободные кредиты, зарезервированные под незавершённые заказы, и действующие тарифы за секунду звука.
→ 200
{ "balance_credits": 1240, "held_credits": 0,
"rates": { "avatars": { "720p": 40, "480p": 28 } },
"min_order_seconds": 20, "max_clip_seconds": 60, "results_ttl_days": 7,
"speeds": [1, 1.5, 2] }Ошибки
Ответ с ошибкой: {"error": {"code", "message", "details"}}. message — по Accept-Language (ru или en), details.clip — номер ролика в clips[] с ошибкой. Ориентируйтесь на code.