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

# 异步任务

> AIHubMix 异步任务接口：图片请求传入 async、视频任务默认异步、LLM 中断后自动保存最终响应，三类任务统一为同一个 task 对象，通过 /ai/v1/tasks 查询状态、下载结果、接收 Webhook 回调。

视频生成、批量图片生成这类请求的耗时通常超过一次 HTTP 连接的合理等待时间；长文本生成过程中客户端一旦断开，已经产生的响应也无法再取回。

**异步任务**（Async Tasks）把这三类场景统一到同一个任务对象上：图片、视频通过生成接口创建任务并立即返回 `task_id`，客户端中断的 LLM 请求由平台继续完成并保存最终响应。三者共用相同的任务状态、查询接口和结果下载流程。

<Note>
  请使用创建任务时的同一个 API Key 查询任务和下载结果。任务按 API Key 隔离，即使两个 Key 属于同一账户，也不能互相读取任务。
</Note>

<Card title="前往控制台开启异步任务" icon="list-check" href="https://console.aihubmix.com/support" horizontal>
  创建异步图片或视频前，请先为当前账户开启异步任务功能。控制台暂未显示该入口时，请联系 AIHubMix 技术支持。
</Card>

<Warning>
  未开启异步任务功能时，媒体任务创建请求返回 `403 async_not_enabled`。LLM 请求不会因此报错，但客户端中断后无法找回最终响应。
</Warning>

***

<h2 id="quickstart">
  快速开始
</h2>

图片和视频异步任务的完整流程分为三步：

```text theme={null}
1. 提交任务 -> 获得 task_id
2. 查询状态 -> 等待任务完成
3. 获取结果 -> 下载文件或读取响应内容
```

<CodeGroup>
  ```shell curl theme={null}
  # 第一步：提交异步视频任务
  curl -X POST https://aihubmix.com/ai/v1/videos \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "wan2.6-t2v",
      "prompt": "A cat playing jazz on a piano, warm lighting, cinematic shot",
      "seconds": "5",
      "size": "1280x720"
    }'

  # 第二步：每 15 秒查询一次，直到任务完成、失败或取消
  curl https://aihubmix.com/ai/v1/tasks/{task_id} \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY"

  # 第三步：下载单个产物
  curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    --output result.mp4
  ```

  ```json 创建响应 theme={null}
  {
    "id": "task_01K0...",
    "object": "video",
    "model": "wan2.6-t2v",
    "status": "in_progress",
    "output": [],
    "error": null,
    "created_at": 1784707200,
    "completed_at": null,
    "expires_at": null
  }
  ```
</CodeGroup>

***

<h2 id="sync-vs-async">
  同步调用与异步任务的对比
</h2>

| 请求类型     | 默认返回方式   | 异步方式                                |
| -------- | -------- | ----------------------------------- |
| 图片生成     | 同步返回生成结果 | 请求体传入 `async: true` 后立即返回 `task_id` |
| 视频生成     | 始终异步     | 创建后返回 `task_id`，通过任务接口获取结果          |
| LLM 文本生成 | 同步或流式返回  | 客户端中断且满足条件时，最终响应保存为 `llm` 任务        |

同步调用在一次 HTTP 响应内返回结果，连接中断后结果无法找回。异步任务把结果保存在平台侧，`task_id` 可以在结果过期前用同一个 API Key 重新查询和下载，适用于耗时较长的生成请求，以及需要在中断后取回最终响应的长文本输出。

***

<h2 id="api-overview">
  接口概览
</h2>

| 操作     | 方法   | 路径                                           | 说明                  |
| ------ | ---- | -------------------------------------------- | ------------------- |
| 创建异步图片 | POST | `/ai/v1/images/generations`                  | 请求体增加 `async: true` |
| 创建异步视频 | POST | `/ai/v1/videos`                              | 视频任务默认异步            |
| 查询任务列表 | GET  | `/ai/v1/tasks`                               | 查找当前 API Key 创建的任务  |
| 查询任务详情 | GET  | `/ai/v1/tasks/{task_id}`                     | 查询统一任务状态与输出         |
| 获取单个结果 | GET  | `/ai/v1/tasks/{task_id}/content`             | 适用于单产物或 LLM 任务      |
| 获取指定结果 | GET  | `/ai/v1/tasks/{task_id}/content/{result_id}` | 适用于多产物任务            |

Base URL：`https://aihubmix.com`，认证方式为 Bearer Token：

