图片生成

POST /v1/images/generations

OpenAI 兼容的图片生成接口,当前主力模型为 gpt-image-2。支持同步与异步两种模式:

  • 同步:一次请求阻塞到出图,直接返回图片(适合低并发、即时场景)。
  • 异步:提交后立即拿到任务 ID,再轮询取结果(适合大批量、避免长连接超时)。

可用模型

模型 分辨率档位 说明
gpt-image-2 1K / 2K / 4K 主力模型,通用生图与编辑。
gpt-image-2.5 1K 仅 1K 档位。
gpt-image-2.5-flare 1K / 2K / 4K 日常生图,出图更快。
gpt-image-2.5-sunburst 1K / 2K / 4K 精准编辑,擅长按指令改图。
flux-3-image 768 / 1K / 1.5K / 2K / 4K 文生图与参考图编辑,默认 1.5K,按成功请求计费。见 FLUX.3 接入指南。

以上模型均支持两种用法:

  • 文生图:POST /v1/images/generations(同步)或 POST /v1/images/generations/async(异步)。
  • 图生图:POST /v1/images/edits(同步)或 POST /v1/images/edits/async(异步),以 multipart 形式上传 image 与 prompt,尺寸/分辨率参数与文生图完全一致。

兼容写法:gpt-image-2-2K / gpt-image-2-4K 这两个模型名仍然可用,便于已有集成继续调用,它们分别等价于 gpt-image-2 搭配 resolution 为 2K / 4K。新接入建议统一使用 gpt-image-2 + 参数的写法。

下文的分辨率对照表、默认 1K 和参考图限制主要适用于 GPT 图片模型。flux-3-image 默认 1.5K、最多 10 张参考图、不支持 mask,尺寸规则与按请求计费方式请参见 FLUX.3 接入指南。

如何选择分辨率档位

gpt-image-2 支持 1K / 2K / 4K 三个分辨率档位——用同一个模型名,通过参数选择,不需要换模型。有两种等价写法:

  • resolution(推荐):直接指定档位 1K / 2K / 4K;画幅比例另用 size 指定,或不传(默认方图 1:1)。
  • size:传该档位对应的像素尺寸(见下方对照表),网关据此同时确定档位与画幅比例。
目标 请求体写法
1K(默认) 不传尺寸参数,或 "resolution": "1K"
2K 方图 "resolution": "2K",或 "size": "2048x2048"
2K 横图 16:9 "resolution": "2K", "size": "2560x1440",或直接 "size": "2560x1440"
4K 方图 "resolution": "4K",或 "size": "2880x2880"
4K 横图 16:9 "resolution": "4K", "size": "3840x2160",或直接 "size": "3840x2160"

gpt-image-2.5-flare / gpt-image-2.5-sunburst 用法完全相同;gpt-image-2.5 仅支持 1K。

同步:POST /v1/images/generations

请求参数

参数 类型 必填 说明
model string 是 模型 ID,如 gpt-image-2。
prompt string 是 图片描述提示词。
n integer 否 生成数量,当前仅支持 1(默认 1)。
size string 否 图片尺寸,格式为 宽x高,如 1024x1024、2560x1440、3840x2160,也可传 auto。它同时决定画幅比例与分辨率档位(见下方档位对照表)。不在对照表中的尺寸按像素面积归入档位:≤ 2,000,000 归为 1K;≤ 5,000,000 归为 2K;≤ 9,000,000 归为 4K;更大则返回 400。
resolution string 否 分辨率档位,取值 1K / 2K / 4K(大小写不敏感;也接受别名 image_size)。优先级高于 size 隐含的档位;与 size 搭配使用可固定画幅比例、单独指定档位。若指定的档位该模型不支持,返回 400。
quality string 否 画质档。gpt-image-2.5 系列取值为 low / medium / high / xhigh / max / auto;gpt-image-2 可选传入,当前不改变出图效果。该参数不影响分辨率档位。
response_format string 否 返回形式:b64_json(默认,图片以 base64 内联在 JSON 里)或 url(返回一个约 2 小时有效的下载链接,见下文「响应」)。传其他值返回 400。

档位优先级:resolution > size 隐含的档位 > 默认 1K。

提示:图片较大(2K/4K)或并发较高时,建议传 "response_format": "url",响应体只有几百字节,客户端按需下载图片即可。

分辨率档位对照表

