curl --request GET \
--url 'https://toapis.com/v1/videos/generations/task_01K9S419324DREZFBWNSVXYR6H' \
--header 'Authorization: Bearer <token>'
import requests
import time
API_BASE = 'https://toapis.com'
API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def get_video_status(task_id):
response = requests.get(f'{API_BASE}/v1/videos/generations/{task_id}', headers=headers)
return response.json()
def wait_for_video(task_id, max_attempts=60, interval=10):
for _ in range(max_attempts):
result = get_video_status(task_id)
status = result.get('status')
progress = result.get('progress', 0)
print(f"Статус: {status}, Прогресс: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Задача не выполнена: {result}")
time.sleep(interval)
raise Exception("Таймаут задачи")
# Пример использования
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"URL видео: {result['result']['data'][0]['url']}")
const API_BASE = 'https://toapis.com';
const API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx';
async function getVideoStatus(taskId) {
const response = await fetch(`${API_BASE}/v1/videos/generations/${taskId}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
return response.json();
}
async function waitForVideo(taskId, maxAttempts = 60, interval = 10000) {
for (let i = 0; i < maxAttempts; i++) {
const result = await getVideoStatus(taskId);
const status = result.status;
const progress = result.progress || 0;
console.log(`Статус: ${status}, Прогресс: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Задача не выполнена: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Таймаут задачи');
}
// Пример использования
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('URL видео:', result.result.data[0].url);
console.log('Формат:', result.result.data[0].format);
});
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
func getVideoStatus(taskId string) (map[string]interface{}, error) {
url := fmt.Sprintf("https://toapis.com/v1/videos/generations/%s", taskId)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer <token>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
func main() {
taskId := "task_01K9S419324DREZFBWNSVXYR6H"
for i := 0; i < 60; i++ {
result, _ := getVideoStatus(taskId)
status := result["status"].(string)
progress := int(result["progress"].(float64))
fmt.Printf("Статус: %s, Прогресс: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Генерация видео завершена!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("URL видео:", videoData["url"])
break
}
time.Sleep(10 * time.Second)
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1768380222
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "in_progress",
"progress": 65,
"created_at": 1768380222
}
{
"id": "tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX",
"object": "generation.task",
"model": "seedance-2",
"status": "completed",
"progress": 100,
"created_at": 1778569600,
"finished_at": 1778569900,
"completed_at": 1778569900,
"expires_at": 1778656300,
"result": {
"type": "video",
"data": [
{
"url": "https://files.toapis.com/videos/tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX/********_********.mp4",
"format": "mp4"
}
]
},
"billing": {
"status": "settled",
"credits": "100",
"cost_usd": "0.5"
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "failed",
"progress": 0,
"created_at": 1768380222,
"error": {
"code": "generation_failed",
"message": "Генерация не удалась: Контент нарушает политику контента"
}
}
{
"error": {
"code": 404,
"message": "Задача не найдена",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API ключ",
"type": "authentication_error"
}
}
{
"id": "task_seedance_example",
"object": "generation.task",
"model": "seedance-2-global",
"client_business_id": "order_123",
"status": "completed",
"progress": 100,
"created_at": 1792400000,
"updated_at": 1792400061,
"finished_at": 1792400060,
"completed_at": 1792400060,
"expires_at": 1792486460,
"result": {
"type": "video",
"data": [
{
"url": "https://cdn.example/result.mp4",
"fallback_url": "https://files.toapis.com/videos/task_seedance_example/result.mp4",
"format": "mp4",
"last_frame_url": "https://cdn.example/last-frame.jpg",
"fallback_last_frame_url": "https://files.toapis.com/videos/task_seedance_example/last-frame.jpg"
}
]
},
"usage": {
"charge_type": "per_token",
"billed_tokens": 87300,
"completion_tokens": 87300,
"total_tokens": 87300
},
"billing": {
"status": "settled",
"credits": "87.3",
"cost_usd": "0.4365"
},
"generation": {
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": true,
"usage": {
"completion_tokens": 87300,
"total_tokens": 87300
}
}
}
Управление задачами
Получить статус задачи видео
Запрос статуса и результатов задачи генерации видео
GET
/
v1
/
videos
/
generations
/
{task_id}
curl --request GET \
--url 'https://toapis.com/v1/videos/generations/task_01K9S419324DREZFBWNSVXYR6H' \
--header 'Authorization: Bearer <token>'
import requests
import time
API_BASE = 'https://toapis.com'
API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def get_video_status(task_id):
response = requests.get(f'{API_BASE}/v1/videos/generations/{task_id}', headers=headers)
return response.json()
def wait_for_video(task_id, max_attempts=60, interval=10):
for _ in range(max_attempts):
result = get_video_status(task_id)
status = result.get('status')
progress = result.get('progress', 0)
print(f"Статус: {status}, Прогресс: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Задача не выполнена: {result}")
time.sleep(interval)
raise Exception("Таймаут задачи")
# Пример использования
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"URL видео: {result['result']['data'][0]['url']}")
const API_BASE = 'https://toapis.com';
const API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx';
async function getVideoStatus(taskId) {
const response = await fetch(`${API_BASE}/v1/videos/generations/${taskId}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
return response.json();
}
async function waitForVideo(taskId, maxAttempts = 60, interval = 10000) {
for (let i = 0; i < maxAttempts; i++) {
const result = await getVideoStatus(taskId);
const status = result.status;
const progress = result.progress || 0;
console.log(`Статус: ${status}, Прогресс: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Задача не выполнена: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Таймаут задачи');
}
// Пример использования
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('URL видео:', result.result.data[0].url);
console.log('Формат:', result.result.data[0].format);
});
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
func getVideoStatus(taskId string) (map[string]interface{}, error) {
url := fmt.Sprintf("https://toapis.com/v1/videos/generations/%s", taskId)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer <token>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
func main() {
taskId := "task_01K9S419324DREZFBWNSVXYR6H"
for i := 0; i < 60; i++ {
result, _ := getVideoStatus(taskId)
status := result["status"].(string)
progress := int(result["progress"].(float64))
fmt.Printf("Статус: %s, Прогресс: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Генерация видео завершена!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("URL видео:", videoData["url"])
break
}
time.Sleep(10 * time.Second)
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1768380222
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "in_progress",
"progress": 65,
"created_at": 1768380222
}
{
"id": "tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX",
"object": "generation.task",
"model": "seedance-2",
"status": "completed",
"progress": 100,
"created_at": 1778569600,
"finished_at": 1778569900,
"completed_at": 1778569900,
"expires_at": 1778656300,
"result": {
"type": "video",
"data": [
{
"url": "https://files.toapis.com/videos/tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX/********_********.mp4",
"format": "mp4"
}
]
},
"billing": {
"status": "settled",
"credits": "100",
"cost_usd": "0.5"
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "failed",
"progress": 0,
"created_at": 1768380222,
"error": {
"code": "generation_failed",
"message": "Генерация не удалась: Контент нарушает политику контента"
}
}
{
"error": {
"code": 404,
"message": "Задача не найдена",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API ключ",
"type": "authentication_error"
}
}
{
"id": "task_seedance_example",
"object": "generation.task",
"model": "seedance-2-global",
"client_business_id": "order_123",
"status": "completed",
"progress": 100,
"created_at": 1792400000,
"updated_at": 1792400061,
"finished_at": 1792400060,
"completed_at": 1792400060,
"expires_at": 1792486460,
"result": {
"type": "video",
"data": [
{
"url": "https://cdn.example/result.mp4",
"fallback_url": "https://files.toapis.com/videos/task_seedance_example/result.mp4",
"format": "mp4",
"last_frame_url": "https://cdn.example/last-frame.jpg",
"fallback_last_frame_url": "https://files.toapis.com/videos/task_seedance_example/last-frame.jpg"
}
]
},
"usage": {
"charge_type": "per_token",
"billed_tokens": 87300,
"completion_tokens": 87300,
"total_tokens": 87300
},
"billing": {
"status": "settled",
"credits": "87.3",
"cost_usd": "0.4365"
},
"generation": {
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": true,
"usage": {
"completion_tokens": 87300,
"total_tokens": 87300
}
}
}
Для пользователей из материкового Китая: используйте
https://toapis.cn в качестве эндпоинта (Base URL). Замените https://toapis.com на https://toapis.cn во всех примерах этого документа.- Запрос статуса выполнения и результатов асинхронной задачи генерации видео
- Обновление статуса и отслеживание прогресса в реальном времени
- Получение сгенерированных видео при завершении задачи
- Поддержка многоязычности (zh/en/ko/ja)
Видеозадачи Seedance, которым нужна проверка материалов, используют этот же API статуса.
queued может включать подготовку и ожидание проверки, а прием задачи не означает начало генерации. На подготовку по умолчанию отводится 20 минут на раунд без учета последующей генерации видео. Причина ошибки указана в error.message.GET /v1/tasks/{task_id} с теми же определениями usage и billing. Эта страница описывает ответ пути запроса генерации, указанного в начале.
Примеры показывают поля, а не текущие цены модели или постоянный способ тарификации. Используйте поля и суммы, возвращённые для конкретной задачи.
Исходные и резервные URL Seedance
Для задач Seedance с включенной передачей исходного URL полеresult.data[].url сохраняет исходный URL видео провайдера. Сначала используйте url и переключайтесь на fallback_url того же элемента результата только при недоступности основного адреса. Платформа не переключает URL автоматически в зависимости от региона клиента.
Резервные поля необязательны и возвращаются только при наличии доступной копии. Они могут отсутствовать, если передача исходного URL отключена, копия недоступна или у старой задачи нет копии. Отсутствие поля не означает ошибку генерации. Для последнего кадра сначала используйте last_frame_url, а при его недоступности используйте fallback_last_frame_url. Резервный URL не продлевает срок действия исходного URL. Для длительного хранения своевременно скачайте результат.
Авторизация
string
обязательно
Все эндпоинты требуют аутентификации Bearer TokenПолучить API ключ:Посетите Страницу управления API ключами для получения API ключаДобавьте в заголовок запроса:
Authorization: Bearer YOUR_API_KEY
Параметры пути
string
обязательно
ID задачи, возвращенный API генерации видео
curl --request GET \
--url 'https://toapis.com/v1/videos/generations/task_01K9S419324DREZFBWNSVXYR6H' \
--header 'Authorization: Bearer <token>'
import requests
import time
API_BASE = 'https://toapis.com'
API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def get_video_status(task_id):
response = requests.get(f'{API_BASE}/v1/videos/generations/{task_id}', headers=headers)
return response.json()
def wait_for_video(task_id, max_attempts=60, interval=10):
for _ in range(max_attempts):
result = get_video_status(task_id)
status = result.get('status')
progress = result.get('progress', 0)
print(f"Статус: {status}, Прогресс: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Задача не выполнена: {result}")
time.sleep(interval)
raise Exception("Таймаут задачи")
# Пример использования
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"URL видео: {result['result']['data'][0]['url']}")
const API_BASE = 'https://toapis.com';
const API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx';
async function getVideoStatus(taskId) {
const response = await fetch(`${API_BASE}/v1/videos/generations/${taskId}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
return response.json();
}
async function waitForVideo(taskId, maxAttempts = 60, interval = 10000) {
for (let i = 0; i < maxAttempts; i++) {
const result = await getVideoStatus(taskId);
const status = result.status;
const progress = result.progress || 0;
console.log(`Статус: ${status}, Прогресс: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Задача не выполнена: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Таймаут задачи');
}
// Пример использования
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('URL видео:', result.result.data[0].url);
console.log('Формат:', result.result.data[0].format);
});
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
func getVideoStatus(taskId string) (map[string]interface{}, error) {
url := fmt.Sprintf("https://toapis.com/v1/videos/generations/%s", taskId)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer <token>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
func main() {
taskId := "task_01K9S419324DREZFBWNSVXYR6H"
for i := 0; i < 60; i++ {
result, _ := getVideoStatus(taskId)
status := result["status"].(string)
progress := int(result["progress"].(float64))
fmt.Printf("Статус: %s, Прогресс: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Генерация видео завершена!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("URL видео:", videoData["url"])
break
}
time.Sleep(10 * time.Second)
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1768380222
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "in_progress",
"progress": 65,
"created_at": 1768380222
}
{
"id": "tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX",
"object": "generation.task",
"model": "seedance-2",
"status": "completed",
"progress": 100,
"created_at": 1778569600,
"finished_at": 1778569900,
"completed_at": 1778569900,
"expires_at": 1778656300,
"result": {
"type": "video",
"data": [
{
"url": "https://files.toapis.com/videos/tsk_vid_01KRDG4S50XXXXXXXXXXXXXXX/********_********.mp4",
"format": "mp4"
}
]
},
"billing": {
"status": "settled",
"credits": "100",
"cost_usd": "0.5"
}
}
{
"id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
"object": "generation.task",
"model": "sora-2",
"status": "failed",
"progress": 0,
"created_at": 1768380222,
"error": {
"code": "generation_failed",
"message": "Генерация не удалась: Контент нарушает политику контента"
}
}
{
"error": {
"code": 404,
"message": "Задача не найдена",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API ключ",
"type": "authentication_error"
}
}
{
"id": "task_seedance_example",
"object": "generation.task",
"model": "seedance-2-global",
"client_business_id": "order_123",
"status": "completed",
"progress": 100,
"created_at": 1792400000,
"updated_at": 1792400061,
"finished_at": 1792400060,
"completed_at": 1792400060,
"expires_at": 1792486460,
"result": {
"type": "video",
"data": [
{
"url": "https://cdn.example/result.mp4",
"fallback_url": "https://files.toapis.com/videos/task_seedance_example/result.mp4",
"format": "mp4",
"last_frame_url": "https://cdn.example/last-frame.jpg",
"fallback_last_frame_url": "https://files.toapis.com/videos/task_seedance_example/last-frame.jpg"
}
]
},
"usage": {
"charge_type": "per_token",
"billed_tokens": 87300,
"completion_tokens": 87300,
"total_tokens": 87300
},
"billing": {
"status": "settled",
"credits": "87.3",
"cost_usd": "0.4365"
},
"generation": {
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": true,
"usage": {
"completion_tokens": 87300,
"total_tokens": 87300
}
}
}
Ответ
string
Уникальный идентификатор задачи
string
Необязательный бизнес-ID клиента, возвращается только при передаче
client_business_id во время создания задачи.string
Тип объекта, всегда
generation.taskstring
Статус задачи
queued- Отправлена, ожидает обработкиin_progress- Обрабатываетсяcompleted- Успешно завершеноfailed- Ошибка
integer
Прогресс задачи в процентах (0-100)
string
Используемая модель генерации видео
integer
Необязательное время обновления задачи на платформе, Unix timestamp. Сейчас возвращается для Seedance Global.
generation.updated_at - время обновления у поставщика.integer
Время создания задачи (Unix timestamp)
integer
Время окончания задачи, Unix timestamp. Этот путь запроса возвращает его для успешных и неуспешных задач, если время окончания сохранено.
integer
Время завершения задачи (Unix timestamp, возвращается только при завершении)
object
Результат задачи (возвращается только при успехе)
Показать Свойства
Показать Свойства
string
Тип результата, всегда
videoarray
Массив данных видео
Показать Элемент массива
Показать Элемент массива
string
Основной URL видео. Для задач Seedance с включенной передачей исходного URL сохраняется исходный адрес провайдера. Используйте его в первую очередь.
string
Необязательный резервный URL видео, возвращаемый только при наличии доступной копии. Используйте при недоступности основного адреса. Не заменяет
url.string
Формат видео (например
mp4)string
URL изображения последнего кадра. Возвращается только для задач с
return_last_frame: true, если модель предоставила кадр.string
Необязательный резервный URL последнего кадра, возвращаемый при наличии доступной копии. Используйте только при недоступности
last_frame_url.object
Необязательные метаданные генерации Seedance. Возвращаются только сохранённые публичные поля без подстановки значений по умолчанию. Эти параметры описывают генерацию и не заменяют оплачиваемые количества в
usage верхнего уровня.| Поле | Тип | Описание |
|---|---|---|
created_at, updated_at | number | Время создания и обновления задачи у поставщика, Unix timestamp; отличается от времени платформы на верхнем уровне |
seed | number | Начальное значение генератора случайных чисел |
resolution | string | Разрешение |
ratio | string | Соотношение сторон |
duration | number | Длительность генерации в секундах |
framespersecond | number | Кадров в секунду |
service_tier | string | Уровень обслуживания |
execution_expires_after | number | Срок выполнения в секундах |
generate_audio | boolean | Генерируется ли аудио |
draft | boolean | Является ли результат черновиком |
priority | number | Приоритет выполнения |
output_format | string | Формат вывода |
generation.usage - существующее поле совместимости с возможными completion_tokens и total_tokens. Оно может отсутствовать или отличаться от окончательного оплачиваемого количества. Не складывайте его с usage верхнего уровня; для оплачиваемых количеств используйте верхний usage.object
Необязательные оплачиваемые количества, токены видео и счётчики инструментов. Единицы и условия пропуска описаны в разделе Поля использования задачи.
Поля от
| Поле | Тип | Значения |
|---|---|---|
charge_type | string | Способ тарификации: per_request - за запрос, per_second - за секунды, per_token - за токены |
requests | integer | Количество оплачиваемых запросов, возвращается для per_request. Учитывается эффективный batch_size видео Midjourney |
billed_tokens | integer | Токены, использованные для расчёта цены, возвращаются для per_token |
output_seconds | integer | Оплачиваемая длительность выходного видео в целых секундах, возвращается для per_second |
input_seconds | integer | Оплачиваемая длительность входного видео в целых секундах; при нуле пропускается |
input_images | integer | Оплачиваемые входные изображения после вычета бесплатной квоты; при нуле пропускается |
input_tokens, output_tokens, prompt_tokens, completion_tokens, total_tokens | integer | Токены, сообщённые видеомоделью, в том виде, как их предоставил поставщик; при расчёте по токенам total_tokens может быть дополнен |
tool_usage | object | Счётчики инструментов: web_search, image_search, grounding_queries; возвращаются при фактическом использовании |
charge_type до input_images - это оплачиваемые количества, они возвращаются только вместе с billing.status=settled. Видео с фиксированной ценой возвращают количества, подтверждённые при отправке; видео, рассчитываемые по фактической длительности или токенам, возвращают итоговые расчётные количества. Не возвращённые поля пропускаются и не заменяются нулями.object
Необязательный статус тарификации платформы и подтверждённая сумма. Статус тарификации не зависит от статуса генерации;
Поле
completed не гарантирует, что расчёт завершён. Отсутствие объекта не означает бесплатную задачу. См. Цены и фактические списания.Показать Свойства
Показать Свойства
string
pending: идёт генерация, ожидается расчёт или возврат ещё не подтверждён; суммы пропускаются. settled: итоговое списание подтверждено, включая видео с фиксированной ценой, списанной целиком при отправке, и возвращается фактическая сумма. refunded: средства возвращены или после сбоя подтверждено отсутствие итогового списания; обе суммы равны "0".string
Фактически списанные ToAPIs Credits в виде десятичной строки. Возвращается только для
settled или refunded.string
Сумма того же списания в USD в виде десятичной строки. Возвращается при тех же условиях, что и
credits; включает скидки и множители и не является себестоимостью у поставщика.data.billing в Task Webhook использует те же условия подтверждения и значения.integer
Время истечения URL видео (Unix timestamp)
object
Информация об ошибке (только при неудаче)Коды ошибок и сообщения обычно являются строками. Seedance Global сохраняет исходные JSON-значения поставщика в
error.code и error.message, включая числа или null. Отсутствующие поля не заменяются значениями платформы по умолчанию.Справка по статусам задач
| Статус | Описание | Финальный | Рекомендуемое действие |
|---|---|---|---|
queued | Задача отправлена, ожидает в очереди | ❌ | Подождите 5-10 секунд и повторите запрос |
in_progress | Задача обрабатывается | ❌ | Подождите 10-15 секунд и повторите запрос |
completed | Задача успешно завершена | ✅ | Получите видео из result.data[0].url |
failed | Обработка задачи не удалась | ✅ | Проверьте информацию об ошибке |
Стратегия опроса
Начальное ожидание: 5 секунд
Интервал опроса: 10 секунд
Максимальное ожидание: 600 секунд (10 минут)
Типичное время: 1-5 минут
Пример опроса на Python
import time
import random
import requests
def poll_video_task(task_id, api_key, max_wait=600):
"""Опрос задачи генерации видео до завершения или таймаута"""
start_time = time.time()
interval = 10 # Интервал 10 секунд
# Начальное ожидание 5 секунд
time.sleep(5)
while time.time() - start_time < max_wait:
response = requests.get(
f'https://toapis.com/v1/videos/generations/{task_id}',
headers={'Authorization': f'Bearer {api_key}'}
)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', interval))
time.sleep(retry_after + random.uniform(0, 1))
interval = min(interval * 2, 120)
continue
response.raise_for_status()
data = response.json()
print(f"Статус: {data['status']}, Прогресс: {data.get('progress', 0)}%")
if data['status'] == 'completed':
return {
'url': data['result']['data'][0]['url'],
'format': data['result']['data'][0].get('format'),
'expires_at': data.get('expires_at')
}
elif data['status'] == 'failed':
raise Exception(f"Генерация не удалась: {data['error']['message']}")
time.sleep(interval + random.uniform(0, 1))
raise TimeoutError("Таймаут задачи")
Срок действия ресурсов
URL сгенерированных видео действительны 24 часа
- Загрузите и сохраните видео в течение срока действия
- Поле
expires_atуказывает время истечения видео (Unix timestamp) - После истечения срока видео недоступны; для повторного получения отправьте новую задачу
- Превью истекает одновременно с видео
Ошибки и причины сбоя
Ошибки запросов, причины сбоя задач и восстановление описаны в справочнике ошибок. После успешной проверки учитывайте статус задачи; HTTP-статус не является бизнес-кодом ошибки.Советы по производительности
Генерация видео занимает больше времени, рекомендации:
- Используйте ToAPIs Task Webhook: Webhook — основной канал, polling — резерв
- Интервал polling: не менее 5–10 секунд с jitter; при 429 соблюдайте
Retry-Afterи exponential backoff - Установите таймаут: Длинные видео могут занимать 5-10 минут, установите разумный таймаут
- Загружайте своевременно: Видео истекают через 24 часа, обязательно сохраните в своё хранилище немедленно