POST /v1/images/generations,与 OpenAI 的同名接口一致:
resp = client.images.generate(
model="gpt-image-2.5",
prompt="一只戴着宇航头盔的橘猫,油画质感",
)
image_base64 = resp.data[0].b64_json
curl https://bothub-api.bookab.info/v1/images/generations \
-H "Authorization: Bearer $BOTHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2.5",
"prompt": "一只戴着宇航头盔的橘猫,油画质感"
}'
响应:
{
"created": 1789000000,
"model": "gpt-image-2.5",
"data": [
{
"b64_json": "iVBORw0KGgoAAAANS...",
"url": "https://bothub-api.bookab.info/v1/tasks/<task>/artifacts/<artifact>",
"revised_prompt": "An orange tabby cat wearing an astronaut helmet, oil painting"
}
]
}
默认两种形态都会给:b64_json 是图片字节,url 指向同一张图(下载时同样需要带你的
API Key)。想只要其中一种,传 "response_format": "b64_json" 或 "url"。
生图要花时间,这个 HTTP 请求会一直等到图片生成完,通常几十秒。默认最多等 5 分钟。
所以:把客户端的超时设长一些。OpenAI SDK 的默认超时对生图往往不够:
client = OpenAI(
base_url="https://bothub-api.bookab.info/v1",
api_key="bhk_live_xxxxxxxx",
timeout=600.0, # 秒
)
如果等待超过了上限,你会收到 504 + IMAGE_GENERATION_TIMEOUT——任务并没有被取消,
它还在跑。响应的 detail 里带着 task id,用它去拿结果:
{
"error": {
"message": "Image generation did not finish within 300s. The task is still running — poll GET /v1/tasks/<task> to collect the result.",
"type": "invalid_request_error",
"code": "image_generation_timeout",
"detail": { "taskId": "...", "statusUrl": "/v1/tasks/..." }
}
}
传 n:
{ "model": "gpt-image-2.5", "prompt": "...", "n": 3 }
实际张数受模型本身的上限约束,超出会被截到上限。
不想让请求挂着,就转异步——传 "async": true,或带上请求头 X-BotHub-Async: true:
curl https://bothub-api.bookab.info/v1/images/generations \
-H "Authorization: Bearer $BOTHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-BotHub-Async: true" \
-d '{"model": "gpt-image-2.5", "prompt": "一只橘猫"}'
立刻返回 202:
{
"id": "7f2c...",
"kind": "image",
"status": "pending",
"model": "gpt-image-2.5",
"status_url": "/v1/tasks/7f2c...",
"result_urls": [],
"thumbnail_urls": [],
"error_code": "",
"error_message": ""
}
轮询 GET /v1/tasks/{id} 直到 status 变成 done(或 failed),然后从 result_urls
下载图片(带 API Key)。
images.generate() 解析不了它。
用异步模式时请直接发 HTTP 请求。status 的取值:pending(排队中)、running(生成中)、done、failed。
编辑走原生任务接口 POST /v1/tasks:
curl https://bothub-api.bookab.info/v1/tasks \
-H "Authorization: Bearer $BOTHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "image",
"operation": "edit",
"model": "gpt-image-2.5",
"input": {
"prompt": "把背景换成星空",
"image_urls": ["https://example.com/cat.png"]
}
}'
返回同样是 202 + 任务体,轮询方式与上面一致。
image_urls 里必须是上游能直接读到的地址:公网 URL 或 data: URI。填本地路径
(比如 /Users/me/cat.png)会被拒绝并告诉你原因——它不会被悄悄忽略。POST /v1/videos,视频天然是分钟级的,所以只有异步形态:
curl https://bothub-api.bookab.info/v1/videos \
-H "Authorization: Bearer $BOTHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<视频模型 id>",
"prompt": "一只猫在雪地里奔跑,电影感运镜",
"seconds": 5
}'
返回 202:
{
"id": "9a1b...",
"object": "video",
"status": "queued",
"status_url": "/v1/videos/9a1b...",
"result_url": null,
"error": null
}
GET /v1/videos/{id} — 查状态,status 走 queued → in_progress → completed / failedGET /v1/videos/{id}/content — 完成后下载视频文件生成的任务与产物保留 24 小时,之后会被清理。需要长期保存的话请及时下载。
给 POST /v1/images/generations、/v1/videos、/v1/tasks 带上 Idempotency-Key 请求头,
重复提交同一个 key 会拿回同一个任务,不会重复生成、也不会重复扣费。网络不稳时值得加上。
注意:同一个 key 配上不一样的请求体会返回 409 —— 换请求内容时也要换 key。