返回首页

图片合成 API

把 1~3 张参考图与一段 prompt 组合,让模型综合生成一张新图。常见用法:把人物 A 放进场景 B、把多个产品组合在同一画面、风格迁移合成等。

想做单张图编辑?图片编辑 API — 单图换装、场景替换、变体等。

纯文生图?图片生成 API

适用场景对比

场景推荐端点协议
纯文生图/v1/images/generationsJSON
单图编辑/v1/images/editsJSON + image_keygeneration_id
多图合成/v1/images/composeJSON + image_keys[] / generation_ids[] / image_urls[](1~3 张)

请求

POST /v1/images/compose

请求头

Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

也支持 x-api-key 头(Anthropic SDK 风格)。

请求体

参数类型必填说明
modelstring模型名称,如 gpt-image-2
promptstring文本指令,最长 32000 字符
image_keysstring[]⚠️通过 文件上传 API 得到的 R2 key 列表 — 与 generation_ids / image_urls 至少三选一
generation_idsstring[]⚠️之前通过 /v1/images/{generations,edits,compose} 生成的图片 UUID 列表 — 与 image_keys / image_urls 至少三选一
image_urlsstring[]⚠️内联图片列表 — 每项是 https://... URL 或 data:image/(jpeg|png|gif|webp);base64,<数据> 形式的 data URI;无需先调用文件上传。与 image_keys / generation_ids 至少三选一
ninteger生成数量,默认 1,上限由模型配置决定
sizestring图片尺寸,与 图片生成 API 一致

参考图总数:image_keys.length + generation_ids.length + image_urls.length 必须在 1~3 之间。三个数组可以混用。同一张图(包括跨数组)重复引用会被拒绝。

image_urls 安全限制:

  • https:// URL 必须使用 HTTPS,Picklyone 会拒绝私网 / loopback / link-local / CGN 等内部地址,拒绝跳转、拒绝携带凭据(user:pass@host 形式),响应 Content-Type 必须是 image/(jpeg\|png\|gif\|webp),30 秒超时,单图最大 25MB。
  • data: URI 必须是 data:image/(jpeg\|png\|gif\|webp);base64,... 的合法 base64,字符串长度上限 35MB,解码后字节上限 25MB,Picklyone 会校验文件头魔数是否与声明的 MIME 一致。
  • 内联图片直接走 Workers 内存,不会写入 R2、不会消耗你的 200MB 文件配额、也不会出现在 /api/images/history

完整示例

引用之前生成的两张图做合成:

{
  "model": "gpt-image-2",
  "prompt": "把图1的人物放进图2的场景里,保留服装,光照统一",
  "generation_ids": [
    "00000000-0000-0000-0000-000000000001",
    "00000000-0000-0000-0000-000000000002"
  ],
  "n": 1
}

混用上传图 + 生成图:

{
  "model": "gpt-image-2",
  "prompt": "把这个 logo 印在产品上,在白色木桌背景前展示",
  "image_keys": ["files/<userId>/<key>.png"],
  "generation_ids": ["<uuid>"],
  "n": 1
}

直接传 base64 内联图片(不需要预先上传):

{
  "model": "gpt-image-2",
  "prompt": "把图1的人物放进图2的场景里,保留服装,光照统一",
  "image_urls": [
    "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...",
    "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
  ],
  "n": 1
}

或者传公网 HTTPS URL:

{
  "model": "gpt-image-2",
  "prompt": "把人物放进这个场景",
  "image_urls": [
    "https://example.com/portrait.jpg",
    "https://example.com/scene.jpg"
  ],
  "n": 1
}

响应

{
  "created": 1776864985,
  "data": [
    {
      "b64_json": "iVBORw0KGgo...",
      "revised_prompt": "..."
    }
  ],
  "picklyone_generation_ids": ["00000000-0000-0000-0000-000000000099"]
}
字段类型说明
data[i].b64_jsonstringbase64 编码的 PNG(无 data: 前缀,可直接 base64 解码)
data[i].revised_promptstring | null模型重写后的 prompt(仅供调试,可能为 null)
picklyone_generation_ids[i]string本次生成图的 UUID,可作为下一次 /v1/images/{compose,edits} 调用的 generation_id 引用做链式合成

计费

按次计费,与 图片生成 API 一致:actualCount × price_per_image。预扣按请求的 n 冻结,结算按实际返回数量收取,差额自动退回。

Python 示例

import requests, base64

API_KEY = "pk_live_xxxxxxxxxxxxxxxx"
BASE = "https://api.picklyone.com"

resp = requests.post(
    f"{BASE}/v1/images/compose",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "model": "gpt-image-2",
        "prompt": "把图1的人物放进图2的场景里",
        "generation_ids": [
            "00000000-0000-0000-0000-000000000001",
            "00000000-0000-0000-0000-000000000002",
        ],
        "n": 1,
    },
    timeout=300,
).json()

