> ## 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 文件為準，影片模型可參考[影片生成文件](/zh-Hant/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