画幅比例 1K 2K 4K
1:1 1024×1024 2048×2048 2880×2880
16:9 1280×720 2560×1440 3840×2160
9:16 720×1280 1440×2560 2160×3840
3:2 1248×832 2496×1664 3504×2336
2:3 832×1248 1664×2496 2336×3504
4:3 1152×864 2304×1728 3264×2448
3:4 864×1152 1728×2304 2448×3264
5:4 1120×896 2240×1792 3200×2560
4:5 896×1120 1792×2240 2560×3200
21:9 1456×624 3024×1296 3696×1584

模型按所选档位与画幅比例的原生分辨率出图,因此返回图片的实际像素尺寸可能与请求的 size 略有出入。

计费说明

图片生成的计费单位与单价以你所在站点的「定价说明」和 Portal 定价页为准。响应中的 usage 反映本次生成的 token 用量,可作为对账参考;档位越高,生成的图片越大,费用也相应更高。

请求示例

cURL

curl https://api.modeltap.net/v1/images/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a red fox running in snow, studio lighting",
    "n": 1
  }'

cURL(用 size 指定 16:9 的 2K)

curl https://api.modeltap.net/v1/images/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a red fox running in snow, studio lighting",
    "size": "2560x1440",
    "n": 1
  }'

cURL(用 resolution 单独指定档位)

curl https://api.modeltap.net/v1/images/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-image-2.5-flare",
    "prompt": "a red fox running in snow, studio lighting",
    "size": "1024x1024",
    "resolution": "2K",
    "n": 1
  }'

Python

import openai
 
client = openai.OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.modeltap.net/v1",
)
 
resp = client.images.generate(
    model="gpt-image-2",
    prompt="a red fox running in snow, studio lighting",
    n=1,
)
b64 = resp.data[0].b64_json   # base64 编码的 PNG

OpenAI SDK 没有 resolution 这个原生字段,通过 extra_body 传入即可:

resp = client.images.generate(
    model="gpt-image-2",
    prompt="a red fox running in snow, studio lighting",
    size="1024x1024",
    n=1,
    extra_body={"resolution": "2K"},
)

图生图:POST /v1/images/edits

以 multipart/form-data 形式上传原图与提示词,返回格式与同步文生图相同(base64 内联)。

参数 类型 必填 说明
image file 是 输入图片,PNG / JPEG / WEBP,单张不超过 25 MB,整个请求合计不超过 32 MB。多张参考图时重复传 image[](或多个 image),最多 8 张。
prompt string 是 编辑指令,描述要怎么改。
model string 是 模型 ID,如 gpt-image-2、gpt-image-2.5-sunburst(擅长按指令改图)。
n integer 否 生成数量,当前仅支持 1。
size / resolution / quality string 否 与文生图语义一致,见上文参数表与档位对照表。

暂不支持 mask(蒙版)参数,传入会返回错误;请用 prompt 描述要修改的区域。

图生图单次通常需要 1–3 分钟,高峰期可能更久。客户端读超时建议不低于 15 分钟,否则可能在出图前主动断开;也可以改用下文的异步图生图接口。

参考图也可以直接传图片链接或 data URL(JSON 写法,不用上传文件),同步和异步接口都支持,详见文末「用链接传参考图」一节。

cURL(单张图)

curl https://api.modeltap.net/v1/images/edits \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F image=@input.png \
  -F model=gpt-image-2.5-sunburst \
  -F prompt="turn the sky into a starry night, keep the fox unchanged" \
  -F resolution=2K

cURL(多张参考图,16:9 横图)

curl https://api.modeltap.net/v1/images/edits \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image[]=@product.png" \
  -F "image[]=@background.jpg" \
  -F model=gpt-image-2 \
  -F prompt="place the product from the first image onto the scene in the second image" \
  -F size=2560x1440

Python

import base64
import openai
 
client = openai.OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.modeltap.net/v1",
    timeout=900,   # 图生图耗时较长,读超时至少 15 分钟
)
 
with open("input.png", "rb") as f:
    resp = client.images.edit(
        model="gpt-image-2.5-sunburst",
        image=f,                      # 多张参考图传列表: image=[f1, f2]
        prompt="turn the sky into a starry night, keep the fox unchanged",
        extra_body={"resolution": "2K"},
    )
 
with open("output.png", "wb") as out:
    out.write(base64.b64decode(resp.data[0].b64_json))

响应

返回 base64 内联的图片:

{
  "created": 1730000000,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA...",
      "revised_prompt": "..."
    }
  ],
  "usage": {
    "input_tokens": 18,
    "input_tokens_details": {
      "image_tokens": 0,
      "text_tokens": 18
    },
    "output_tokens": 7024,
    "output_tokens_details": {
      "image_tokens": 7024,
      "text_tokens": 0
    },
    "total_tokens": 7042
  }
}

前端展示时加前缀:data:image/png;base64,<b64_json>。

