外观
图片任务 API
异步图片生成与编辑接口:提交任务 → 轮询状态 → 下载成品。同一个入口 POST /api/v1/image-tasks 同时支持文生图和图生图(编辑),并支持一次传多张参考图(多图编辑)。
启用条件
绑定的 API Key 必须属于一个 OpenAI 平台分组,且该分组同时开启了「图片生成」和「图片任务 API」。
鉴权
http
Authorization: Bearer <你的 API Key>POST /api/v1/image-tasks 还必须带幂等键:
http
Idempotency-Key: <每次请求唯一的字符串>同一个幂等键 + 相同的请求体会返回已存在的任务(不重复生成/扣费)。response_format 在内部会被归一化,所以只改 response_format 仍命中同一任务;改其它字段会返回 409。
提交任务
服务端会自动判断:请求里没有图 → 走文生图;带了 image(可选 mask)→ 走图生图编辑。 客户端只用这一个入口,无需声明意图。不支持 stream。
文生图(不带输入图)
json
{
"model": "gpt-image-2",
"prompt": "赛博修真风格头像,霓虹,放松氛围",
"size": "1024x1024",
"n": 1,
"response_format": "url"
}图生图 / 多图编辑(带输入图)
三种格式任选其一,image 都可以是单张或多张:
① JSON + 图片 URL(服务端转发时自动下载):
json
{
"model": "gpt-image-2",
"prompt": "给主体加一圈霓虹光环",
"image": "https://your-cdn/source.png",
"size": "1024x1024"
}② JSON + base64 / dataURL(本地图,无需公网 URL):
json
{
"model": "gpt-image-2",
"prompt": "去掉背景",
"image": "data:image/png;base64,iVBORw0KGgo...",
"mask": "data:image/png;base64,iVBORw0KGgo..."
}③ 多张参考图:image 传字符串数组即可(URL / base64 混用都行):
json
{
"model": "gpt-image-2",
"prompt": "把这几张图融合成一张海报",
"image": [
"https://your-cdn/a.png",
"data:image/png;base64,iVBORw0KGgo...",
"https://your-cdn/c.jpg"
],
"size": "1024x1536"
}④ multipart 上传(与 OpenAI /v1/images/edits 的 form-data 一致):
http
POST /api/v1/image-tasks
Content-Type: multipart/form-data; boundary=...
Authorization: Bearer <你的 API Key>
Idempotency-Key: order-10001-image-1表单字段:model、prompt、可选 size/n/quality、文件 [email protected]、可选 [email protected]。 多张参考图:重复 image[][email protected] 多个文件部分(也接受 image[0]=@...、image[1]=@... 这种带下标的名字)。
三种格式落库时都会归一化成同一份 JSON,幂等哈希在归一化之后计算:同一批图片不论走 multipart 还是 base64,视为同一请求(URL 形式按 URL 文本独立哈希,不下载后再比)。
请求体字段
| 字段 | 含义 | 说明 |
|---|---|---|
model | 模型名 | 如 gpt-image-2、gpt-image-1 |
prompt | 提示词 | 文生图必填;编辑时描述要做的改动 |
image | 输入图 | 字符串或字符串数组;URL / base64 / dataURL 均可。多张=数组(多图编辑) |
mask | 蒙版 | 可选,作用于第一张 image;不能单独传 mask |
size | 输出尺寸 | 见下「尺寸与宽高比」。透传上游,按尺寸计费 |
n | 生成张数 | 默认 1。n>1 需分组账号支持(高级能力) |
quality | 质量 | 透传上游(如 high/medium/low,依模型而定) |
response_format | 返回形态 | url(返回本地文件链接)或 b64_json(内联 base64) |
尺寸与宽高比
size 写 宽x高 即可,支持任意宽高比(方/横/竖屏)。服务端按最长边归入计费档: ≤1024 = 1K,≤2048 = 2K,更大 = 4K(也接受直接写 1k/2k/4k 或 auto)。常用值:
| 比例 | 1K | 2K | 4K |
|---|---|---|---|
| 1:1 方形 | 1024x1024 | 2048x2048 | — |
| 16:9 横屏 | 1792x1024 | 2048x1152 | 3840x2160 |
| 9:16 竖屏 | 1024x1792 | 1152x2048 | 2160x3840 |
| 3:2 / 2:3 | 1536x1024 / 1024x1536 | — | — |
| 4:3 / 3:4 | 1024x768 / 768x1024 | — | — |
一次请求只能指定一个
size(OpenAI 协议如此)。需要多个规格 = 用不同size多发几次请求; 需要多张同尺寸结果 = 用n。
提交返回
json
{
"object": "image_task",
"task_id": "imgtask_4d89a5f68d2e44d4a1ab6b6e4a7b12e9",
"status": "queued",
"model": "gpt-image-2",
"image_size": "1K",
"image_count": 1,
"billing": { "status": "not_billed", "customer_cost": 0.04 },
"created_at": "2026-05-15T12:00:00Z"
}轮询任务
http
GET /api/v1/image-tasks/{task_id}
Authorization: Bearer <你的 API Key>成功后按你提交时的 response_format 返回。response_format: "url" 时:
json
{
"status": "succeeded",
"image_size": "1K",
"image_count": 1,
"billing": { "status": "settled", "customer_cost": 0.04 },
"result": {
"created": 1780000000,
"data": [{ "url": "https://你的站点/api/v1/image-tasks/imgtask_4d.../files/0.png" }]
}
}省略或 b64_json 时,data 内联返回 { "b64_json": "iVBORw0KGgo..." }。
下载图片文件
http
GET /api/v1/image-tasks/{task_id}/files/{idx}.{ext}
Authorization: Bearer <你的 API Key>idx:data[]里的序号,从 0 开始;ext:png/jpg/jpeg/webp/gif。- 与轮询同样校验 API Key 归属;带
ETag、Cache-Control: private。
保留期与过期
成品落本地磁盘,默认保留 3 天、总容量上限 1 GiB,先到者触发清理,最老任务被删、状态转 expired:
json
{ "status": "expired", "error": { "code": "expired", "message": "image files have been deleted by retention policy" } }请在窗口内下载/转存。极少数情况下上游成功+已扣费但本地落盘失败,任务为 succeeded_storage_failed。
Python 完整示例(多图编辑 + 指定尺寸 + 轮询下载)
下面这段已实测跑通:读本地多张图 → 多图编辑 → 轮询到成功 → 下载成品。
python
import base64, mimetypes, time, uuid, requests
BASE = "https://hub.nocannobb.com"
KEY = "sk-你的Key"
s = requests.Session()
s.headers.update({
"Authorization": f"Bearer {KEY}",
# 若脚本被 Cloudflare 拦(返回 error 1010),带一个常规 User-Agent 即可
"User-Agent": "Mozilla/5.0",
})
def data_url(path):
mime = mimetypes.guess_type(path)[0] or "image/jpeg"
with open(path, "rb") as f:
return f"data:{mime};base64," + base64.b64encode(f.read()).decode()
payload = {
"model": "gpt-image-2",
# 多张参考图就传数组(URL 或 base64/dataURL 混用都行)
"image": [data_url("a.jpg"), data_url("b.jpg"), data_url("c.jpg")],
"prompt": "把这几款浴巾整齐挂在原木晾杆上,暖调婴儿房背景,柔和治愈。"
"不要出现:水印、错误文字、混乱背景。",
"size": "1024x1536", # 任意 宽x高;竖屏/横屏/方形都行
"n": 1,
"response_format": "url",
}
# 提交(每次唯一 Idempotency-Key)
r = s.post(f"{BASE}/api/v1/image-tasks", json=payload,
headers={"Idempotency-Key": str(uuid.uuid4())})
task_id = r.json()["task_id"]
print("task_id:", task_id)
# 轮询到终态
while True:
time.sleep(4)
t = s.get(f"{BASE}/api/v1/image-tasks/{task_id}").json()
print("status:", t["status"])
if t["status"] in ("succeeded", "failed", "expired", "succeeded_storage_failed"):
break
# 下载成品
for i, d in enumerate(t.get("result", {}).get("data", [])):
if d.get("url"):
img = s.get(d["url"]).content
open(f"out_{i}.png", "wb").write(img)
print("saved out_%d.png" % i)文生图(不带
image)把image字段去掉即可,其余相同。
避坑
- 多张图就用
image数组(或 multipart 重复image[])——不是只能传一张。 - 负面词不要用
--no:gpt-image 不认 Midjourney 语法,写成自然语言「不要出现 X」才有效。 - 精确版式靠后期:gpt-image 擅长场景/风格/构图,但「把文字放到某个角」「预留 logo 区域」这类像素级排版不保证执行,建议出图后用设计工具叠加 logo/文字。
- 不是同步直返:提交拿
task_id,要轮询到succeeded再取result/下载,别期望提交就返回图。 size写宽x高,任意比例都行;一次一个 size,多规格就多发请求。mask必须配image一起传,不能单独传。- 每次提交必须带唯一
Idempotency-Key;复用同键+同体会返回旧任务。