```bash theme={null}
Authorization: Bearer $AIHUBMIX_API_KEY
```

<Note>
  `/ai/v1/tasks` 是只读的统一查询入口，不提供 `POST /ai/v1/tasks`。图片和视频分别通过对应的生成接口创建；满足 [LLM 中断恢复](#llm-interruption-recovery)条件的请求会在客户端中断后自动记录为 `llm` 任务。
</Note>

***

<h2 id="supported-models">
  支持的模型
</h2>

异步任务按任务类型划分支持范围，调用时无需增加额外参数。

<h3 id="supported-models-image">
  异步图片
</h3>

| 模型               |
| ---------------- |
| `qwen-image-2.0` |

<h3 id="supported-models-video">
  异步视频
</h3>

| 模型           |
| ------------ |
| `wan2.6-t2v` |

<h3 id="supported-models-llm">
  LLM 中断恢复
</h3>

| 模型               |
| ---------------- |
| `gpt-5.5-pro`    |
| `claude-fable-5` |

支持范围会持续扩展，本表随之更新。

***

<h2 id="create-async-task">
  如何创建异步任务
</h2>

<h3 id="create-async-image">
  异步图片
</h3>

图片接口默认同步返回。将 `async` 设置为 `true` 后，接口会立即返回任务对象，生成过程在后台继续执行。

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/images/generations \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "prompt": "A flower shop with delicate windows, warm sunlight streaming in",
    "n": 2,
    "size": "1024x1024",
    "async": true
  }'
```

`async` 必须是布尔值。未传或设置为 `false` 时，图片接口保持同步行为。

<h3 id="create-async-video">
  异步视频
</h3>

视频接口始终异步。创建成功后会返回 `pending` 或 `in_progress` 状态，不支持通过 `Prefer: wait` 改为同步等待。

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/videos \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan2.6-t2v",
    "prompt": "Ocean waves crashing on rocky cliffs at sunset",
    "seconds": "5",
    "size": "1280x720"
  }'
```

<h3 id="common-parameters">
  公共参数
</h3>

示例中的 `model`、`prompt`、`n`、`seconds` 和 `size` 是常见模型参数，各模型支持的字段与取值以对应模型的 API 文档为准，视频模型可参考[视频生成文档](/cn/api/Video-Gen)。下表只说明所有异步任务共用的参数。

| 参数                      | 类型        | 必填           | 说明                                            |
| ----------------------- | --------- | ------------ | --------------------------------------------- |
| `async`                 | boolean   | 图片：是；视频：无需传入 | 图片接口设置为 `true` 后异步执行                          |
| `webhook_url`           | string    | 否            | 当前任务的 HTTPS 回调地址，最长 512 字符                    |
| `webhook_events_filter` | string\[] | 否            | 需要推送的最终状态，可选 `completed`、`failed`、`cancelled` |

<Note>
  图片任务只有在 `async: true` 时才能使用 Webhook。省略 `webhook_events_filter` 时，平台会推送 `completed`、`failed` 和 `cancelled` 三种最终状态；传入时必须与 `webhook_url` 一起使用，并且不能为空、不能重复。
</Note>

***

<h2 id="llm-interruption-recovery">
  LLM 中断恢复如何生效
</h2>

LLM 中断恢复用于取回客户端断开连接后的最终响应。该能力复用现有的 LLM 请求方式，流式行为和响应格式保持不变，无需调用额外的创建接口，也不会预先返回 `task_id`。

<h3 id="recovery-conditions">
  生效条件
</h3>

以下条件必须同时满足：

