Appearance
GPT-Image-2 图片生成 API
gpt-image-2 是 1XM.AI 支持的 OpenAI 兼容图片模型,适合文本生图、图片编辑、产品图、海报图、插画和文档配图等场景。
接入信息
| 项目 | 值 |
|---|---|
| Base URL | https://api.1xm.ai/v1 |
| 生成端点 | POST /images/generations |
| 编辑端点 | POST /images/edits |
| 异步任务创建 | POST /images/tasks |
| 异步任务查询 | GET /images/tasks/{task_id} |
| 模型名 | gpt-image-2 |
| 认证方式 | Authorization: Bearer sk-你的Key |
提示
图片 API 使用 OpenAI 兼容格式。已有 OpenAI SDK 的项目通常只需要替换 api_key 和 base_url。
同步和异步怎么选
| 场景 | 推荐接口 |
|---|---|
| 后端脚本、小图测试、内部低频调用 | 同步接口:POST /images/generations 或 POST /images/edits |
| 4K 图片、图片编辑、多参考图、多张输出 | 异步任务:POST /images/tasks |
| 面向客户的网页、SaaS、自动化平台 | 异步任务:POST /images/tasks |
| 你的服务或域名经过 Cloudflare 等代理 | 异步任务:POST /images/tasks |
如果你要把 1XM 图片能力卖给下游客户,建议默认接入异步任务 API。同步接口在长耗时任务中可能受到代理超时影响;异步接口会先返回任务 ID,图片完成后通过轮询或 webhook 获取结果。
文本生成图片
cURL
bash
curl -X POST https://api.1xm.ai/v1/images/generations \
-H "Authorization: Bearer sk-你的Key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "一张干净的科技产品海报,白色背景,蓝色半透明智能音箱,商业摄影风格",
"size": "1024x1024",
"quality": "high",
"output_format": "png",
"n": 1
}'Python SDK
python
import base64
from openai import OpenAI
client = OpenAI(
api_key="sk-你的Key",
base_url="https://api.1xm.ai/v1"
)
result = client.images.generate(
model="gpt-image-2",
prompt="一张干净的科技产品海报,白色背景,蓝色半透明智能音箱,商业摄影风格",
size="1024x1024",
quality="high",
output_format="png",
)
image_base64 = result.data[0].b64_json
with open("gpt-image-2-output.png", "wb") as f:
f.write(base64.b64decode(image_base64))Node.js SDK
javascript
import fs from 'fs';
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'sk-你的Key',
baseURL: 'https://api.1xm.ai/v1'
});
const result = await client.images.generate({
model: 'gpt-image-2',
prompt: '一张干净的科技产品海报,白色背景,蓝色半透明智能音箱,商业摄影风格',
size: '1024x1024',
quality: 'high',
output_format: 'png'
});
const imageBase64 = result.data[0].b64_json;
fs.writeFileSync('gpt-image-2-output.png', Buffer.from(imageBase64, 'base64'));图片编辑
图片编辑接口使用 multipart/form-data,可以上传一张或多张参考图。
cURL
bash
curl -X POST https://api.1xm.ai/v1/images/edits \
-H "Authorization: Bearer sk-你的Key" \
-F "model=gpt-image-2" \
-F "prompt=保持主体形状不变,把材质改成拉丝金属,背景保持简洁" \
-F "image[][email protected]" \
-F "size=1024x1024" \
-F "quality=high" \
-F "output_format=png"兼容提示
如果你使用的客户端或网关不接受 image[] 字段名,可以尝试改成 image。
Python SDK
python
import base64
from openai import OpenAI
client = OpenAI(
api_key="sk-你的Key",
base_url="https://api.1xm.ai/v1"
)
with open("input.png", "rb") as image:
result = client.images.edit(
model="gpt-image-2",
image=image,
prompt="保持主体形状不变,把材质改成拉丝金属,背景保持简洁",
size="1024x1024",
quality="high",
output_format="png",
)
image_base64 = result.data[0].b64_json
with open("edited.png", "wb") as f:
f.write(base64.b64decode(image_base64))常用参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 固定填写 gpt-image-2 |
prompt | string | ✅ | 图片生成或编辑指令 |
size | string | ❌ | 图片尺寸,支持 auto 或符合约束的分辨率 |
quality | string | ❌ | auto、high、medium、low |
n | integer | ❌ | 返回图片数量 |
output_format | string | ❌ | png、jpeg、webp |
output_compression | integer | ❌ | 仅适用于 jpeg / webp |
background | string | ❌ | auto 或 opaque;gpt-image-2 不支持透明背景 |
moderation | string | ❌ | auto 或 low |
image[] | file | 编辑时必填 | 编辑接口的输入图片 |
mask | file | ❌ | 局部编辑时使用的遮罩图 |
尺寸规则
gpt-image-2 支持 auto,也支持自定义分辨率。自定义尺寸需要满足:
| 规则 | 要求 |
|---|---|
| 最大边长 | 不超过 3840px |
| 边长倍数 | 宽高都必须是 16 的倍数 |
| 长宽比 | 长边 / 短边不超过 3:1 |
| 总像素 | 不少于 655,360,不超过 8,294,400 |
常用尺寸:
text
1024x1024
1536x1024
1024x1536
2048x2048
2048x1152
3840x2160
2160x3840
auto官方异步任务 API
gpt-image-2 的 4K 生成、图片编辑、多参考图融合等请求可能耗时较长,常见耗时可能超过 120 秒。1XM 已提供官方异步任务 API,适合下游客户、SaaS、网页工具和经过 Cloudflare 的长耗时场景。
关于 Cloudflare 524
如果你用同步 HTTP 请求一直等待图片生成完成,长耗时任务可能遇到 524: A timeout occurred。这通常不是模型失败,而是代理层在固定等待窗口内没有收到完整响应。异步任务 API 会先返回 task_id,生成过程在后台执行,不需要让客户端长时间挂住连接。
如果你要在 Agent / Codex / Skill 工作流里直接接入异步生图,可以使用 1XM 官方示例 Skills 仓库:
text
https://github.com/coolyhx/1xm-agent-skills调用流程
mermaid
sequenceDiagram
participant C as 客户服务端
participant A as 1XM API
participant W as 1XM Worker
participant R as R2 图片存储
C->>A: POST /v1/images/tasks
A-->>C: 202 queued + task_id + poll_url
W->>W: 后台调用 gpt-image-2
W->>R: 保存生成图片
C->>A: GET /v1/images/tasks/{task_id}
A-->>C: succeeded + data[].url创建任务
bash
curl -X POST "https://api.1xm.ai/v1/images/tasks" \
-H "Authorization: Bearer sk-你的Key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_20260507_0001" \
-d '{
"model": "gpt-image-2",
"prompt": "一张适合电商落地页的高端龙虾海报,写实摄影风格",
"size": "3840x2160",
"quality": "high",
"output_format": "png",
"n": 1,
"webhook_url": "https://client.example.com/webhooks/1xm-image",
"webhook_secret": "client-side-secret"
}'成功创建后返回 202 Accepted:
json
{
"id": "task_xxx",
"object": "image.task",
"status": "queued",
"poll_url": "https://api.1xm.ai/v1/images/tasks/task_xxx",
"poll_after": 5,
"created_at": 1778120861,
"expires_at": 1778207261
}字段说明:
| 字段 | 说明 |
|---|---|
id | 任务 ID,客户系统应保存到自己的订单或业务记录里 |
status | 当前任务状态,创建后通常是 queued |
poll_url | 查询任务状态的完整 URL |
poll_after | 建议下次轮询间隔,单位秒 |
expires_at | 任务结果建议保留到期时间 |
带参考图创建异步编辑任务
异步任务也支持参考图。请求仍然是 POST /v1/images/tasks,区别是 JSON 里传 image 字段;image 可以是一个 data URL 字符串,也可以是 data URL 数组。服务端会自动按图片编辑任务处理,最终仍返回 data[].url。
bash
IMAGE_DATA_URL="data:image/png;base64,$(base64 -i input.png | tr -d '\n')"
MASK_DATA_URL="data:image/png;base64,$(base64 -i mask.png | tr -d '\n')"
curl -X POST "https://api.1xm.ai/v1/images/tasks" \
-H "Authorization: Bearer sk-你的Key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_20260507_edit_0001" \
-d "{
\"model\": \"gpt-image-2\",
\"prompt\": \"保持产品主体外观不变,换成高级电商白底摄影风格\",
\"image\": [\"${IMAGE_DATA_URL}\"],
\"mask\": \"${MASK_DATA_URL}\",
\"size\": \"1024x1024\",
\"quality\": \"high\",
\"output_format\": \"png\",
\"n\": 1
}"参考图规则:
| 字段 | 说明 |
|---|---|
image | data URL 字符串或数组,例如 data:image/png;base64,... |
mask | 可选 data URL 字符串,用于局部编辑;传 mask 时必须同时传 image |
| 支持格式 | image/png、image/jpeg、image/webp |
| 默认数量上限 | 单次最多 10 张参考图 |
| 默认大小上限 | 单张参考图最大 20MB |
| 远程 URL | 异步 JSON 任务不直接抓取远程图片;请由客户服务端先下载并转成 data URL |
查询任务
bash
curl "https://api.1xm.ai/v1/images/tasks/task_xxx" \
-H "Authorization: Bearer sk-你的Key"处理中:
json
{
"id": "task_xxx",
"object": "image.task",
"status": "running",
"poll_after": 5,
"created_at": 1778120861,
"started_at": 1778120863,
"expires_at": 1778207261
}成功:
json
{
"id": "task_xxx",
"object": "image.task",
"status": "succeeded",
"data": [
{
"url": "https://img.1xm.ai/generated/task_xxx_0.png",
"revised_prompt": "..."
}
],
"usage": {
"model": "gpt-image-2",
"images": 1,
"billed_quota": 50000
}
}失败:
json
{
"id": "task_xxx",
"object": "image.task",
"status": "failed",
"error": {
"code": "image_task_failed",
"message": "upstream timeout"
}
}任务状态:
| 状态 | 含义 |
|---|---|
queued | 已创建,等待后台 worker 处理 |
running | 正在调用 gpt-image-2 |
succeeded | 生成成功,data[].url 可直接访问 |
failed | 生成失败,系统会按失败路径处理退款 |
Node.js 接入示例
javascript
const API_KEY = process.env.ONE_XM_API_KEY;
async function createImageTask(payload, orderId) {
const res = await fetch('https://api.1xm.ai/v1/images/tasks', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId
},
body: JSON.stringify(payload)
});
const body = await res.json();
if (!res.ok && res.status !== 202) {
throw new Error(body.error?.message || 'create image task failed');
}
return body;
}
async function pollImageTask(pollUrl) {
while (true) {
const res = await fetch(pollUrl, {
headers: { Authorization: `Bearer ${API_KEY}` }
});
const task = await res.json();
if (task.status === 'succeeded') return task.data[0].url;
if (task.status === 'failed') {
throw new Error(task.error?.message || 'image task failed');
}
const waitSeconds = task.poll_after || 5;
await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
}
}
const task = await createImageTask({
model: 'gpt-image-2',
prompt: '一张高端龙虾电商海报,写实摄影风格',
size: '3840x2160',
quality: 'high',
output_format: 'png',
n: 1
}, 'order_20260507_0001');
const imageUrl = await pollImageTask(task.poll_url);
console.log(imageUrl);带参考图时,把文件转成 data URL 后传 image:
javascript
import { readFile } from 'node:fs/promises';
async function fileToDataUrl(path, mime = 'image/png') {
const data = await readFile(path);
return `data:${mime};base64,${data.toString('base64')}`;
}
const editTask = await createImageTask({
model: 'gpt-image-2',
prompt: '保持参考图人物身份不变,生成一张高级商务头像',
image: [await fileToDataUrl('./input.png')],
// 局部编辑时可选:
// mask: await fileToDataUrl('./mask.png'),
size: '1024x1024',
quality: 'high',
output_format: 'png',
n: 1
}, 'order_20260507_edit_0001');Python 接入示例
python
import os
import time
import requests
API_KEY = os.environ["ONE_XM_API_KEY"]
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"Idempotency-Key": "order_20260507_0001",
}
create_resp = requests.post(
"https://api.1xm.ai/v1/images/tasks",
headers=headers,
json={
"model": "gpt-image-2",
"prompt": "一张高端龙虾电商海报,写实摄影风格",
"size": "3840x2160",
"quality": "high",
"output_format": "png",
"n": 1,
},
timeout=30,
)
create_resp.raise_for_status()
task = create_resp.json()
while True:
query_resp = requests.get(
task["poll_url"],
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
query_resp.raise_for_status()
current = query_resp.json()
if current["status"] == "succeeded":
print(current["data"][0]["url"])
break
if current["status"] == "failed":
raise RuntimeError(current.get("error", {}).get("message", "image task failed"))
time.sleep(current.get("poll_after", 5))带参考图时:
python
import base64
from pathlib import Path
def file_to_data_url(path: str, mime: str = "image/png") -> str:
data = Path(path).read_bytes()
return f"data:{mime};base64,{base64.b64encode(data).decode()}"
payload = {
"model": "gpt-image-2",
"prompt": "保持参考图产品造型不变,生成一张高级电商白底图",
"image": [file_to_data_url("input.png")],
# 局部编辑时可选:
# "mask": file_to_data_url("mask.png"),
"size": "1024x1024",
"quality": "high",
"output_format": "png",
"n": 1,
}Webhook 回调
创建任务时可选传入:
| 字段 | 说明 |
|---|---|
webhook_url | 任务完成或失败后,1XM 会向该 URL 发送 POST |
webhook_secret | 用于签名校验,建议每个客户或业务线独立配置 |
回调请求会带两个 Header:
| Header | 说明 |
|---|---|
X-1XM-Timestamp | Unix 时间戳 |
X-1XM-Signature | sha256=<HMAC_SHA256(timestamp + "." + raw_body)> |
Node.js 校验示例:
javascript
import crypto from 'crypto';
function verify1xmWebhook(rawBody, timestamp, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}回调和轮询可以同时使用
建议你的服务端同时支持 webhook 和轮询。webhook 用于快速更新业务状态,轮询作为兜底,避免客户侧 webhook 临时不可达时任务结果丢失。
幂等与重试
Idempotency-Key 建议必传。它用于处理网络重试、客户服务重启、前端重复点击等场景。
| 场景 | 建议 |
|---|---|
| 同一个订单重复提交 | 使用同一个 Idempotency-Key,会返回同一个任务 |
| 客户端请求超时但不确定是否创建成功 | 用同一个 Idempotency-Key 重试创建 |
| 用户主动重新生成一张新图 | 使用新的 Idempotency-Key |
推荐格式:
text
order_<你的订单ID>
image_<业务ID>_<版本号>轮询频率和超时
- 创建任务接口只负责入队,客户端超时设置
10-30 秒即可。 - 查询任务时使用返回的
poll_after,默认约5 秒,不要每秒高频刷接口。 - 你的业务系统可以为 4K 或多参考图任务预留
5-10 分钟。 - 如果用户刷新页面,应能通过你保存的
task_id继续查询。 - 不要把 1XM API Key 写进浏览器前端代码;面向用户的产品应由你的服务端调用 1XM。
图片结果存储
异步任务成功后返回的是可直接访问的图片 URL:
text
https://img.1xm.ai/generated/task_xxx_0.png这些图片由 1XM 保存到对象存储并通过 CDN 访问。你可以直接把 URL 返回给下游客户;如果你的业务有长期归档、私有访问或水印要求,也可以在任务成功后把图片下载到你自己的对象存储。
不支持或不建议的参数
| 参数/用法 | 说明 |
|---|---|
input_fidelity | gpt-image-2 不支持 |
background=transparent | gpt-image-2 不支持透明背景 |
| 把图片模型当聊天模型调用 | 请使用 /images/generations 或 /images/edits |
错误排查
| 现象 | 排查方向 |
|---|---|
401 Unauthorized | 检查 API Key 是否正确,Header 是否是 Authorization: Bearer sk-xxx |
model not found | 确认模型名是 gpt-image-2 |
| 尺寸参数报错 | 检查宽高是否为 16 的倍数、总像素和长宽比是否符合规则 |
| 编辑接口上传失败 | 同步编辑检查 multipart/form-data;异步任务检查 image 是否是合法 data URL |
| 透明背景失败 | 改用 background=auto 或 background=opaque |
524 或客户端等待超时 | 改用 POST /images/tasks 创建异步任务,不要长时间等待同步请求 |
轮询返回 404 task_not_found | 确认查询时使用的是创建任务的同一个 API Key |
| webhook 没收到 | 确认 webhook_url 可公网访问,并用轮询作为兜底 |
推荐实践
- 提示词尽量描述主体、风格、构图、背景、光线和用途。
- 面向下游客户售卖时,默认使用官方异步任务 API。
- 有参考图时仍然优先使用异步任务 API,在 JSON 中传
imagedata URL 数组。 - 创建任务时保存
task_id、poll_url、你的订单 ID 和Idempotency-Key。 - 生成产品图、海报图时优先使用
quality=high;内部测试可用quality=low降低等待时间。 - Web 展示优先使用
webp或jpeg,需要无损或后期处理时使用png。 - 图片编辑时,指令应明确说明“哪些保持不变、哪些需要修改”。
- API Key 不要写入前端代码,建议使用服务端代理或环境变量。
- webhook 和轮询同时接入:webhook 提升完成通知速度,轮询保证结果可恢复。