图片编辑 API(图生图)
OpenAI 兼容的图片编辑端点。基于一张源图,按 prompt 生成新图片。支持「锚定图 → 变体」、「人物换装」、「场景替换」等常见图生图场景。
支持 两种调用方式:
- JSON body +
image_key(Picklyone 扩展):先用 文件上传 API 上传图片拿到key,再传image_key调用 - multipart/form-data +
image文件(OpenAI 标准):直接在请求中上传图片文件,兼容 OpenAI SDK 和第三方客户端(如 LobeChat、Cherry Studio)
想做多图合成(多张参考图融合)? 用 图片合成 API — 一次请求最多传 3 张参考图,响应格式与
/v1/images/edits一致。
请求
POST /v1/images/edits
请求头
方式一(JSON):
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
方式二(multipart):
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Content-Type: multipart/form-data
也支持 x-api-key 头(Anthropic SDK 风格)。
请求体
方式一:JSON body(需要先上传图片)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 模型名称,如 gpt-image-2 |
prompt | string | ✅ | 编辑指令,最长 32000 字符(例如 "把背景换成蓝天") |
image_key | string | ⚠️ | 上传得到的 key(形如 files/USER_ID/UUID_xxx.jpg)—— 与 generation_id 二选一 |
generation_id | string | ⚠️ | 之前通过 /v1/images/generations 或 /v1/images/edits 生成的图片 ID(UUID)—— 与 image_key 二选一 |
n | integer | ❌ | 生成数量,默认 1,上限由模型配置决定 |
size | string | ❌ | 图片尺寸,见下方支持列表 |
quality | string | ❌ | 质量等级,如 auto、high、medium、low |
background | string | ❌ | 背景设置,如 auto、transparent、opaque |
output_format | string | ❌ | 输出格式,如 png、jpeg、webp |
response_format | string | ❌ | 返回格式,固定为 b64_json(不暴露外部地址) |
方式二:multipart/form-data(直接上传图片,OpenAI 标准格式)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
image | File | ✅ | 源图片文件(JPEG/PNG/GIF/WebP,最大 25 MB) |
model | string | ✅ | 模型名称,如 gpt-image-2 |
prompt | string | ✅ | 编辑指令 |
n | string | ❌ | 生成数量(字符串形式,如 "1") |
size | string | ❌ | 图片尺寸 |
quality | string | ❌ | 质量等级 |
multipart 模式下系统会自动上传图片到存储,然后执行编辑。单次请求体上限 26 MB。
支持的尺寸
与 图片生成 API 一致——接受任何 auto 或 WIDTHxHEIGHT 格式(字符串 ≤ 16 字符)。完整说明、可用尺寸表、以及超出能力时的退费行为请看 图片生成 API 的"支持的尺寸"小节。
请求示例
使用上传得到的 image_key:
{
"model": "gpt-image-2",
"prompt": "把背景换成黄昏下的城市天际线,保留人物姿态不变",
"image_key": "files/USER_ID/UUID_anchor.jpg",
"n": 1,
"size": "1024x1024"
}
使用已有生成图的 generation_id(链式编辑):
{
"model": "gpt-image-2",
"prompt": "把衣服颜色改成红色",
"generation_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"n": 1
}
响应
{
"created": 1776864985,
"data": [
{
"b64_json": "iVBORw0KGgo..."
}
],
"picklyone_generation_ids": [
"a1b2c3d4-5678-90ab-cdef-1234567890ab"
]
}
picklyone_generation_ids 是本次生成的图片 UUID 列表——可以作为下一次调用 /v1/images/edits 的 generation_id 做链式编辑。
计费方式
与 图片生成 API 完全一致:按次计费,actualCount × price_per_image。预扣费按请求的 n 冻结,结算按实际返回数量收取,差额自动退回。
Python 示例(完整两步流程)
import requests, base64
API_KEY = "pk_live_xxxxxxxxxxxxxxxx"
BASE = "https://api.picklyone.com"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# Step 1: 上传源图
with open("anchor.jpg", "rb") as f:
up = requests.post(
f"{BASE}/api/v1/upload",
headers=HEADERS,
files={"files": f},
).json()
image_key = up["uploaded"][0]["key"]
# Step 2: 调用 edits
resp = requests.post(
f"{BASE}/v1/images/edits",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "gpt-image-2",
"prompt": "把背景换成黄昏下的城市天际线",
"image_key": image_key,
"n": 1,
"size": "1024x1024",
},
).json()
# 保存返回图片
image_data = base64.b64decode(resp["data"][0]["b64_json"])
with open("edited.png", "wb") as f:
f.write(image_data)
cURL 示例
方式一:JSON body(先上传)
# Step 1: 上传源图
UPLOAD=$(curl -sX POST https://api.picklyone.com/api/v1/upload \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
-F "files=@/path/to/anchor.jpg")
IMAGE_KEY=$(echo "$UPLOAD" | jq -r '.uploaded[0].key')
# Step 2: 调用 edits
curl https://api.picklyone.com/v1/images/edits \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"gpt-image-2\",
\"prompt\": \"change background to city skyline at sunset\",
\"image_key\": \"$IMAGE_KEY\",
\"n\": 1
}"
方式二:multipart/form-data(直接上传,OpenAI 标准格式)
curl https://api.picklyone.com/v1/images/edits \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
-F "image=@/path/to/anchor.jpg" \
-F "model=gpt-image-2" \
-F "prompt=change background to city skyline at sunset" \
-F "n=1"
这种方式一步到位,兼容 OpenAI 官方 SDK 以及 LobeChat、Cherry Studio 等第三方客户端。
Node.js 示例
import fs from "fs";
const API_KEY = "pk_live_xxxxxxxxxxxxxxxx";
const BASE = "https://api.picklyone.com";
// Step 1: 上传
const form = new FormData();
form.append("files", new Blob([fs.readFileSync("anchor.jpg")], { type: "image/jpeg" }), "anchor.jpg");
const up = await fetch(`${BASE}/api/v1/upload`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
}).then(r => r.json());
const imageKey = up.uploaded[0].key;
// Step 2: edits
const res = await fetch(`${BASE}/v1/images/edits`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-image-2",
prompt: "change background to city skyline at sunset",
image_key: imageKey,
n: 1,
}),
}).then(r => r.json());
fs.writeFileSync("edited.png", Buffer.from(res.data[0].b64_json, "base64"));
常见错误
| HTTP | code | 说明 |
|---|---|---|
| 400 | invalid_request | 同时传了 image_key 和 generation_id / 都没传 / prompt 为空 |
| 400 | invalid_image_key | image_key 格式错误、包含路径穿越字符、或不是当前用户的 |
| 400 | invalid_generation_id | generation_id 不是有效 UUID |
| 400 | IMAGE_TYPE_UNSUPPORTED | 上传的源图 MIME 类型不支持 |
| 400 | IMAGE_TOO_LARGE | 源图超过 25 MB |
| 400 | content_policy_violation | prompt 触发了内容审查 |
| 401 | invalid_api_key | API Key 无效 |
| 402 | insufficient_balance | 余额不足 |
| 402 | OUTSTANDING_DEBT | 账户有未结清欠款 |
| 404 | generation_not_found | generation_id 不存在或不属于当前用户 |
| 404 | IMAGE_NOT_FOUND | image_key 指向的文件不存在(已删除或未上传) |
| 409 | generation_not_ready | generation_id 对应的源图还在存储中,稍后重试 |
| 429 | rate_limit_exceeded | 请求频率超限 |
| 502 | upstream_error | 服务异常 |
注意事项
- Edits 与 generations 定价完全一致——单次成本相同
- 源图最大 25 MB,Picklyone 不做二次压缩——原始质量完整保留,避免链式编辑时的累积画质损失。源图越大延迟越高,建议控制在 5-10 MB 内
- 源图存储在云端,不会自动删除——如需清理请用文件管理接口或控制台
- 如果源图上传后立刻调 edits 偶尔遇到
409 generation_not_ready,建议延迟 1-2 秒重试 - 非图片模型请用
/v1/chat/completions,别发到这里