> ## 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 原生图片协议同步或异步生成图片，并查询任务和下载结果。

AIHubMix 原生图片协议使用 `/ai/v1/images` 系列端点。生成接口默认同步，传入布尔值
`async: true` 后在后台生成，并使用同一套任务状态、Webhook 和错误结构。

<Warning>
  使用异步图片、任务查询或 Webhook 前，需要为当前账户开启异步任务功能。未开启时，
  异步任务创建请求返回 `403 async_not_enabled`。
</Warning>

## 快速开始

下面使用 `qwen-image-2.0` 异步生成一张图片。

<CodeGroup>
  ```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": 1,
      "size": "1024x1024",
      "async": true
    }'
  ```

  ```json 创建响应 theme={null}
  {
    "id": "task_01K0ABCDEF",
    "object": "image",
    "model": "qwen-image-2.0",
    "status": "in_progress",
    "output": [],
    "error": null,
    "created_at": 1784707200,
    "completed_at": null,
    "expires_at": null
  }
  ```

  ```bash 查询任务 theme={null}
  curl https://aihubmix.com/ai/v1/images/{id} \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY"
  ```

  ```bash 下载图片 theme={null}
  curl "{content_url}" \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    --output result.png
  ```
</CodeGroup>

任务进入 `completed` 后，逐项读取 `output[].content_url`。该地址对应
`GET /ai/v1/images/{id}/content/{result_id}`，客户端不需要自行拼接 `result_id`。

## 接口概览

| 场景     | 方法   | 路径                                       | 说明                     |
| ------ | ---- | ---------------------------------------- | ---------------------- |
| 生成图片   | POST | `/ai/v1/images/generations`              | 默认同步，`async: true` 时异步 |
| 查询图片详情 | GET  | `/ai/v1/images/{id}`                     | 返回任务最新状态               |
| 查询图片列表 | GET  | `/ai/v1/images`                          | 返回当前 API Key 创建的图片任务快照 |
| 下载指定图片 | GET  | `/ai/v1/images/{id}/content/{result_id}` | 下载多图任务中的指定结果           |

Base URL：`https://aihubmix.com`

认证方式：

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

## 查询模型 Schema

模型目录可以筛选已经提供请求 Schema 的文生图模型：

```bash theme={null}
curl "https://aihubmix.com/api/v1/models?type=image_generation&schema_checked=true&sort_by=order"
```

取得 `model_id` 后，查询该模型实际支持的端点：

```bash theme={null}
curl "https://aihubmix.com/call/schema/models/qwen-image-2.0/endpoints"
```

同一模型可能同时返回 AIHubMix 原生与兼容端点。应按 `path` 选择原生图片接口，再读取
对应的 `request.schema`：

```bash theme={null}
curl -s "https://aihubmix.com/call/schema/models/qwen-image-2.0/endpoints" \
  | jq '.endpoints[] | select(.path == "/ai/v1/images/generations") | .request.schema'
```