| 条件            | 说明                                              |
| ------------- | ----------------------------------------------- |
| 账户已开启异步任务功能   | 在 AIHubMix 控制台为当前账户开启                           |
| 所用模型支持中断恢复    | 见 [LLM 中断恢复](#supported-models-llm)，调用时无需增加额外参数 |
| 调用受支持的 LLM 接口 | 请求命中下方列出的文本生成接口                                 |
| 客户端发生中断       | 客户端主动取消、网络断开或调用方取消请求                            |

支持的接口：

| 接口                                                 | 说明                               |
| -------------------------------------------------- | -------------------------------- |
| `POST /v1/chat/completions`                        | OpenAI Chat Completions，支持流式和非流式 |
| `POST /v1/messages`                                | Anthropic Messages，支持流式和非流式      |
| `POST /v1/responses`                               | OpenAI Responses API             |
| Gemini `generateContent` / `streamGenerateContent` | Gemini 原生文本生成接口                  |

<Note>
  调用时无需传入额外字段。支持范围见 [LLM 中断恢复](#supported-models-llm)；表中未列出的模型，可在正式接入前使用一条低成本请求完成中断恢复验证，验证请求仍会正常计费。任一条件不满足时，请求仍会正常执行，客户端中断后不会生成 `llm` 任务。
</Note>

<h3 id="recovery-flow">
  中断后的执行流程
</h3>

```text theme={null}
1. 客户端正常发起 LLM 请求
2. 客户端在响应完成前断开或取消
3. AIHubMix 继续处理请求，该请求仍会正常计费
4. 最终 JSON 或 SSE 响应保存为类型为 llm 的任务
5. 使用原 API Key 查询任务列表并读取保存的响应
```

正常完成且成功返回给客户端的 LLM 请求不会创建任务，也不会出现在任务列表中。中断请求会在最终响应保存完成后出现在列表中，因此处理期间可能暂时查询不到。

<h3 id="locate-interrupted-request">
  定位对应的中断请求
</h3>

LLM 响应头会返回 `X-Aihubmix-Request-Id`。客户端收到响应头后应立即保存该值；发生中断后，可在 AIHubMix 控制台的异步任务列表中使用该请求 ID 查找对应任务。

公开任务 API 当前不支持按请求 ID 过滤。未保存请求 ID 时，只能使用创建请求时的同一个 API Key，按模型和创建时间查找：

```bash theme={null}
# 查询最近的 LLM 中断任务
curl "https://aihubmix.com/ai/v1/tasks?object=llm&model={model}&order=desc&limit=20" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"

# 找到 task_id 后，查询详情并获取原始响应
curl https://aihubmix.com/ai/v1/tasks/{task_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"

curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

<Warning>
  同一个 API Key 并发发起多个相同模型请求时，仅凭模型和创建时间无法保证精确对应。需要可靠恢复时，请保存 `X-Aihubmix-Request-Id` 并通过控制台查找；未取得响应头时，应避免将列表中的最新任务直接认定为本次请求。
</Warning>

<Warning>
  LLM 中断恢复任务当前不发送 Webhook，请通过任务列表查询结果。客户端中断不会停止平台继续处理请求，该次调用仍按原 LLM 接口规则计费。
</Warning>

***

<h2 id="task-object">
  任务对象与状态
</h2>

所有任务使用统一响应结构：

```json theme={null}
{
  "id": "task_01K0ABCDEF",
  "object": "video",
  "model": "wan2.6-t2v",
  "status": "completed",
  "output": [
    {
      "index": 0,
      "result_id": "result_01K0XYZ",
      "type": "file",
      "content_type": "video/mp4",
      "content_url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content"
    }
  ],
  "error": null,
  "created_at": 1784707200,
  "completed_at": 1784707320,
  "expires_at": 1784709120
}
```

| 字段             | 类型           | 说明                           |
| -------------- | ------------ | ---------------------------- |
| `id`           | string       | 平台任务 ID，即后续请求使用的 `task_id`   |
| `object`       | string       | 任务类型：`llm`、`image` 或 `video` |
| `model`        | string       | 创建任务时使用的模型                   |
| `status`       | string       | 统一任务状态                       |
| `output`       | array        | 可获取的结果；任务未产出结果时为空数组          |
| `error`        | object/null  | 失败信息，通常包含 `code` 和 `message` |
| `created_at`   | integer      | 创建时间，Unix 秒                  |
| `completed_at` | integer/null | 任务完成、失败或取消的时间，Unix 秒         |
| `expires_at`   | integer/null | 最早一个结果的过期时间，Unix 秒           |

`output` 中的结果字段：

| 字段             | 说明                                                |
| -------------- | ------------------------------------------------- |
| `index`        | 结果在当前任务中的顺序，从 0 开始                                |
| `result_id`    | 结果 ID；下载多产物任务的指定结果时使用                             |
| `type`         | 结果类型，文件为 `file`，LLM 响应为 `response`                |
| `content_type` | 结果的文件类型（MIME），例如 `video/mp4` 或 `application/json` |
| `content_url`  | 结果下载地址，访问时需要携带创建任务所用的 API Key                     |
| `b64_json`     | 部分图片模型可能直接返回的 Base64 编码结果                         |
| `truncated`    | LLM 响应是否因大小限制被截断                                  |

<h3 id="task-status">
  状态说明
</h3>

| 状态            | 是否已结束 | 说明                    |
| ------------- | ----- | --------------------- |
| `pending`     | 否     | 平台已接收任务，等待开始执行        |
| `in_progress` | 否     | 任务正在执行                |
| `completed`   | 是     | 任务完成，可从 `output` 获取结果 |
| `failed`      | 是     | 任务失败，失败原因见 `error`    |
| `cancelled`   | 是     | 任务已取消                 |

建议每 **15 秒**查询一次，直到状态变为 `completed`、`failed` 或 `cancelled`。

<Note>
  `failed` 或 `cancelled` 任务也可能包含已经生成的部分结果。判断是否有结果时，除状态外还应检查 `output` 是否为空。
</Note>

***

<h2 id="query-tasks">
  如何查询任务
</h2>

<h3 id="query-task-detail">
  查询任务详情
</h3>

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

该接口返回查询时的最新任务信息。查询操作不会改变任务，任务状态由平台自动更新。

<h3 id="query-task-list">
  查询任务列表
</h3>

创建响应丢失，或者需要批量查看历史任务时，可以通过列表接口找回 `task_id`：

```bash theme={null}
curl "https://aihubmix.com/ai/v1/tasks?object=video&status=in_progress&limit=20&order=desc" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

| 参数       | 类型      | 默认值    | 说明                          |
| -------- | ------- | ------ | --------------------------- |
| `object` | string  | -      | 按类型过滤：`llm`、`image`、`video` |
| `status` | string  | -      | 按统一任务状态过滤                   |
| `model`  | string  | -      | 按模型名称精确过滤                   |
| `after`  | string  | -      | 分页游标，使用上一页的 `next_after`    |
| `limit`  | integer | `20`   | 每页数量，范围 1～100               |
| `order`  | string  | `desc` | `asc` 或 `desc`              |

响应示例：

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "task_01K0ABCDEF",
      "object": "video",
      "model": "wan2.6-t2v",
      "status": "in_progress",
      "output": [],
      "error": null,
      "created_at": 1784707200,
      "completed_at": null,
      "expires_at": null
    }
  ],
  "has_more": true,
  "next_after": "task_01K0ABCDEF"
}
```

| 字段           | 说明                  |
| ------------ | ------------------- |
| `object`     | 固定为 `list`，表示这是列表响应 |
| `data`       | 当前页的任务数组            |
| `has_more`   | 是否还有下一页             |
| `next_after` | 下一页游标；仅在还有下一页时返回    |

继续请求下一页：

```bash theme={null}
curl "https://aihubmix.com/ai/v1/tasks?limit=20&order=desc&after=task_01K0ABCDEF" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