传 "response_format": "url" 时,返回下载链接而不是 base64:

{
  "created": 1730000000,
  "data": [
    {
      "url": "https://<bucket>.r2.cloudflarestorage.com/...&X-Amz-Signature=...",
      "revised_prompt": "..."
    }
  ],
  "usage": { "...": "与上面相同" }
}

链接约 2 小时有效,请在有效期内下载或转存;图片在 48 小时后删除。图片已生成但链接暂时无法生成时(极少见),返回 502 且不计费,可以直接重试。


异步:POST /v1/images/generations/async

请求体与同步文生图完全一致(model / prompt / n / size / resolution / quality,语义与上文相同),但立即返回任务 ID,不阻塞出图。适合批量生成或客户端不希望长连接等待的场景。

本节是异步文生图。异步图生图见文末「异步图生图」一节。

1. 提交任务

curl https://api.modeltap.net/v1/images/generations/async \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a red fox running in snow",
    "size": "2560x1440",
    "n": 1
  }'

返回 202 Accepted:

{
  "id": "nximg_xxxxxxxx",
  "status": "queued",
  "created": 1730000000,
  "object": "image.generation.async"
}

2. 轮询结果:GET /v1/images/generations/async/{job_id}

curl https://api.modeltap.net/v1/images/generations/async/nximg_xxxxxxxx \
  -H "Authorization: Bearer YOUR_API_KEY"

status 取值:queued → processing → succeeded(或 failed)。建议每 1–2 秒轮询一次,通常数秒到数十秒完成。

进行中:

{ "id": "nximg_xxxxxxxx", "status": "processing", "created": 1730000000 }

完成:

{
  "id": "nximg_xxxxxxxx",
  "status": "succeeded",
  "created": 1730000000,
  "data": [
    {
      "url": "https://<bucket>.r2.cloudflarestorage.com/...&X-Amz-Signature=...",
      "revised_prompt": "..."
    }
  ],
  "usage": {
    "input_tokens": 18,
    "input_tokens_details": {
      "image_tokens": 0,
      "text_tokens": 18
    },
    "output_tokens": 7024,
    "output_tokens_details": {
      "image_tokens": 7024,
      "text_tokens": 0
    },
    "total_tokens": 7042
  }
}

失败:

{
  "id": "nximg_xxxxxxxx",
  "status": "failed",
  "created": 1730000000,
  "error": { "type": "upstream_error", "message": "generation failed", "code": "..." }
}

关于 url:与同步返回内联 base64 不同,异步成功时返回一个带签名的下载链接(有效期约 2 小时)。请在有效期内下载/转存,过期需重新生成。失败任务不计费。

参数说明

字段 说明
id 任务 ID(nximg_ 前缀),用于轮询。与你的 API Key 所属组织绑定,他人无法访问。
status queued / processing / succeeded / failed。
data[].url 成功时的图片下载链接(presigned,约 2h 有效)。
data[].revised_prompt 模型改写后的提示词(可能为空)。
usage 成功时返回,结构与同步一致。

异步图生图:POST /v1/images/edits/async

同步图生图 POST /v1/images/edits 的异步版本。请求格式完全相同(multipart/form-data 上传文件,或 JSON 写法传图片链接,参数见上文「图生图」一节),但立即返回任务 ID,出图后再轮询取结果。图生图耗时较长(通常 1–3 分钟),批量或不想长时间保持连接时推荐使用。

与同步图生图的区别:

  • 输入图片最多 8 张,单张不超过 25 MB,整个请求合计不超过 32 MB。
  • 不支持 mask,传入会直接返回 400。
  • 成功时返回带签名的下载链接(约 2 小时有效),不是内联 base64。

1. 提交任务

curl https://api.modeltap.net/v1/images/edits/async \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F image=@input.png \
  -F model=gpt-image-2 \
  -F prompt="turn the sky into a starry night, keep the fox unchanged" \
  -F resolution=2K

多张参考图时重复传 image[](或多个 image),与同步接口一致。

返回 202 Accepted:

{
  "id": "nximg_xxxxxxxx",
  "status": "queued",
  "created": 1730000000,
  "object": "image.edit.async"
}

2. 轮询结果:GET /v1/images/edits/async/{job_id}

curl https://api.modeltap.net/v1/images/edits/async/nximg_xxxxxxxx \
  -H "Authorization: Bearer YOUR_API_KEY"

返回格式与异步文生图完全相同(queued → processing → succeeded / failed,成功时 data[].url 为下载链接,并附 usage)。建议每 2–5 秒轮询一次。异步文生图和异步图生图的任务 ID 通用,也可以用 GET /v1/images/generations/async/{job_id} 查询。

