Получение статуса задачи видео
После отправки задачи через Создание задачи генерации видео опрашивайте GET /v1/video/generations/{task_id}, пока задача не достигнет конечного состояния, затем скачайте видео с GET /v1/videos/{task_id}/content. Опрос читает запись, которую RouteAPI обновляет в фоне, поэтому интервала в 10–15 секунд достаточно.
Получение записи задачи
Section titled “Получение записи задачи”GET /v1/video/generations/{task_id}Задачи привязаны к пользователю API Key: task_id, принадлежащий другому аккаунту, сообщается как task_not_exist.
curl https://api.routeapi.ai/v1/video/generations/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV \ -H "Authorization: Bearer $ROUTEAPI_KEY"{ "code": "success", "message": "", "data": { "id": 4512, "created_at": 1792048450, "updated_at": 1792048569, "task_id": "task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV", "platform": "54", "user_id": 1024, "group": "default", "channel_id": 18, "quota": 123456, "action": "generate", "status": "SUCCESS", "progress": "100%", "fail_reason": "", "result_url": "https://...mp4", "submit_time": 1792048458, "start_time": 1792048461, "finish_time": 1792048569, "properties": { "input": "", "origin_model_name": "seedance-2.0-fast" }, "data": { "id": "cgt-xxxxxxxx", "status": "succeeded" } }}Поля записи задачи
Section titled “Поля записи задачи”| Поле | Описание |
|---|---|
code | "success" для читаемой задачи; при ошибке используется формат ошибки задачи, описанный ниже |
data.id | Внутренний ID строки; нигде в запросах не используется |
data.task_id | ID задачи RouteAPI — значение для опроса и скачивания |
data.status | NOT_START, SUBMITTED, QUEUED, IN_PROGRESS, SUCCESS или FAILURE |
data.progress | Строка прогресса, например "30%" или "100%" |
data.result_url | URL видео после успешного завершения. Может указывать на эндпоинт скачивания RouteAPI или напрямую на URL вышестоящего сервиса с ограниченным сроком жизни |
data.fail_reason | Причина сбоя; в остальных случаях пусто |
data.submit_time / start_time / finish_time | Unix-секунды. start_time и finish_time равны 0 до начала и завершения |
data.created_at / updated_at | Unix-секунды, время создания и последнего обновления строки |
data.quota | Квота, списанная за задачу |
data.platform | Числовой тип канала вышестоящего сервиса, выполнившего задачу |
data.group / data.channel_id / data.user_id | Группа биллинга, канал и аккаунт-владелец. Полезно при обращении в поддержку |
data.action | Тип задачи: generate, textGenerate, firstTailGenerate, referenceGenerate или remixGenerate |
data.properties | Сохранённые свойства: origin_model_name, upstream_model_name, а в input — снимок запроса к вышестоящему сервису, если адаптер его собирает. Для диагностики |
data.data | Последняя полезная нагрузка задачи от вышестоящего поставщика, сохранена для отладки. Её форма зависит от поставщика |
Статусы
Section titled “Статусы”| Статус | Значение | Что делать |
|---|---|---|
NOT_START | Строка создана, но вышестоящий сервис ещё не опрашивался | Продолжать опрос |
SUBMITTED / QUEUED | Принята, ожидает в очереди поставщика | Продолжать опрос |
IN_PROGRESS | Идёт генерация | Продолжать опрос |
SUCCESS | Конечный успех | Скачать видео |
FAILURE | Конечная ошибка | Прочитать fail_reason; зарезервированная сумма уже возвращена |
Только SUCCESS — конечный успех; FAILURE — конечная ошибка, и при её появлении зарезервированная сумма уже возвращена. Всё остальное означает, что нужно продолжать опрос.
Пример опроса
Section titled “Пример опроса”import osimport timeimport requests
BASE = "https://api.routeapi.ai"HEADERS = {"Authorization": f"Bearer {os.environ['ROUTEAPI_KEY']}"}
task_id = requests.post( f"{BASE}/v1/video/generations", headers=HEADERS, json={ "model": "seedance-2.0-fast", "prompt": "An orange cat stretching on a windowsill at sunrise", "duration": 5, "resolution": "720p", "ratio": "16:9", }, timeout=60,).json()["task_id"]
while True: task = requests.get(f"{BASE}/v1/video/generations/{task_id}", headers=HEADERS, timeout=30).json()["data"] print(task["status"], task["progress"])
if task["status"] == "SUCCESS": video = requests.get(f"{BASE}/v1/videos/{task_id}/content", headers=HEADERS, timeout=300) video.raise_for_status() with open(f"{task_id}.mp4", "wb") as f: f.write(video.content) break if task["status"] == "FAILURE": raise SystemExit(f"task failed: {task['fail_reason']}")
time.sleep(15)Полный пример на shell
Section titled “Полный пример на shell”#!/usr/bin/env bashset -euo pipefail: "${ROUTEAPI_KEY:?set ROUTEAPI_KEY first}"BASE="${ROUTEAPI_BASE:-https://api.routeapi.ai}"AUTH="Authorization: Bearer $ROUTEAPI_KEY"
TASK_ID=$(curl -sS -X POST "$BASE/v1/video/generations" \ -H "$AUTH" -H "Content-Type: application/json" \ -d '{"model":"seedance-2.0-fast","prompt":"An orange cat stretching on a windowsill at sunrise","duration":4,"resolution":"480p","ratio":"16:9"}' \ | jq -er .task_id)
echo "task: $TASK_ID"
for _ in $(seq 1 60); do RESP=$(curl -sS "$BASE/v1/video/generations/$TASK_ID" -H "$AUTH") STATUS=$(echo "$RESP" | jq -r .data.status) echo "status: $STATUS $(echo "$RESP" | jq -r .data.progress)"
case "$STATUS" in SUCCESS) curl -sSL -o "$TASK_ID.mp4" "$BASE/v1/videos/$TASK_ID/content" -H "$AUTH" echo "saved $TASK_ID.mp4" exit 0 ;; FAILURE) echo "failed: $(echo "$RESP" | jq -r .data.fail_reason)" exit 1 ;; esac
sleep 15done
echo "timed out waiting for the task"exit 1Опрос GET /v1/video/generations/{task_id} обычно лишь читает локальную запись задачи, поэтому держите интервал 10–15 секунд и не нагружайте эндпоинт запросами без паузы.
Скачивание видео
Section titled “Скачивание видео”GET /v1/videos/{task_id}/contentПотоково передаёт байты видео через RouteAPI, поэтому вызывающей стороне не нужно обращаться к хранилищу поставщика. Ответ содержит Cache-Control: public, max-age=86400 и Content-Type вышестоящего сервиса (по умолчанию video/mp4 для встроенных Base64-результатов).
curl -L -o out.mp4 \ https://api.routeapi.ai/v1/videos/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV/content \ -H "Authorization: Bearer $ROUTEAPI_KEY"Этот маршрут принимает API Key или сессию консоли и возвращает данные только задач, принадлежащих вызывающей стороне. Его ошибки используют объектную форму {"error": {"message": "...", "type": "..."}}:
| Статус | Значение |
|---|---|
| 400 | Задача ещё не завершена; сообщение содержит текущий статус |
| 404 | Задача неизвестна или принадлежит другому аккаунту |
| 403 | Полученный URL видео отклонён правилами защиты исходящих запросов |
| 500 | Не удалось прочитать строку задачи или её канал, либо разобрать URL видео |
| 502 | Поставщик недоступен, вернул статус, отличный от 200, или URL видео пуст |
Ошибки
Section titled “Ошибки”| Статус | Код | Значение |
|---|---|---|
| 400 | task_not_exist | task_id неизвестен или принадлежит другому аккаунту |
| 500 | get_task_failed | RouteAPI не смог прочитать собственную строку задачи |
| 500 | marshal_response_failed, copy_response_body_failed | RouteAPI не смог сериализовать или записать ответ |
Запросы, отклонённые до маршрутизации, используют стандартное тело ошибки middleware {"error": {"message": ..., "type": "error", "code": ...}}, а не формат задачи.
Что дальше
Section titled “Что дальше”- Создание задачи генерации видео — отправка задачи и общая структура запроса.
- Формат видео OpenAI — диалект
/v1/videosтой же задачи сremix. - Материалы (Assets) —
404от API материалов означает, что у аккаунта ещё нет пространства материалов. - Частые ошибки — коды состояния, общие для всех эндпоинтов моделей.