***

<h2 id="get-task-results">
  如何获取任务结果
</h2>

<h3 id="single-artifact">
  单产物任务
</h3>

`output` 只有一个文件时，可以直接访问：

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  --output result.bin
```

也可以直接使用 `output[0].content_url`。下载响应的 `Content-Type` 与 `output[0].content_type` 一致。

<h3 id="multiple-artifacts">
  多产物任务
</h3>

`output` 包含多个文件时，必须指定对应的 `result_id`：

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content/{result_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  --output result.png
```

多产物任务未指定 `result_id` 时，接口返回 `400 result_id_required`。

<h3 id="llm-response-task">
  LLM 响应任务
</h3>

满足 [LLM 中断恢复](#llm-interruption-recovery)条件并保存响应后，任务的 `object` 为 `llm`，`output` 项的 `type` 为 `response`。内容类型可能是：

* `application/json`：普通 JSON 响应
* `text/event-stream`：保存的 SSE 流式响应

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

截断标记位于任务详情的 `output[0].truncated`。值为 `true` 时，表示保存的响应因大小限制被截断。`GET /ai/v1/tasks/{task_id}/content` 返回原始 JSON 或 SSE 内容，内容外不再包装 `truncated` 字段，因此应先查询任务详情再读取内容。

<Warning>
  结果可能过期，并且可能存在下载次数限制。请在 `expires_at` 之前及时保存。过期返回 `410 artifact_expired`，超过下载次数限制返回 `429 too_many_downloads`。
</Warning>

***

<h2 id="webhooks">
  如何使用 Webhook
</h2>

当前支持在创建异步任务时提交任务级 Webhook。需要任务完成后由 AIHubMix 主动通知时，请在异步图片或视频请求体中传入 `webhook_url` 和可选的 `webhook_events_filter`：

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/videos \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan2.6-t2v",
    "prompt": "A tranquil Japanese garden at sunrise",
    "seconds": "5",
    "webhook_url": "https://example.com/webhooks/aihubmix",
    "webhook_events_filter": ["completed", "failed"]
  }'