Python 示例

import time
import requests
 
API = "https://api.modeltap.net/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
 
# 1. 提交任务(多张参考图: files=[("image[]", f1), ("image[]", f2)])
with open("input.png", "rb") as f:
    job = requests.post(
        f"{API}/images/edits/async",
        headers=HEADERS,
        files=[("image", ("input.png", f, "image/png"))],
        data={
            "model": "gpt-image-2",
            "prompt": "turn the sky into a starry night, keep the fox unchanged",
            "resolution": "2K",
        },
        timeout=120,
    ).json()
 
# 2. 轮询结果
while True:
    r = requests.get(f"{API}/images/edits/async/{job['id']}", headers=HEADERS, timeout=30).json()
    if r["status"] in ("succeeded", "failed"):
        break
    time.sleep(3)
 
if r["status"] == "succeeded":
    img = requests.get(r["data"][0]["url"], timeout=120).content   # 链接约 2 小时有效
    open("output.png", "wb").write(img)
else:
    print(r["error"])

用链接传参考图(JSON 写法)

适用于 POST /v1/images/edits(同步)和 POST /v1/images/edits/async(异步)。图片已经在对象存储、CDN 或图床上时,不必先下载再上传,直接把链接放进 JSON 请求体即可。

工作方式:网关收到请求后先下载并校验每一张参考图,全部合格才会开始出图。任何一张有问题,都会在出图前返回 400,不计费。这样可以避免「链接失效,却生成了一张和参考图无关的图并被收费」的情况。

请求格式

  • 请求头:Content-Type: application/json(不能与 multipart 混用,一个请求只能用一种写法)。
  • 请求体参数:
参数 类型 必填 说明
model string 是 模型 ID,如 gpt-image-2。
prompt string 是 编辑指令。多张参考图时,可以用「第一张图」「第二张图」指代,顺序与 images 数组一致。
images array 是 参考图列表,最多 8 张,每一项的写法见下表。
size / resolution / quality string 否 与文生图语义一致,见上文参数表与档位对照表。
response_format string 否 b64_json(默认)或 url。仅同步接口有效;异步接口始终返回链接。
n integer 否 当前仅支持 1。

不支持 mask,传入会返回 400。

images 每一项的写法

以下写法都可以,也可以在同一个数组里混用:

写法 示例
图片链接(字符串) "https://cdn.example.com/product.png"
data URL(字符串) "data:image/png;base64,iVBORw0KGgo..."
OpenAI 风格对象 {"image_url": "https://cdn.example.com/product.png"}
OpenAI 风格嵌套对象 {"image_url": {"url": "https://cdn.example.com/product.png"}}

也可以用 image 字段代替 images,值可以是单个字符串或数组。

链接要求

项目 要求
协议与端口 只支持 https://,且必须是默认端口 443;不支持 http://,也不支持在链接里写端口号。
地址 必须是公网可直接访问的域名;不能是 IP 地址、localhost 或内网地址。
访问权限 网关下载时不带任何 Cookie、登录态或自定义请求头。需要登录才能看的图片、开启了防盗链(校验 Referer)的图片都会下载失败;私有对象请提供带签名的临时链接(如 S3 / OSS / COS / R2 的预签名 URL)。
重定向 不跟随重定向。短链、需要跳转的分享链接会被拒绝,请提供跳转后的最终图片地址。
格式 只接受 PNG / JPEG / WEBP。按文件内容判断格式,不看链接后缀和对方返回的 Content-Type;GIF、HEIC、SVG、BMP 会被拒绝。
大小 单张不超过 25 MB,所有参考图合计不超过 64 MB。
下载超时 连接 5 秒,单张图片下载总时长 30 秒;超时即报错。
签名链接有效期 同步接口:请求发出时有效即可。异步接口:提交任务时就会下载参考图,所以链接只需在提交时有效,不必覆盖整个排队和出图时间。

建议:参考图尽量先压缩再传,每张控制在 2 MB 以内(例如转成长边不超过 2048 像素的 JPEG)。图片越小,提交越快、出图成功率越高,高峰期尤其明显。

data URL 要求

  • 格式必须是 data:image/png;base64,...、data:image/jpeg;base64,... 或 data:image/webp;base64,...。
  • base64 必须合法,声明的类型必须与实际内容一致(例如声明 image/png 但内容是 JPEG,会被拒绝)。
  • data URL 计入整个请求 32 MB 的上限,base64 编码会让体积增大约 1/3,所以单张原图最好不超过约 20 MB;大图建议改用链接。

把本地文件转成 data URL:

import base64
 