不要依赖 `endpoints` 数组位置。完整响应字段和失败情况参阅
[模型 Schema 接口](/cn/api/async-tasks#model-schema)。

## 创建图片

### 同步生成

省略 `async` 或设置为 `false` 时，请求等待生成完成后返回任务对象：

```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 quiet reading room in the afternoon",
    "n": 1,
    "size": "1024x1024",
    "response_format": "url"
  }'
```

同步请求也会保存任务记录。创建响应丢失时，可以通过图片列表找回任务。

### 异步生成

`async` 必须是布尔值 `true`，不能写成字符串。异步请求立即返回任务对象，生成在后台继续。
`webhook_url` 和 `webhook_events_filter` 只能与 `async: true` 一起使用。

### 标准字段

| 字段                      | 类型            | 必填 | 说明                                     |
| ----------------------- | ------------- | -- | -------------------------------------- |
| `model`                 | string        | 是  | 模型 ID                                  |
| `prompt`                | string        | 是  | 图片描述，不能为空                              |
| `n`                     | integer/null  | 否  | 图片数量，最小值 `1`，默认 `1`                    |
| `size`                  | string/null   | 否  | `{width}x{height}`，例如 `1024x1024`      |
| `aspect_ratio`          | string/null   | 否  | 宽高比，与 `size` 二选一                       |
| `seed`                  | integer/null  | 否  | 随机种子                                   |
| `negative_prompt`       | string/null   | 否  | 负向提示词                                  |
| `image`                 | string/object | 否  | 单张输入图片                                 |
| `images`                | array/null    | 否  | 多张输入图片                                 |
| `mask`                  | string/object | 否  | 图片编辑蒙版                                 |
| `output_format`         | string/null   | 否  | `png`、`jpeg` 或 `webp`                  |
| `response_format`       | string/null   | 否  | `url` 或 `b64_json`                     |
| `async`                 | boolean       | 否  | `true` 时异步执行                           |
| `webhook_url`           | string        | 否  | HTTPS 回调地址，最长 512 字符                   |
| `webhook_events_filter` | string\[]     | 否  | `completed`、`failed`、`cancelled` 的非空子集 |
| `extra`                 | object/null   | 否  | 模型专属扩展参数                               |

<Warning>
  标准字段集合不表示所有模型支持全部字段。字段、枚举和取值范围以该模型
  `/ai/v1/images/generations` 端点的 `request.schema` 为准。
</Warning>

## 图片任务对象

同步生成完成后，或异步任务进入结束态后，接口返回以下结构：

```json theme={null}
{
  "id": "task_01K0ABCDEF",
  "object": "image",
  "model": "qwen-image-2.0",
  "status": "completed",
  "output": [
    {
      "index": 0,
      "type": "file",
      "b64_json": null,
      "content_url": "https://aihubmix.com/ai/v1/images/task_01K0ABCDEF/content/result_01K0XYZ"
    }
  ],
  "error": null,
  "created_at": 1784707200,
  "completed_at": 1784707218,
  "expires_at": 1784714418
}
```

| 字段             | 类型           | 说明                                           |
| -------------- | ------------ | -------------------------------------------- |
| `id`           | string       | 平台任务 ID                                      |
| `object`       | string       | 图片任务固定为 `image`                              |
| `model`        | string       | 实际使用的模型 ID                                   |
| `status`       | string       | 当前任务状态                                       |
| `output`       | array        | 已生成的图片；尚无结果时为空数组                             |
| `error`        | object/null  | 失败信息，可含 `code`、`message` 和 `upstream_detail` |
| `created_at`   | integer      | 创建时间，Unix 秒                                  |
| `completed_at` | integer/null | 进入结束态的时间，Unix 秒                              |
| `expires_at`   | integer/null | 结果过期时间，Unix 秒；任务完成前可能为空                      |

`output` 项包含顺序 `index`、固定值 `type: "file"`、可选的 `b64_json` 和
`content_url`。多图请求会按 `index` 返回多个结果。

### 状态说明

| 状态            | 是否结束 | 说明               |
| ------------- | ---- | ---------------- |
| `pending`     | 否    | 已接收，等待执行         |
| `in_progress` | 否    | 正在生成             |
| `completed`   | 是    | 已完成，可读取 `output` |
| `failed`      | 是    | 已失败，原因见 `error`  |
| `cancelled`   | 是    | 已取消              |

客户端可以每 15 秒查询一次，直到状态变为 `completed`、`failed` 或 `cancelled`。
15 秒是客户端轮询建议，不是服务端协议限制。

## 查询图片任务

### 查询详情

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

图片详情接口会返回任务最新状态。异步图片轮询必须使用该接口，不要使用统一任务详情代替。

### 查询列表

创建响应丢失时，可以通过图片列表找回任务 ID：

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

| 参数      | 类型      | 默认值    | 说明                       |
| ------- | ------- | ------ | ------------------------ |
| `after` | string  | -      | 分页游标，使用上一页的 `next_after` |
| `limit` | integer | `20`   | 每页数量，最大 `100`            |
| `order` | string  | `desc` | `asc` 为升序，其他值按 `desc` 处理 |

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "task_01K0ABCDEF",
      "object": "image",
      "model": "qwen-image-2.0",
      "status": "in_progress",
      "output": [],
      "error": null,
      "created_at": 1784707200,
      "completed_at": null,
      "expires_at": null
    }
  ],
  "has_more": true,
  "next_after": "task_01K0ABCDEF"
}
```

列表返回查询时的任务快照，不会主动刷新活动任务状态。

## 统一任务接口

`/ai/v1/tasks` 提供图片、视频和 LLM 任务的统一只读视图。可以只查询图片任务：

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

统一任务列表支持 `object`、`status`、`model`、`after`、`limit` 和 `order`。统一任务详情：

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

统一任务中的图片结果会额外提供 `result_id` 和 `content_type`：

```json theme={null}
{
  "index": 0,
  "result_id": "result_01K0XYZ",
  "type": "file",
  "content_type": "image/png",
  "content_url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content/result_01K0XYZ"
}
```

多结果统一任务通过 `/ai/v1/tasks/{id}/content/{result_id}` 下载。未指定结果 ID 时返回
`400 result_id_required`。

<Note>
  媒体详情接口可能在查询时更新活动任务状态，统一任务接口只返回当前快照。因此轮询使用
  `/ai/v1/images/{id}`；统一筛选和读取结果元数据时使用 `/ai/v1/tasks`。
  任务及内容按创建任务时的 Bearer Token 隔离。
</Note>

## 下载图片结果

任务进入 `completed` 后，优先直接使用媒体任务对象返回的结果字段：

* `output[].b64_json` 非空：直接进行 Base64 解码。
* `output[].content_url` 非空：携带创建任务时的 Bearer Token 请求该地址。

```bash theme={null}
curl "{content_url}" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  --output result.png
```

图片媒体下载路径是 `/ai/v1/images/{id}/content/{result_id}`。媒体任务对象不单独公开
`result_id`，客户端不需要自行解析或拼接，逐项使用 `output[].content_url` 即可。

<Warning>
  结果可能过期，也可能存在下载次数限制。过期返回 `410 artifact_expired`；超过下载
  次数限制返回 `429 too_many_downloads`。客户端应在任务完成后及时保存结果。
</Warning>

## Webhook

Webhook 仅用于 `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 quiet reading room in the afternoon",
    "n": 1,
    "size": "1024x1024",
    "async": true,
    "webhook_url": "https://example.com/webhooks/aihubmix",
    "webhook_events_filter": ["completed", "failed"]
  }'
