> ## Documentation Index
> Fetch the complete documentation index at: https://docs.toapis.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 获取视频任务状态

> 查询视频生成任务的状态和结果

> [!NOTE]
>
> **国内用户请注意：** 中国大陆用户请使用 `https://toapis.cn` 作为接口地址（Base URL）。文档示例中的 `https://toapis.com` 请替换为 `https://toapis.cn`。

* 查询异步视频生成任务的执行状态和结果
* 实时状态更新和进度跟踪
* 任务完成时获取生成的视频
* 支持多语言返回（zh/en/ko/ja）

所有视频生成任务都是异步执行的。提交任务后，您需要通过查询接口获取任务状态和结果。

> [!NOTE]
>
> Seedance 视频任务需要[素材审核](https://docs.toapis.com/docs/cn/api-reference/videos/seedance-2/generation.md)时也通过本接口查询. `queued` 可能包含素材准备和审核等待, 返回任务不表示视频已经开始生成. 默认每轮准备期限为 20 分钟, 后续视频生成另计; 失败原因查看 `error.message`.

普通图片和视频任务也可通过 `GET /v1/tasks/{task_id}` 查询, `usage` 和 `billing` 采用相同口径. 本页描述的是页首生成任务查询路径的响应.

以下样例用于展示字段, 不代表模型的当前价格或固定计费方式. 实际字段和金额以本次任务返回为准.

## Seedance 原始地址与备用地址

启用原始地址交付的 Seedance 任务, `result.data[].url` 保留上游原始视频 URL. 客户端应优先使用 `url`, 只有该地址无法访问时才切换到同一结果项的 `fallback_url`. 平台不会根据客户端所在地区自动切换地址.

备用字段均为可选: 只有副本准备成功时才返回. 未启用原始地址交付, 备用副本不可用或历史任务没有副本时, 字段可能缺省; 缺省不表示生成失败. 尾帧同样优先使用 `last_frame_url`, 不可访问时再使用 `fallback_last_frame_url`. 备用地址不延长原始 URL 的有效期, 需要长期保存时请及时下载.

## 创建任务时传入业务 ID

创建视频任务时，可以在请求体顶层传入 `client_business_id`。该字段用于保存您系统内的订单号、流水号或业务任务 ID，方便后续按业务 ID 查询生成结果。

```json theme={null}
{
  "model": "sora-2",
  "client_business_id": "order_20260428_002",
  "prompt": "海浪拍打着海岸",
  "duration": 15,
  "aspect_ratio": "16:9"
}
```

也兼容放在 `metadata.client_business_id` 中，但推荐使用顶层字段。

## Authorizations

**Authorization** `string` *required*

所有接口均需要使用 Bearer Token 进行认证

获取 API Key：

访问 [API Key 管理页面](https://toapis.com/console/token) 获取您的 API Key

使用时在请求头中添加：

```
Authorization: Bearer YOUR_API_KEY
```

## Path Parameters

**task\_id** `string` *required*

视频生成 API 返回的任务 ID。也可以传创建任务时提交的 `client_business_id`，用于按客户侧业务 ID 查询任务状态和结果。

> [!NOTE]
>
> 如果创建视频任务时传入 `client_business_id`，可直接使用同一个状态查询接口：
> `GET /v1/videos/generations/{client_business_id}`。业务 ID 会限定在当前 API Key 所属用户下查询。

```bash cURL theme={null}
curl --request GET \
  --url 'https://toapis.com/v1/videos/generations/task_01K9S419324DREZFBWNSVXYR6H' \
  --header 'Authorization: Bearer <token>'
```

```python Python theme={null}
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 = "video_7497f4d5-3a88-44c7-923a-967fa7d941a0"
result = wait_for_video(task_id)
print(f"视频URL: {result['result']['data'][0]['url']}")
```

```javascript JavaScript theme={null}
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 = 'video_7497f4d5-3a88-44c7-923a-967fa7d941a0';
waitForVideo(taskId).then(result => {
  console.log('视频URL:', result.result.data[0].url);
  console.log('格式:', result.result.data[0].format);
});
```

```go Go theme={null}
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 := "video_7497f4d5-3a88-44c7-923a-967fa7d941a0"
    
    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)
    }
}
```

```json 200 - 排队中 theme={null}
{
  "id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
  "object": "generation.task",
  "model": "sora-2",
  "status": "queued",
  "progress": 0,
  "created_at": 1768380222
}
```

```json 200 - 处理中 theme={null}
{
  "id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
  "object": "generation.task",
  "model": "sora-2",
  "status": "in_progress",
  "progress": 65,
  "created_at": 1768380222
}
```

```json 200 - 已完成 theme={null}
{
  "id": "video_7497f4d5-3a88-44c7-923a-967fa7d941a0",
  "client_business_id": "order_20260428_001",
  "object": "generation.task",
  "model": "sora-2",
  "status": "completed",
  "progress": 100,
  "created_at": 1768380222,
  "finished_at": 1768380514,
  "completed_at": 1768380514,
  "expires_at": 1768466914,
  "result": {
    "type": "video",
    "data": [
      {
        "url": "https://files.toapis.com/sora/7712af45-ca35-4a15-b800-f20ea623665b.mp4",
        "format": "mp4"
      }
    ]
  },
  "billing": {
    "status": "settled",
    "credits": "100",
    "cost_usd": "0.5"
  }
}
```

```json 200 - 失败 theme={null}
{
  "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": "生成失败: 内容违反了内容政策"
  }
}
```

```json 404 theme={null}
{
  "error": {
    "code": 404,
    "message": "任务不存在",
    "type": "not_found_error"
  }
}
```

```json 401 theme={null}
{
  "error": {
    "code": 401,
    "message": "身份验证失败，请检查您的API密钥",
    "type": "authentication_error"
  }
}
```

```json 200 - Seedance theme={null}
{
  "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
    }
  }
}
```

## Response

**id** `string`

任务唯一标识符

**client\_business\_id** `string`

客户侧业务 ID。仅当创建任务时传入 `client_business_id` 时返回。

**object** `string`

对象类型，固定为 `generation.task`

**model** `string`

使用的视频生成模型

**status** `string`

任务状态

* `queued` - 排队等待处理
* `in_progress` - 处理中
* `completed` - 成功完成
* `failed` - 失败

**progress** `integer`

任务进度百分比（0-100）

**updated\_at** `integer`

可选的平台任务更新时间, Unix 时间戳. 当前用于 Seedance Global; `generation.updated_at` 是上游更新时间.

**created\_at** `integer`

任务创建时间（Unix 时间戳）

**finished\_at** `integer`

任务结束时间, Unix 时间戳. 本页查询路径在任务成功或失败且已保存结束时间时返回.

**completed\_at** `integer`

任务完成时间（Unix 时间戳，仅完成时返回）

**expires\_at** `integer`

视频 URL 过期时间（Unix 时间戳，仅完成时返回）

**result** `object`

任务结果（仅成功时返回）

**属性**

**type** `string`

结果类型，固定为 `video`

**data** `array`

视频数据数组

**数组元素**

**url** `string`

视频主地址. 启用原始地址交付的 Seedance 任务保留上游原始 URL, 优先使用该地址.

**fallback\_url** `string`

可选的视频备用 URL. 仅在副本可用时返回; 主地址无法访问时才使用, 不替换 `url`.

**format** `string`

视频格式（如 `mp4`）

**last\_frame\_url** `string`

生成视频的尾帧图像 URL。仅当创建任务时设置 `return_last_frame: true` 且模型返回尾帧时出现。

**fallback\_last\_frame\_url** `string`

可选的尾帧备用 URL. 尾帧副本可用时返回; 仅在 `last_frame_url` 无法访问时使用.

**generation** `object`

可选的 Seedance 生成元数据. 仅返回已保存且可公开的字段, 不补默认值. 这些参数描述生成任务, 不替代顶层 `usage` 的计费量.

| 字段 | 类型 | 说明 |
| - | - | - |
| `created_at`, `updated_at` | number | 上游任务创建和更新时间, Unix 时间戳; 与平台顶层时间区分 |
| `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`.

**usage** `object`

可选的计费量, 视频 token 明细和工具次数. 各字段的单位和省略规则见[任务用量字段](https://docs.toapis.com/docs/cn/api-reference/account/pricing.md).

| 字段 | 类型 | 取值 |
| - | - | - |
| `charge_type` | string | 计费方式: `per_request` 按次, `per_second` 按秒, `per_token` 按 token |
| `requests` | integer | 计费次数, `per_request` 时返回. Midjourney 视频的有效 `batch_size` 计入次数 |
| `billed_tokens` | integer | 计价 token 数, `per_token` 时返回 |
| `output_seconds` | integer | 参与计费的输出视频时长, 整数秒, `per_second` 时返回 |
| `input_seconds` | integer | 参与计费的输入视频时长, 整数秒, 为零时省略 |
| `input_images` | integer | 扣除免费额度后参与计费的输入图片数, 为零时省略 |
| `input_tokens`, `output_tokens`, `prompt_tokens`, `completion_tokens`, `total_tokens` | integer | 视频模型报告的 token 数, 按供应商实际提供情况返回; 按 token 结算后可补齐 `total_tokens` |
| `tool_usage` | object | 工具次数: `web_search`, `image_search`, `grounding_queries`, 按实际发生返回 |

`charge_type` 到 `input_images` 是计费量, 只与 `billing.status=settled` 同时返回. 固定价视频按提交时确认的数量返回, 按实际时长或 token 结算的视频按最终结算数量返回. 未返回的字段直接省略, 不补零.

**billing** `object`

可选的平台计费状态和已确认费用. 计费状态独立于任务生成状态, `completed` 不保证已经结算. 缺少该对象不代表任务免费. 详见[价格与实际费用](https://docs.toapis.com/docs/cn/api-reference/account/pricing.md).

**属性**

**status** `string`

`pending`: 生成中, 待结算或退款尚未确认, 省略金额. `settled`: 已确认最终扣费, 包括提交时一次扣清的固定价视频, 返回实际金额. `refunded`: 已退款或失败后确认无净扣费, 金额均为 `"0"`.

**credits** `string`

实际扣除的 ToAPIs Credits, 十进制字符串. 仅在 `settled` 或 `refunded` 时返回.

**cost\_usd** `string`

同一笔费用的美元金额, 十进制字符串. 返回条件同 `credits`, 已包含折扣和倍率, 不代表供应商成本.

任务 Webhook 的 `data.billing` 使用相同的确认条件和取值.

**error** `object`

错误信息（仅失败时返回）

通常错误码和消息为字符串. Seedance Global 的 `error.code` 和 `error.message` 保留上游原始 JSON 值, 包括数字或 `null`; 上游缺失时不补平台默认值.

**属性**

**code** `any`

错误代码

**message** `any`

错误描述

## 任务状态说明

| 状态 | 说明 | 是否终态 | 建议操作 |
| - | - | - | - |
| `queued` | 任务排队等待处理 | ❌ | 等待 5-10 秒后重试查询 |
| `in_progress` | 任务正在处理中 | ❌ | 等待 10-15 秒后重试查询 |
| `completed` | 任务成功完成 | ✅ | 从 result.data\[0].url 获取视频 |
| `failed` | 任务处理失败 | ✅ | 检查 error 信息 |

## 轮询策略建议

```
初始等待: 5 秒
轮询间隔: 10 秒
最大等待: 600 秒（10分钟）
典型耗时: 1-5 分钟
```

### Python 轮询示例

```python theme={null}
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("任务超时")
```

## 视频资源有效期

> [!WARNING]
>
> 生成的视频 URL 有效期为 **24 小时**
>
> * 请在有效期内下载保存视频
> * `expires_at` 字段标识视频过期时间（Unix 时间戳）
> * 视频过期后无法访问，如需重新获取，需要重新提交生成任务
> * 缩略图与视频同步过期

## 错误码与失败原因

请求错误和任务执行失败的区别, 具体错误标识与处理建议, 见[错误码速查](https://docs.toapis.com/docs/cn/api-reference/errors.md). 查询成功仍需检查任务状态, 不要把 HTTP 状态码当作业务错误码.

## 性能建议

> [!NOTE]
>
> 视频生成耗时较长，建议：
>
> 1. **使用 ToAPIs 统一任务 Webhook**：以 [Webhook](https://docs.toapis.com/docs/cn/api-reference/webhooks/task-webhooks.md) 为主，轮询为兜底
> 2. **合理设置轮询间隔**：至少5～10秒并加入随机抖动；遇到429读取 `Retry-After` 后指数退避
> 3. **设置超时时间**：长视频生成可能需要5-10分钟，请设置合理的超时
> 4. **及时下载保存**：视频24小时后过期，请务必及时保存到自己的存储

查询限流和响应头见 [异步任务速率限制](https://docs.toapis.com/docs/cn/api-reference/rate-limits/async-tasks.md)。批量查询最多 100 个任务 ID。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.