HiAPI
博客

教程

如何通过 HiAPI API 使用 ideogram-v4.5:curl、Python 与一个可用的请求

2026年10月31日
封面图:浅灰蓝底上多层半透明玻璃片交叠,折射出克制的蓝色条带,安静而具建筑感。

HiAPI 上的 ideogram-v4.5 能为你带来什么

当图片中的文字确实重要时,ideogram-v4.5 就是你该选的模型。海报版式、标志图形、包装效果图、社交卡片——任何一处拼错的标题或糊掉的说明文字就会毁掉素材的场景,正是这个模型的价值所在。如果你要生成抽象纹理或摄影风景,其中没有任何内容需要清晰可读,那么通用图像模型通常更便宜也更快速。

本文是一篇集成指南,不是模型评测。读完后你将拥有一个可运行的请求、一个执行相同操作的 Python 客户端,以及一个可复用的辅助函数,它能处理人们通常容易出错的部分:宽高比参数、异步任务轮询和输出获取。

有一点需要尽早内化:HiAPI 上的图像生成是一个异步任务 API。你提交请求,拿回一个标识符,然后轮询直到任务完成。那些假设响应体里已经包含图像的代码是行不通的。下面的每一节都在朝这个模式靠拢。

发送请求之前

首次调用之前,需要准备好四样东西。

1. API 密钥

在你的 HiAPI 账户控制台中创建一个,并让它远离源代码管理。把它导出为环境变量,而不是粘贴进脚本:

export HIAPI_API_KEY="your_key_here"

2. 基础 URL

所有请求都发往 HiAPI API 基础 URL,并附加生成端点的具体路径。平台文档会列出当前路径;如果文档说法不同,就不要硬编码你在博客文章(包括本文)里看到的路径。

3. 模型标识符

你在请求体中传入的模型字符串用于标识 ideogram-v4.5。请使用平台模型列表中显示的精确大小写——模型标识符按字面匹配,稍有偏差就会返回验证错误,而不是有用的建议。

4. 参数参考

ideogram-v4.5 的模型页面是请求体接受哪些字段的权威来源:提示词长度限制、支持的宽高比、输出格式,以及任何种子或风格控制。写代码之前先读一遍。那里未列出的参数可能会被静默忽略或拒绝,而猜测取值是浪费调试时间最常见的方式。

有了这四样东西,你就可以发出第一个请求了。

一个可用的 curl 请求

下面是一个最小提交示例。如果你的账户显示的值不同,请替换平台文档中的端点路径和模型标识符。

curl -X POST "$HIAPI_BASE_URL/<generation-path>" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ideogram-v4.5",
    "input": {
      "prompt": "A vintage travel poster for the Amalfi Coast, bold serif headline reading \"AMALFI\", warm sunset palette, grainy print texture"
    }
  }'

各部分的作用:

  • Authorization — bearer token 认证。请求头缺失或格式错误是导致 401 最常见的原因。
  • Content-Type — 必须是 application/json。有些 HTTP 客户端在 POST 时不会自动设置它,导致服务端出现令人困惑的解析错误。
  • model — 字面模型标识符。按文档所示将其放在请求体的顶层。
  • input.prompt — 你的生成指令。如上所示,用引号括起你希望渲染在图像内的文字,这样模型会把它当作字面文案而非描述来处理。
  • input.* — 所有其他生成参数(宽高比、格式、种子等)都属于这个嵌套对象,与 prompt 并列。

成功提交后会返回一个 JSON 对象,其中包含任务标识符和状态字段。这个响应里没有图像——这是预期行为。保存好标识符;轮询步骤会用到它。

用 Python 发出同样的调用

Python 版本是一对一的翻译。我们使用 requests 并共享相同的请求体,方便你并排对比两者。

import os
import json
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"]
GEN_PATH = "/<generation-path>"  # confirm in platform docs

payload = {
    "model": "ideogram-v4.5",
    "input": {
        "prompt": (
            "A vintage travel poster for the Amalfi Coast, bold serif "
            'headline reading "AMALFI", warm sunset palette, grainy print texture'
        )
    },
}

response = requests.post(
    BASE_URL + GEN_PATH,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    data=json.dumps(payload),
    timeout=30,
)
response.raise_for_status()

job = response.json()
print(job)

两个有意的选择:

  • json.dumps 而不是 json= 让传输格式与 curl 示例保持可见地一致。两者都能用;显式写出使调试时更容易检查你实际发送的内容。
  • timeout=30 仅用于提交。提交很快,生成不快。绝不要让提交调用继承为轮询设置的短超时,否则你会把运行正常的任务报成失败。

打印出的 job 字典包含任务标识符和当前状态。把标识符存到某处——轮询循环依赖它。

控制宽高比与输出格式

宽高比和输出格式是请求体参数,不是单独的端点。它们与提示词位于同一个 input 对象中:

{
  "model": "ideogram-v4.5",
  "input": {
    "prompt": "...",
    "aspect_ratio": "<ratio from docs>",
    "output_format": "<format from docs>"
  }
}

这里重要的纪律是不要猜测取值。每个生成模型都暴露固定的比例和格式枚举,而且不同模型接受的拼写方式也不同——16:9 与 16x9、png 与 PNG,等等。传入模型不支持的值通常会产生验证错误,或者更糟,静默回退到默认输出,看起来像你提示词里的 bug。

所以工作流程是:

  1. 在平台上打开 ideogram-v4.5 模型页面,逐字复制支持的宽高比列表和输出格式列表。
  2. 把这些值放进代码中的一个小白名单,让无效输入在调用处就失败,而不是等到 API。
  3. 默认使用与你的下游版式匹配的比例。如果图像要放进 1200×630 的社交卡片位置,就选择接近该比例的值,而不是生成正方形再裁掉内容。