```

回调地址必须使用 HTTPS，且不能指向本机、私网或其他受限地址。

<h3 id="webhook-payload">
  回调请求
</h3>

AIHubMix 会向回调地址发送 `POST` 请求：

```json theme={null}
{
  "event_id": "evt_01K0ABCDEF",
  "event_type": "completed",
  "created_at": "2026-07-22T12:00:00Z",
  "data": {
    "task_id": "task_01K0ABCDEF",
    "status": "completed",
    "model": "wan2.6-t2v",
    "results": [
      {
        "url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content"
      }
    ]
  }
}
```

| 字段                   | 说明                                        |
| -------------------- | ----------------------------------------- |
| `event_id`           | 本次回调事件的唯一 ID，用于识别重复通知                     |
| `event_type`         | 任务最终状态：`completed`、`failed` 或 `cancelled` |
| `created_at`         | 回调事件创建时间                                  |
| `data.task_id`       | 任务 ID，可用于查询任务详情                           |
| `data.status`        | 当前任务状态                                    |
| `data.model`         | 创建任务时使用的模型                                |
| `data.results[].url` | 已生成结果的下载地址                                |
| `data.error.code`    | 失败错误码，仅失败事件可能包含                           |
| `data.error.message` | 失败原因，仅失败事件可能包含                            |

`results` 中的 URL 仍需携带创建任务时的 API Key 才能访问。

<h3 id="webhook-retry">
  重试与去重
</h3>

平台会至少尝试投递一次回调，因此同一个事件可能被重复发送：

* HTTP `2xx` 表示接收成功。
* HTTP `5xx`、网络错误或超时会触发重试。
* HTTP `3xx` 和 `4xx` 不会重试。
* 最多投递 6 次，重试间隔依次为 1、4、16、64、256 秒。

接收端应保存 `event_id`。再次收到相同 `event_id` 时，跳过业务逻辑并直接返回 `2xx`。

<Warning>
  当前任务级 Webhook 不提供可配置的独立签名凭据。收到通知后，应使用创建任务时的 API Key 请求 `GET /ai/v1/tasks/{task_id}`，以查询结果为准。
</Warning>

***

<h2 id="error-codes">
  错误响应与错误码
</h2>

错误响应使用统一结构：

```json theme={null}
{
  "error": {
    "message": "Task not found.",
    "type": "invalid_request_error",
    "code": "task_not_found",
    "tid": "req_01K0..."
  }
}
```

| 字段              | 说明                  |
| --------------- | ------------------- |
| `error.message` | 错误原因                |
| `error.type`    | 错误类型                |
| `error.code`    | 程序可识别的错误码           |
| `error.tid`     | 请求追踪 ID；联系技术支持排查时提供 |

| HTTP 状态码 | 错误码                             | 说明                   |
| -------- | ------------------------------- | -------------------- |
| 400      | `invalid_request`               | 参数类型或取值不正确           |
| 400      | `result_id_required`            | 多产物任务未指定 `result_id` |
| 400      | `webhook_invalid`               | Webhook URL 不合法      |
| 400      | `webhook_events_filter_invalid` | Webhook 事件列表不合法      |
| 401      | `authentication_failed`         | API Key 缺失或无效        |
| 403      | `async_not_enabled`             | 账户未开启异步任务功能          |
| 404      | `task_not_found`                | 任务不存在，或不属于当前 API Key |
| 404      | `result_not_found`              | 结果不存在或当前不可获取         |
| 410      | `artifact_expired`              | 结果已过期                |
| 429      | `too_many_downloads`            | 超过结果下载次数限制           |
| 503      | `async_unavailable`             | 异步图片服务暂不可用，请稍后重试     |

***

<h2 id="full-example">
  完整示例
</h2>

创建视频任务、轮询状态、下载全部结果的完整流程：

<CodeGroup>
  ```python Python theme={null}
  import base64
  import os
  import time

  import requests

  BASE_URL = "https://aihubmix.com"
  API_KEY = os.environ["AIHUBMIX_API_KEY"]
  HEADERS = {
      "Authorization": f"Bearer {API_KEY}",
      "Content-Type": "application/json",
  }

  # 1. 创建任务
  response = requests.post(
      f"{BASE_URL}/ai/v1/videos",
      headers=HEADERS,
      json={
          "model": "wan2.6-t2v",
          "prompt": "A cat playing jazz on a piano",
          "seconds": "5",
          "size": "1280x720",
      },
      timeout=60,
  )
  response.raise_for_status()
  task = response.json()
  task_id = task["id"]

  # 2. 轮询，直到任务完成、失败或取消
  while task["status"] not in {"completed", "failed", "cancelled"}:
      time.sleep(15)
      response = requests.get(
          f"{BASE_URL}/ai/v1/tasks/{task_id}",
          headers=HEADERS,
          timeout=30,
      )
      response.raise_for_status()
      task = response.json()
      print("status:", task["status"])

  # 3. 获取结果
  if task["output"]:
      for index, item in enumerate(task["output"]):
          if encoded := item.get("b64_json"):
              with open(f"result-{index}.bin", "wb") as file:
                  file.write(base64.b64decode(encoded))
              continue
          result = requests.get(
              item["content_url"],
              headers=HEADERS,
              timeout=120,
          )
          result.raise_for_status()
          with open(f"result-{index}.bin", "wb") as file:
              file.write(result.content)
  elif task["status"] == "failed":
      raise RuntimeError(task.get("error"))
  ```

  ```typescript TypeScript theme={null}
  import { writeFile } from "node:fs/promises";

  const BASE_URL = "https://aihubmix.com";
  const HEADERS = {
    Authorization: `Bearer ${process.env.AIHUBMIX_API_KEY}`,
    "Content-Type": "application/json",
  };

  // 1. 创建任务
  const created = await fetch(`${BASE_URL}/ai/v1/videos`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({
      model: "wan2.6-t2v",
      prompt: "A cat playing jazz on a piano",
      seconds: "5",
      size: "1280x720",
    }),
  });
  let task = await created.json();

  // 2. 轮询，直到任务完成、失败或取消
  const finished = new Set(["completed", "failed", "cancelled"]);
  while (!finished.has(task.status)) {
    await new Promise((resolve) => setTimeout(resolve, 15_000));
    const polled = await fetch(`${BASE_URL}/ai/v1/tasks/${task.id}`, {
      headers: HEADERS,
    });
    task = await polled.json();
    console.log("status:", task.status);
  }

  // 3. 获取结果
  if (task.output?.length) {
    for (const [index, item] of task.output.entries()) {
      if (item.b64_json) {
        await writeFile(`result-${index}.bin`, Buffer.from(item.b64_json, "base64"));
        continue;
      }
      const result = await fetch(item.content_url, { headers: HEADERS });
      await writeFile(`result-${index}.bin`, Buffer.from(await result.arrayBuffer()));
    }
  } else if (task.status === "failed") {
    throw new Error(JSON.stringify(task.error));
  }
  ```

  ```shell curl theme={null}
  # 1. 创建任务，记录返回的 id
  curl -X POST https://aihubmix.com/ai/v1/videos \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "wan2.6-t2v",
      "prompt": "A cat playing jazz on a piano",
      "seconds": "5",
      "size": "1280x720"
    }'

  # 2. 每 15 秒查询一次状态
  curl https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY"

  # 3. 状态变为 completed 后下载结果
  curl https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    --output result.mp4
  ```
</CodeGroup>

***

<h2 id="faq">
  常见问题
</h2>

**建议多久查询一次任务状态？**

建议每 15 秒查询一次，避免高频轮询。使用 Webhook 时也应保留低频查询作为备用。

**创建响应丢失后如何找回任务？**

使用创建任务时的同一个 API Key 请求 `GET /ai/v1/tasks`，可以按 `object`、`model` 和 `status` 缩小范围。

**为什么同一账户的另一个 API Key 查不到任务？**

任务按 API Key 隔离。查询、下载和列表请求都必须使用创建任务时的同一个 Key。

**为什么任务失败了但 `output` 不是空数组？**

部分模型可能在整体失败或取消前已经生成了可交付结果。只要 `output` 中存在 `content_url` 或 `b64_json`，就可以按对应方式获取。

**Webhook 没收到怎么办？**

确认回调地址能公开访问、使用 HTTPS，并在 10 秒内返回 `2xx`。无论是否使用 Webhook，都可以通过 `GET /ai/v1/tasks/{task_id}` 查询最终状态。

**LLM 中断恢复需要修改现有代码吗？**

不需要。请求方式、流式行为和响应格式保持不变。建议保存响应头 `X-Aihubmix-Request-Id`，以便中断后在控制台精确定位对应任务。

***

更新时间：2026-07-28
