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: {status}, Progress: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Task failed: {result}")
time.sleep(interval)
raise Exception("Task timeout")
# Usage example
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"Video 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: ${status}, Progress: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Task failed: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Task timeout');
}
// Usage example
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('Video URL:', result.result.data[0].url);
console.log('Format:', 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("Status: %s, Progress: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Video generation completed!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("Video 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,
"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": "Generation failed: Content violates the content policy"
}
}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
작업 관리
Get Video Task 상태
Query video generation task status and results
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: {status}, Progress: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Task failed: {result}")
time.sleep(interval)
raise Exception("Task timeout")
# Usage example
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"Video 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: ${status}, Progress: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Task failed: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Task timeout');
}
// Usage example
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('Video URL:', result.result.data[0].url);
console.log('Format:', 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("Status: %s, Progress: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Video generation completed!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("Video 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,
"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": "Generation failed: Content violates the content policy"
}
}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
중국 본토 사용자 안내: 중국 본토 사용자는
https://toapis.cn 를 API 엔드포인트(Base URL)로 사용해 주세요. 본 문서의 예시에서 https://toapis.com 을 https://toapis.cn 로 바꿔 주세요.- Query async video generation task execution status and results
- Real-time status updates and progress tracking
- Get generated videos when task completes
- Multi-language support (zh/en/ko/ja)
요청 시 소재 심사를 사용하는 동영상 작업도 이 API로 조회합니다.
queued에는 소재 준비와 심사 대기가 포함될 수 있으며, 작업 접수가 생성 시작을 뜻하지는 않습니다. 준비 기한은 기본 라운드당 20분이며 이후 동영상 생성 시간은 별도입니다. 실패 시 error.message를 확인하세요. 기존 소재 API를 따로 폴링할 필요는 없습니다.Authorizations
string
필수
All endpoints require Bearer Token authenticationGet your API Key:Visit the API Key Management Page to get your API KeyAdd it to the request header:
Authorization: Bearer YOUR_API_KEY
Path 파라미터
string
필수
Task ID returned by the video generation 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: {status}, Progress: {progress}%")
if status == 'completed':
return result
elif status == 'failed':
raise Exception(f"Task failed: {result}")
time.sleep(interval)
raise Exception("Task timeout")
# Usage example
task_id = "task_01K9S419324DREZFBWNSVXYR6H"
result = wait_for_video(task_id)
print(f"Video 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: ${status}, Progress: ${progress}%`);
if (status === 'completed') {
return result;
} else if (status === 'failed') {
throw new Error(`Task failed: ${JSON.stringify(result)}`);
}
await new Promise(r => setTimeout(r, interval));
}
throw new Error('Task timeout');
}
// Usage example
const taskId = 'task_01K9S419324DREZFBWNSVXYR6H';
waitForVideo(taskId).then(result => {
console.log('Video URL:', result.result.data[0].url);
console.log('Format:', 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("Status: %s, Progress: %d%%\n", status, progress)
if status == "completed" {
fmt.Println("Video generation completed!")
resultData := result["result"].(map[string]interface{})
dataArray := resultData["data"].([]interface{})
videoData := dataArray[0].(map[string]interface{})
fmt.Println("Video 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,
"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": "Generation failed: Content violates the content policy"
}
}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
응답
string
Unique task identifier
string
Object type, always
generation.taskstring
Task status
queued- Queued for processingin_progress- Processingcompleted- Successfully completedfailed- Failed
integer
Task progress percentage (0-100)
string
Video generation model used
integer
Task creation time (Unix timestamp)
integer
Task completion time (Unix timestamp, only returned when completed)
integer
Video URL expiration time (Unix timestamp, only returned on completion)
object
object
모델 도구 사용량입니다. Seedance 2에서
tools: [{ "type": "web_search" }]를 사용하면 usage.tool_usage.web_search에 실제 검색 횟수가 반환되며, 0은 검색하지 않았음을 의미합니다.object
선택적인 플랫폼 청구 상태와 확정 금액입니다.
status는 pending, settled, refunded 중 하나입니다. credits와 cost_usd는 10진수 문자열이며 순 청구 금액이 확정된 경우에만 반환됩니다. 객체가 없다고 해서 무료인 것은 아닙니다. 가격 및 실제 청구 금액을 참고하세요.Task 상태 Reference
| 상태 | 설명 | Is Final | Recommended Action |
|---|---|---|---|
queued | Task submitted, waiting in queue | ❌ | Wait 5-10 seconds, then query again |
in_progress | Task is processing | ❌ | Wait 10-15 seconds, then query again |
completed | Task completed successfully | ✅ | Get video from result.data[0].url |
failed | Task processing failed | ✅ | Check error info |
Polling Strategy
Initial wait: 5 seconds
Polling interval: 10 seconds
Max wait: 600 seconds (10 minutes)
Typical time: 1-5 minutes
Python Polling Example
import time
import random
import requests
def poll_video_task(task_id, api_key, max_wait=600):
"""Poll video generation task until completion or timeout"""
start_time = time.time()
interval = 10 # 10 second interval
# Initial 5 second wait
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"Status: {data['status']}, Progress: {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"Generation failed: {data['error']['message']}")
time.sleep(interval + random.uniform(0, 1))
raise TimeoutError("Task timeout")
Resource Expiration
Generated video URLs are valid for 24 hours
- Please download and save videos within the validity period
expires_atfield indicates video expiration time (Unix timestamp)- Expired videos cannot be accessed; to regenerate, submit a new task
- Thumbnails expire simultaneously with videos
오류 Codes
| HTTP Code | 오류 Type | 설명 |
|---|---|---|
| 400 | invalid_request | Invalid request parameters |
| 401 | unauthorized | 인증 failed, check API Key |
| 402 | insufficient_quota | Insufficient balance |
| 404 | task_not_found | Task not found |
| 422 | content_policy_violation | Content policy violation |
| 429 | rate_limit_exceeded | Rate limit exceeded |
| 500 | internal_error | Internal server error |
Performance Tips
Video generation takes longer, recommendations:
- ToAPIs Task Webhook: Webhook을 기본으로, 조회를 대체 경로로 사용
- 조회 간격: 5~10초 이상과 지터. 429는
Retry-After를 읽고 지수 백오프 - Set Timeout: Long videos may take 5-10 minutes, set reasonable timeout
- Download Promptly: Videos expire after 24 hours, save to your storage immediately