文字密集的图像值得额外提醒一句:极端比例(超宽横幅、超高海报)会压缩可用于渲染文字的空间。对于你确实需要清晰可读的标题,中景横版或竖版比例比全景式极端比例更保险。

处理异步任务并下载结果

一次生成的生命周期分三步:提交 → 轮询 → 获取。

提交

你在前面的小节中已经掌握了这一步。响应会给你一个任务标识符和一个状态,例如 queued 或 processing。

轮询

用该标识符轮询任务状态端点,直到状态报告完成。两条规则让这个过程保持得体:

  • 轮询之间要休眠。 从大约一秒开始并逐步退避。猛敲状态端点不会让任务更快完成,还有触发限流的风险。
  • 限定等待时间。 设置最大尝试次数或截止时间,超限时明确报错,而不是无限循环。
import time

def wait_for_job(job_id, headers, base_url, status_path,
                 max_attempts=60, initial_delay=1.0, factor=1.5):
    delay = initial_delay
    for _ in range(max_attempts):
        r = requests.get(
            f"{base_url}{status_path}/{job_id}",
            headers=headers,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()
        status = data.get("status")
        if status in ("succeeded", "completed", "success"):
            return data
        if status in ("failed", "error", "cancelled"):
            raise RuntimeError(f"job {job_id} ended with status {status}: {data}")
        time.sleep(delay)
        delay *= factor
    raise TimeoutError(f"job {job_id} did not finish in time")

查阅平台文档以获取你账户的精确状态字符串和状态路径——按文档中的值进行匹配,把任何无法识别的状态都当作仍在运行,而不是成功。

获取

当任务报告完成时,响应中包含输出位置(通常是一个 URL)。用普通的 GET 下载它,并把字节写入磁盘。输出 URL 可能有时间限制,所以要尽快下载,而不是把 URL 存起来以后用。编写这个循环所需知道的一切都来自提交响应的结构——没有单独的“获取图像”API 需要学习。

封装成可复用的辅助函数

三个各自重新实现轮询的内联脚本是一个维护问题。把它打包一次。

import os, json, time, requests

class IdeogramClient:
    def __init__(self, base_url, api_key, gen_path, status_path,
                 poll_attempts=60, poll_factor=1.5):
        self.base_url = base_url.rstrip("/")
        self.gen_path = gen_path
        self.status_path = status_path
        self.poll_attempts = poll_attempts
        self.poll_factor = poll_factor
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }

    def generate(self, prompt, **params):
        body = {"model": "ideogram-v4.5", "input": {"prompt": prompt, **params}}
        r = requests.post(self.base_url + self.gen_path,
                          headers=self.headers,
                          data=json.dumps(body), timeout=30)
        r.raise_for_status()
        job = r.json()
        done = self._wait(job["id"])
        url = done["output"]["url"]  # confirm shape in docs
        return self._download(url)

    def _wait(self, job_id):
        delay = 1.0
        for _ in range(self.poll_attempts):
            r = requests.get(f"{self.base_url}{self.status_path}/{job_id}",
                             headers=self.headers, timeout=30)
            r.raise_for_status()
            data = r.json()
            if data.get("status") in ("succeeded", "completed", "success"):
                return data
            if data.get("status") in ("failed", "error", "cancelled"):
                raise RuntimeError(data)
            time.sleep(delay)
            delay *= self.poll_factor
        raise TimeoutError(job_id)

    def _download(self, url):
        r = requests.get(url, timeout=60)
        r.raise_for_status()
        return r.content

使用时只需一次调用:img_bytes = IdeogramClient(...).generate("...", aspect_ratio="<from docs>")。调整 done["output"]["url"] 的访问方式和状态字符串,使其与文档中的响应结构一致——这两处最可能需要按账户微调。

常见错误与调试技巧

第一周的大多数失败都归入五类。

401 / 403 — 认证。 密钥缺失、因复制粘贴带有空白,或缺少 Bearer 前缀。打印你实际发送的密钥的前后各四个字符;环境文件带来的尾部换行是经典元凶。

400 — JSON 格式错误或未知字段。 如果请求体是通过字符串拼接组装的,提示词中未转义的引号会破坏 JSON。把请求体构建为字典并用 json.dumps 序列化。如果 JSON 能解析,下一个嫌疑对象是模型不接受的参数名——逐字符对照模型页面检查你的键。

404 / 模型未找到。 通常是模型标识符拼写或大小写错误,或者端点路径已过时。从平台文档复制这两者,而不是凭记忆或从旧教程里抄。

429 — 限流。 几乎总是因为轮询过于激进。增大初始轮询延迟和退避因子。在提交侧,为 429 和 5xx 响应添加带抖动的重试,但不要重试 4xx 验证错误——它们每次都会以相同方式失败。

任务成功但图像打不开。 检查你下载的是字节而不是 JSON 错误页面;在下载 GET 上调用 raise_for_status() 能捕获大多数这类问题。还要确认你把下载 URL 当作短期有效,而不是跨会话缓存它。

拿不准时,记录整条调用链中每次调用的完整响应体和状态码——提交、每次轮询和下载。API 通常明确说明了哪里出错;bug 通常是我们从没去看。

有了可用的提交、轮询循环和合理的错误处理,ideogram-v4.5 就能像任何其他 HiAPI 模型调用一样接入真实流水线。

立即开始构建持久 AI 产物

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

阅读 API 文档