HiAPI
博客

教程

如何通过 hiapi API 使用 gpt-image-2/text-to-image:参数、代码与可运行示例

2026年11月3日
如何通过 hiapi API 使用 gpt-image-2/text-to-image:参数、代码与可运行示例

本教程展示了通过 hiapi 统一任务 API 用 gpt-image-2/text-to-image 生成图像所需的最少代码量,然后逐一解释每个参数,以及代码跑通后应当采用的生产级模式(回调、幂等性、错误处理)。

前置条件

你需要一个 API 密钥。请从 hiapi 控制台的 API 密钥页面创建——密钥以 sk- 开头。gpt-image-2/text-to-image 的模型页面列出了当前的单张图像价格;完整明细见价格页面。

本指南中的所有调用都打到统一的异步任务端点:

  • POST https://api.hiapi.ai/v1/tasks——创建生成任务
  • GET https://api.hiapi.ai/v1/tasks/{taskId}——轮询任务状态

平台通用参考文档位于 hiapi API 文档。

最小可运行示例(curl)

单次生成是一个两步交互:先创建任务,然后等待其完成。

# 1. Create the task
curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/text-to-image",
    "input": {
      "prompt": "a calico cat curled up on a sunlit windowsill, soft focus background",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KVY...."},"message":"success"}

# 2. Poll until status == "success"
TASK_ID="tk-hiapi-01KVY...."
curl -s "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer sk-YOUR_KEY"
# => {"code":200,"data":{"status":"success","output":[{"url":"https://..."}], ...}}

图像 URL 位于 data.output[0].url。请立即下载——output[0].expireAt 很短,因此该 URL 只用于获取,不用于永久嵌入。

Python:创建 + 轮询 + 保存到磁盘

import os
import time
import urllib.request
import requests  # pip install requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]  # sk-...

def create_task(prompt: str, aspect_ratio: str = "1:1", resolution: str = "1K") -> str:
    payload = {
        "model": "gpt-image-2/text-to-image",
        "input": {
            "prompt": prompt,
            "aspect_ratio": aspect_ratio,
            "resolution": resolution,
        },
    }
    r = requests.post(API_BASE, json=payload,
                      headers={"Authorization": f"Bearer {TOKEN}"},
                      timeout=60)
    r.raise_for_status()
    body = r.json()
    if body.get("error"):
        raise RuntimeError(f"create failed: {body['error']}")
    return body["data"]["taskId"]

def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API_BASE}/{task_id}",
                         headers={"Authorization": f"Bearer {TOKEN}"},
                         timeout=30)
        r.raise_for_status()
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            raise RuntimeError(f"task failed: {task.get('error')}")
        time.sleep(poll_s)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")

if __name__ == "__main__":
    task_id = create_task(
        "a calico cat curled up on a sunlit windowsill, soft focus background",
        aspect_ratio="3:2",
        resolution="1K",
    )
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    urllib.request.urlretrieve(url, "cat.png")
    print(f"saved cat.png from task {task_id}")

Node.js:使用 fetch 的相同流程

// Node 18+ has global fetch
const API_BASE = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;

async function createTask(prompt, aspectRatio = "1:1", resolution = "1K") {
  const res = await fetch(API_BASE, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gpt-image-2/text-to-image",
      input: { prompt, aspect_ratio: aspectRatio, resolution },
    }),
  });
  const body = await res.json();
  if (body.error) throw new Error(`create failed: ${body.error.code} ${body.error.message}`);
  return body.data.taskId;
}