```

`webhook_url` 最长 512 字符，不能指向本机、私网或其他受限地址。省略事件过滤器时，
平台推送 `completed`、`failed` 和 `cancelled`；显式传入时，数组不能为空、不能重复，
并且必须与 `webhook_url` 一起使用。

### 回调请求

```json theme={null}
{
  "event_id": "evt_01K0ABCDEF",
  "event_type": "completed",
  "created_at": "2026-08-12T12:00:00Z",
  "data": {
    "task_id": "task_01K0ABCDEF",
    "status": "completed",
    "model": "qwen-image-2.0",
    "results": [
      {
        "url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content/result_01K0XYZ"
      }
    ]
  }
}
```

`event_id` 用于去重；`data.error` 在失败时可能出现；`data.results` 只在结果已存档时出现，
下载仍需 Bearer Token。

### 重试与去重

平台采用至少一次投递，同一事件可能重复送达：

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

接收端应保存 `event_id`，重复收到相同事件时直接返回 `2xx`。任务级 Webhook 本身不
携带独立签名密钥；需要签名验证时，请配置账户级 Webhook，并保留详情查询作为结果确认方式。

## 错误响应与错误码

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

| HTTP 状态码 | 错误码                             | 说明                             |
| -------- | ------------------------------- | ------------------------------ |
| 400      | `invalid_request`               | 参数类型或取值不正确                     |
| 400      | `result_id_required`            | 统一任务包含多个结果，但下载时未指定 `result_id` |
| 400      | `webhook_invalid`               | Webhook URL 不合法，或过滤器缺少 URL     |
| 400      | `webhook_events_filter_invalid` | Webhook 事件列表不合法                |
| 401      | `authentication_failed`         | API Key 缺失或无效                  |
| 403      | `async_not_enabled`             | 账户未开启异步任务功能                    |
| 404      | `task_not_found`                | 任务或分页游标不存在                     |
| 404      | `result_not_found`              | 结果不存在或当前不可下载                   |
| 410      | `artifact_expired`              | 结果已过期                          |
| 413      | `request_too_large`             | 请求体超过 32 MiB                   |
| 429      | `too_many_downloads`            | 超过结果下载次数限制                     |
| 503      | `async_unavailable`             | 异步图片服务暂不可用                     |

`error.tid` 是请求追踪 ID，联系技术支持排查时请一并提供。

## 完整示例

以下示例完成异步创建、轮询和多图片保存。

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

  import requests

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

  response = requests.post(
      f"{base_url}/ai/v1/images/generations",
      headers=headers,
      json={
          "model": "qwen-image-2.0",
          "prompt": "A flower shop with delicate windows, warm sunlight streaming in",
          "n": 1,
          "size": "1024x1024",
          "async": True,
      },
      timeout=60,
  )
  response.raise_for_status()
  task = response.json()

  while task["status"] not in {"completed", "failed", "cancelled"}:
      time.sleep(15)
      response = requests.get(
          f"{base_url}/ai/v1/images/{task['id']}",
          headers=headers,
          timeout=30,
      )
      response.raise_for_status()
      task = response.json()

  if task["status"] != "completed":
      raise RuntimeError(task.get("error") or task["status"])

  for output in task["output"]:
      filename = f"result-{output['index']}.png"
      if output.get("b64_json"):
          content = base64.b64decode(output["b64_json"])
      else:
          result = requests.get(output["content_url"], headers=headers, timeout=120)
          result.raise_for_status()
          content = result.content
      with open(filename, "wb") as file:
          file.write(content)
  ```

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

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

  const created = await fetch(`${baseUrl}/ai/v1/images/generations`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "qwen-image-2.0",
      prompt: "A flower shop with delicate windows, warm sunlight streaming in",
      n: 1,
      size: "1024x1024",
      async: true,
    }),
  });
  if (!created.ok) throw new Error(await created.text());
  let task = await created.json();

  const finished = new Set(["completed", "failed", "cancelled"]);
  while (!finished.has(task.status)) {
    await new Promise((resolve) => setTimeout(resolve, 15_000));
    const polled = await fetch(`${baseUrl}/ai/v1/images/${task.id}`, { headers });
    if (!polled.ok) throw new Error(await polled.text());
    task = await polled.json();
  }

  if (task.status !== "completed") {
    throw new Error(JSON.stringify(task.error ?? task.status));
  }

  for (const output of task.output) {
    let content;
    if (output.b64_json) {
      content = Buffer.from(output.b64_json, "base64");
    } else {
      const result = await fetch(output.content_url, { headers });
      if (!result.ok) throw new Error(await result.text());
      content = Buffer.from(await result.arrayBuffer());
    }
    await writeFile(`result-${output.index}.png`, content);
  }
  ```
</CodeGroup>

## 常见问题

**图片任务应该查询 `/ai/v1/tasks/{id}` 还是图片详情接口？**

轮询使用 `/ai/v1/images/{id}`；统一筛选任务或读取 `result_id`、`content_type` 时使用
`/ai/v1/tasks`。

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

请求 `GET /ai/v1/images?limit=20&order=desc`，再用返回的任务 ID 查询图片详情。

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

确认回调地址可以公开访问并及时返回 `2xx`，然后使用图片详情接口确认最终状态。

更多跨媒体背景参阅 [异步任务](/cn/api/async-tasks)、
[Webhook 说明](/cn/api/async-tasks#webhooks) 和
[完整错误码](/cn/api/async-tasks#error-codes)。