for i, item in enumerate(resp.get("data", [])):
    if item.get("b64_json"):
        with open(f"out_{i}.png", "wb") as f:
            f.write(base64.b64decode(item["b64_json"]))
        print(f"saved out_{i}.png — generation_id: {resp['picklyone_generation_ids'][i]}")

cURL 示例

curl https://api.picklyone.com/v1/images/compose \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "把图1的人物放进图2的场景里",
    "generation_ids": [
      "00000000-0000-0000-0000-000000000001",
      "00000000-0000-0000-0000-000000000002"
    ]
  }'

Node.js 示例

import fs from "fs";

const API_KEY = "pk_live_xxxxxxxxxxxxxxxx";
const BASE = "https://api.picklyone.com";

const resp = await fetch(`${BASE}/v1/images/compose`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-image-2",
    prompt: "...",
    image_keys: ["files/<userId>/<key>.png"],
    generation_ids: ["<uuid>"],
    n: 1,
  }),
}).then(r => r.json());

for (const [i, item] of resp.data.entries()) {
  if (item.b64_json) {
    fs.writeFileSync(`out_${i}.png`, Buffer.from(item.b64_json, "base64"));
  }
}

限制

限制
请求 body 最大100 MB(为内联 image_urls 留空间;若只用 image_keys/generation_ids 实际不会用到)
单张参考图最大25 MB(R2 来源 + 内联同口径)
单条 image_urls 数据 URI 字符串35 MB(对应解码后约 25 MB)
单条 image_urls HTTPS URL2048 字符
参考图合计最大30 MB(R2 + 内联累计)
参考图总数1~3(image_keys + generation_ids + image_urls 合计)
一次请求图片数由模型 max_n_per_request 决定(n 超过会 400 invalid_request)
响应超时通常 30-90 秒
速率限制30 请求/分钟/用户(与其他图片端点共享)

错误码

HTTPcode说明
400invalid_request字段格式错 / n 超出 / size 格式错
400invalid_source参考图 0 张或超过 3 张,或者三个数组都没传
400invalid_image_keyimage_key 格式不对或不属于调用方
400invalid_generation_idgeneration_id 不是合法 UUID
400invalid_urlimage_urls 条目不是 https://data:image/...,或 URL 长度超过 2048 字符
400invalid_data_uriimage_urls 中的 data URI 格式不合法(MIME 不在白名单内,或 base64 主体缺失)
400image_too_largeimage_urls 数据 URI 字符串超过 35MB,或解码后超过 25MB
400MAGIC_MISMATCHimage_urls 的实际文件头与声明的 MIME 不一致(防止 MIME 伪造)
400IMAGE_TYPE_UNSUPPORTEDimage_urls 远端响应的 Content-Type 不在 image/(jpeg|png|gif|webp) 白名单中
400NON_HTTPS / BLOCKED_HOST / PRIVATE_IP / REDIRECT_BLOCKED / NOT_IMAGE / TOO_LARGE / UPSTREAM_ERRORimage_urls 远端 URL SSRF/拉取检查失败(详见上方安全限制)
400IMAGES_TOO_LARGE_TOTAL三种来源累加超过 30MB
400duplicate_reference同一张图被引用了多次(image_keys 内、generation_ids 内、image_urls 内,或跨 image_keysgeneration_ids)
400content_policy_violationprompt 触发内容审查(已退预扣)
400no_image_generated模型对模糊 prompt 无图返回(已退预扣)
401invalid_api_keyAPI Key 无效
402insufficient_balance余额不足
404model_not_found模型不存在或未激活
404generation_not_foundgeneration_ids 中某个 UUID 不存在或不属于调用方
408upstream_timeout请求超时(已退预扣)
409generation_not_ready引用的 generation_id 还在生成中 — 稍后重试
413image_too_large单条 data URI 字符串超过 35MB(请求被早拒,未计费)
422generation_not_ready引用的 generation_id 是失败的 generation,无法用作参考
429rate_limit_exceeded速率限制
502upstream_error服务异常(已退预扣)

注意事项

  • 响应中的 b64_json 是裸 base64(不带 data:image/png;base64, 前缀),可以直接 Buffer.from(b64, "base64") 或 Python base64.b64decode(b64) 解码
  • 图片自动入库 — 此端点会把生成的图片自动持久化到 Picklyone 历史记录,可在 /api/images/history 查询。响应里的 picklyone_generation_ids 是入库的 UUID
  • 链式合成 — 把上一次返回的 picklyone_generation_ids[i] 作为下一次调用的 generation_id,即可在同一组上下文里逐步迭代

相关端点