def to_data_url(path: str) -> str:
    data = open(path, "rb").read()
    if data.startswith(b"\x89PNG"):
        mime = "image/png"
    elif data.startswith(b"\xff\xd8\xff"):
        mime = "image/jpeg"
    elif data[:4] == b"RIFF" and data[8:12] == b"WEBP":
        mime = "image/webp"
    else:
        raise ValueError("只支持 PNG / JPEG / WEBP")
    return f"data:{mime};base64,{base64.b64encode(data).decode()}"

示例

cURL:同步,两张参考图(一张链接,一张 data URL),返回链接

curl https://api.modeltap.net/v1/images/edits \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "把第一张图里的产品放到第二张图的场景中,保持产品外观不变",
    "images": [
      "https://cdn.example.com/product.png",
      "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
    ],
    "size": "2560x1440",
    "response_format": "url"
  }'

Python:同步

import requests
 
API = "https://api.modeltap.net/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
 
r = requests.post(
    f"{API}/images/edits",
    headers=HEADERS,
    json={
        "model": "gpt-image-2",
        "prompt": "把天空改成星空,其余保持不变",
        "images": ["https://cdn.example.com/photo.jpg"],
        "response_format": "url",
    },
    timeout=900,   # 图生图耗时较长,读超时至少 15 分钟
)
d = r.json()
if r.status_code != 200:
    raise RuntimeError(d["error"]["message"])      # 例如 "images[0]: host cdn.example.com answered HTTP 404"
img = requests.get(d["data"][0]["url"], timeout=120).content   # 链接约 2 小时有效
open("output.png", "wb").write(img)

Python:异步

import time
import requests
 
API = "https://api.modeltap.net/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
 
r = requests.post(
    f"{API}/images/edits/async",
    headers=HEADERS,
    json={
        "model": "gpt-image-2",
        "prompt": "把天空改成星空,其余保持不变",
        "images": ["https://cdn.example.com/photo.jpg"],
    },
    timeout=120,
)
job = r.json()
if r.status_code != 202:                       # 参考图有问题时,提交阶段就返回 400
    raise RuntimeError(job["error"]["message"])
 
while True:
    res = requests.get(f"{API}/images/edits/async/{job['id']}", headers=HEADERS, timeout=30).json()
    if res["status"] in ("succeeded", "failed"):
        break
    time.sleep(3)

报错对照

参考图有问题时,返回 HTTP 400,error.type 为 invalid_request_error。针对某一张图的错误,message 以 images[序号]: 开头(序号从 0 开始,对应 images 数组中的位置),后面是具体原因;针对整个请求的错误(如张数超限、传了 mask、没有传图片)没有序号前缀。报错里只会出现域名,不会回显完整链接。

message 中的原因 含义 处理方法
only https:// URLs are accepted 链接不是 https 改用 https 链接
only the default https port 443 is allowed 链接里带了端口号 去掉端口,使用标准 https 地址
URL host must be a domain name, not an IP 链接里是 IP 地址 改用域名
URL host is not a public hostname / resolves to a non-public address 是 localhost、内网域名,或域名解析到了内网地址 使用公网可访问的地址
could not resolve host ... 域名无法解析 检查域名拼写
answered with a redirect (3xx) 链接发生了跳转 改用跳转后的最终地址
answered HTTP 403 / answered HTTP 404 等 对方拒绝访问或文件不存在(常见于防盗链、需要登录、签名链接已过期) 确认链接可以匿名直接打开;私有文件请用未过期的预签名链接
timed out fetching from host ... / could not fetch from host ... 下载超时或连接失败 确认对方服务可用、下载速度足够,或改用 data URL
content is not a PNG, JPEG or WebP image 下载到的内容不是支持的图片(例如 HTML 页面、GIF、HEIC) 确认链接直接指向图片文件,并转换为 PNG / JPEG / WEBP
image larger than ... bytes / images exceed ... bytes in total 单张超过 25 MB,或合计超过 64 MB 压缩图片或减少张数
data URL must be data:image/(png|jpeg|webp);base64, / data URL is not valid base64 / data URL content is not a valid image/... data URL 格式不对、base64 不合法,或声明类型与内容不符 按上文「data URL 要求」生成
too many images (max 8) 参考图超过 8 张 减少到 8 张以内
mask is not supported with a JSON body 传了 mask 去掉 mask,用 prompt 描述要修改的区域
images is required (a list of image URLs or data URLs) 没有传图片,或 images 为空数组 至少传一张参考图

计费

  • 参考图校验失败:不出图,不计费。
  • 校验通过后出图成功:与上传文件的写法计费完全相同。