async function waitTask(taskId, { timeoutMs = 600_000, pollMs = 5_000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(`${API_BASE}/${taskId}`, {
      headers: { "Authorization": `Bearer ${TOKEN}` },
    });
    const task = (await res.json()).data || {};
    if (task.status === "success") return task;
    if (task.status === "fail") throw new Error(`task failed: ${JSON.stringify(task.error)}`);
    await new Promise(r => setTimeout(r, pollMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await createTask(
    "a calico cat curled up on a sunlit windowsill, soft focus background",
    "16:9",
    "1K",
  );
  const task = await waitTask(id);
  const url = task.output[0].url;
  const img = await fetch(url).then(r => r.arrayBuffer());
  const { writeFileSync } = await import("node:fs");
  writeFileSync("cat.png", Buffer.from(img));
  console.log(`saved cat.png from task ${id}`);
})();

参数参考

请求体始终包含两个顶层字段:model(字符串,裸模型 ID gpt-image-2/text-to-image)和 input(各模型专属的参数对象)。

input 字段 是否必填 类型 说明
prompt 是 string 你想要的图像的文字描述。
aspect_ratio 是 string 取值之一:1:1、3:2、2:3、4:3、3:4、5:4、4:5、16:9、9:16、21:9 或 auto。
resolution 否 string 1K(默认)、2K 或 4K。像素尺寸随所选宽高比缩放。
callback 否 object { "url": "https://yours.example/hook", "when": "final" }——见下一节。

创建成功返回 {"code":200, "data":{"taskId":"tk-hiapi-..."}, "message":"success"}。GET /v1/tasks/{taskId} 返回的 data.status 为 handling、success 或 fail 之一;成功时,data.output 是一个数组,其第一个元素包含图像的 url 和 expireAt 时间戳。

其他 hiapi 图像模型(例如 z-image、qwen-image)使用略有不同的 input 字段——aspect_ratio 是 gpt-image-2/text-to-image 采用的约定。切换模型时,请查看模型页面以确认确切的 input 结构。

生产级模式

使用回调代替轮询

每 5 秒轮询一次对原型开发没问题,但对于生产流量,你希望 hiapi 把完成的任务推送给你,从而释放 worker。在 input 中添加一个 callback 块:

{
  "model": "gpt-image-2/text-to-image",
  "input": {
    "prompt": "an astronaut sketching the moon",
    "aspect_ratio": "3:2",
    "resolution": "1K",
    "callback": {
      "url": "https://your-app.example.com/webhooks/hiapi",
      "when": "final"
    }
  }
}

when: "final" 在任务达到终态(success 或 fail)时触发一次。你的端点收到的载荷结构与 GET /v1/tasks/{id} 相同,因此处理器可以复用轮询的解析逻辑。请将 taskId 与你创建任务时存储的 taskId 进行核对,从而知道回调属于哪个请求。

让创建操作具备幂等性

如果 worker 在 POST /v1/tasks 之后、存储 taskId 之前崩溃,你可能会把同一张图像生成两次。低成本的解决办法是:在收到创建响应的那一刻,在提交请求的同一事务中把 (your_request_id → taskId) 存入数据库。如果 worker 重试,它会找到已有的 taskId 并恢复轮询,而不是创建新任务。

正确处理鉴权错误

hiapi 鉴权失败会返回 HTTP 200,并在响应体内嵌错误载荷:

{"error":{"code":"permission_denied","message":"This API key cannot use the selected model. ...","type":"hiapi_error"}}

所以仅凭 200 状态码并不意味着成功。始终先检查 body.error;如果存在,查看 error.code(permission_denied、invalid_request 等)和 error.message。消息中的 request_id 就是你在需要帮助时粘贴到支持工单里的内容。

立即下载,自行重新托管

data.output[0].url 是一个短时效 URL——响应中包含 expireAt。不要把 hiapi 的 URL 直接放进你产品里的 <img src>;一旦任务成功就立刻下载字节流,上传到你自己的存储(S3、R2、Supabase Storage 等),然后从那里提供服务。

设置合理的超时

一个合理的默认值是:POST 请求超时 60 秒(创建任务很快——你实际上只是在等 API 确认收到),轮询循环总预算 10 分钟、轮询间隔 5 秒。耗时超过 10 分钟的任务几乎总是意味着任务已悄悄进入 fail 状态,因此超时并在日志中输出最后一次任务响应体,比无限等待更有用。

常见问题

gpt-image-2 和 gpt-image-2/text-to-image 有什么区别?

gpt-image-2 是模型系列;gpt-image-2/text-to-image 是你调用来将文本提示转换为新图像的特定端点。该系列中的其他变体暴露不同的 input 结构(例如,图像编辑接受参考图像)。如有疑问,请使用你在模型页面上看到的裸模型 ID。

aspect_ratio: auto 有什么作用?

auto 让模型根据提示决定宽高比。当你没有强烈的布局要求时使用它;否则请自行固定比例,以便下游裁剪可预测。

为什么我的请求返回 HTTP 200 却带有 permission_denied?

要么 API 密钥有误(拼写错误、已被撤销、缺少 sk- 前缀),要么该密钥的套餐不包含 gpt-image-2/text-to-image。打开 API 密钥控制台,确认密钥字符串,并在价格页面检查你的套餐。始终检查 body.error.code——绝不要只相信 HTTP 状态码。

我可以在一个请求中生成多张图像吗?

gpt-image-2/text-to-image 每个任务只生成一张图像——data.output 是数组,但对该模型来说长度始终为 1。要生成 N 个变体,请并发发起 N 个任务,并使用上面的 callback 模式,这样你就不会让 N 个工作线程一直挂着。

如何取消正在执行中的任务?

统一任务 API 目前不提供取消端点。最简单的缓解办法是让客户端 worker 在用户不再需要结果时丢弃它——已经执行的生成仍然会计费,因此强制执行取消的正确位置是在调用 POST /v1/tasks 之前。

如何切换到其他图像模型?

将 model 改为新的裸 ID(例如 z-image/text-to-image),并调整 input 以匹配该模型的结构。各模型的结构并不完全相同——有些接受 size,有些接受 aspect_ratio,还有少数不接受 resolution。模型目录列出了所有可用模型,每个模型页面都记录了其 input 字段。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档