图像生成 API
Upthos Relay 提供两套图像生成入口,共用同一套鉴权、同一份价格表、同一个上游账号池。按客户端形态二选一:
| 路径 | 模式 | 适用场景 |
|---|---|---|
/v1/images/generations + /v1/images/edits |
同步透传 | 用 OpenAI 官方 SDK,或任何期望标准 {data: [...]} 返回结构的客户端。HTTP 请求阻塞直到上游返回。 |
/v1/images/tasks/* |
异步任务 | 需要中途取消、持久可分享 URL(我们存 R2)、按需开启的流式 partial preview(partial_preview: true),或客户端在 Cloudflare 100s idle 超时墙后面。 |
两条路径完全等价计费:USD 单价 × 图片数 × fx_rate,不打 group_rate —— 订阅档位的折扣(如 Codex Pro 0.5x)不下沉到图像,无论用哪条路径或哪个订阅档位都一样。
鉴权
和其他网关端点一致。Key 通过下面任一 header 传入:
Authorization: Bearer sk-...
x-api-key: sk-...
x-goog-api-key: sk-...
Key 必须挂在 OpenAI 平台分组下(Codex Lite / Pro / Max 等)。Anthropic / Gemini 平台的 key 打这两条路径都会返 404 not_found_error。
同步 API
POST /v1/images/generations
OpenAI Images API 直接兼容。返回上游原生结构(账号选择 + failover 在网关层完成)。
请求体(JSON):
{
"model": "gpt-image-2",
"prompt": "一只赛博朋克风格的猫,霓虹背光",
"n": 1,
"size": "1024x1024",
"quality": "high",
"response_format": "url"
}
| 字段 | 类型 | 说明 |
|---|---|---|
model |
string | gpt-image-2(推荐、默认)、gpt-image-2.5-flare、gpt-image-2.5-sunburst、gpt-image-1.5、gpt-image-1、gpt-image-1-mini、chatgpt-image-latest、dall-e-3 |
prompt |
string | 图像描述,支持 UTF-8 |
n |
int | 张数,默认 1 |
size |
string | 1024x1024 / 1024x1536 / 1536x1024 / auto,按 1K / 2K 档计费 |
quality |
string | low / medium / high / auto,auto 按 medium 查矩阵 |
response_format |
string | url(默认)或 b64_json |
响应(200):标准 OpenAI 结构:
{
"created": 1715478000,
"data": [
{ "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/..." }
]
}
OpenAI Python SDK 示例:
from openai import OpenAI
client = OpenAI(
api_key="sk-...",
base_url="https://relay.upthos.com/v1",
)
resp = client.images.generate(
model="gpt-image-2",
prompt="一只赛博朋克风格的猫,霓虹背光",
size="1024x1024",
quality="high",
n=1,
)
print(resp.data[0].url)
POST /v1/images/edits
同样的鉴权,multipart 请求体。源图通过 image 字段传入(PNG/JPEG/WebP,单 part 上限 4 MB)。可选 mask。其他字段同 /generations:
curl -sS -X POST https://relay.upthos.com/v1/images/edits \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-F "model=gpt-image-2" \
-F "prompt=把背景换成森林" \
-F "size=1024x1024" \
-F "[email protected]"
什么时候不该用同步
- 长任务(
gpt-image-2在high质量下 60–120s)。Cloudflare 100s idle 超时会先把连接踹掉,看不到上游结果。走异步。 - 移动端,应用进后台就丢连接。走异步 + 轮询。
- 要可分享 URL。OpenAI 返的 URL 几小时就过期;异步路径上传 R2,默认保留 30 天。
异步任务 API
任务模型:submit → 立刻拿 task_id → 轮询进度 → status: completed 时拿到 R2 持久 URL。任务能熬过客户端断开、可中途取消,传 partial_preview: true 时还会暴露 partial preview。
POST /v1/images/tasks
提交任务,立刻返回。
curl -sS -X POST https://relay.upthos.com/v1/images/tasks \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "一只赛博朋克风格的猫,霓虹背光",
"size": "1:1",
"resolution": "1k",
"n": 1
}'
请求字段:
| 字段 | 类型 | 说明 |
|---|---|---|
model |
string | 同同步 API 的模型集 |
prompt |
string | UTF-8 描述文本 |
n |
int | 默认 1,支持 1..4。单任务可一次生成多张,前端会渐进交付 |
size |
string | 比例:1:1 / 16:9 / 9:16 / 3:2 / 2:3 / auto |
resolution |
string | 1k(默认)/ 2k / 4k |
image_urls |
string[] | 可选。img2img 参考图,配合 /v1/images/uploads。 |
partial_preview |
bool | 可选,缺省 false。传 true 才向上游请求 partial 帧,并在任务处理中把最新一帧暴露成 progress_image_url。同一张成品图,开预览会让我们从上游拉的字节数约翻三倍,所以只有真的要渲染预览再开。 |
响应(200):
{
"code": 200,
"data": [
{ "status": "submitted", "task_id": "task_01HZQ3R..." }
]
}
Submit 端做余额预检:估算 max cost 超过 key 可用余额时,入队前返 402 INSUFFICIENT_BALANCE。
GET /v1/images/tasks/:id
轮询单个任务。建议节奏:每 3-5 秒一次。
curl -sS https://relay.upthos.com/v1/images/tasks/task_01HZQ3R... \
-H "Authorization: Bearer $UPTHOS_API_KEY"
响应结构:
{
"code": 200,
"data": {
"id": "task_01HZQ3R...",
"status": "completed",
"progress": 100,
"created": 1715478000,
"completed": 1715478060,
"actual_time": 58000,
"estimated_time": 100000,
"result": {
"images": [
{
"url": ["https://r2.upthos.com/..."],
"expires_at": 1718070000
}
]
},
"progress_image_url": null
}
}
status 取值:submitted / processing / completed / failed。
当 status === "processing" 时,progress_image_url 可能带一个中间 preview URL —— 仅限提交时传了 partial_preview: true 的任务。这类任务上游会流式推 partial image,我们逐帧上传 R2 并把最新一帧暴露在这里,前端拿来做渐进式预览,不需要改轮询逻辑。没传这个标志的任务,该字段全程为 null。
失败时 result 改为 error: { code, message, type }:
{
"code": 200,
"data": {
"id": "task_01HZQ3R...",
"status": "failed",
"error": {
"code": "upstream_rate_limit",
"message": "Upstream returned 429 after 3 retries",
"type": "upstream_error"
}
}
}
常见 error.code:
| Code | 含义 |
|---|---|
client_cancelled |
用户调了 /cancel |
worker_timeout |
上游调用超过 worker 单任务超时(默认 15 分钟) |
upstream_rate_limit |
上游 429 多次重试后失败 |
upstream_overload |
上游 529 多次重试后失败 |
upstream_error |
上游通用错误 |
internal_error |
网关侧错误,请提 issue |
POST /v1/images/tasks/batch
最多一次轮 100 个任务。
curl -sS -X POST https://relay.upthos.com/v1/images/tasks/batch \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "ids": ["task_01HZQ3R...", "task_01HZQ4S..."] }'
返回单任务接口的同款结构组成的数组,顺序与入参一致。
POST /v1/images/tasks/:id/cancel
幂等。如果任务还在执行中,会中断上游 HTTP 调用,然后把任务标记 failed,error.code = client_cancelled。对已终止的任务再调没副作用,返 200。
curl -sS -X POST https://relay.upthos.com/v1/images/tasks/task_01HZQ3R.../cancel \
-H "Authorization: Bearer $UPTHOS_API_KEY"
POST /v1/images/uploads —— img2img 参考图上传
把参考图存到 R2,给后续 submit 通过 image_urls[] 引用。返回短期公开 URL(24h TTL)。
curl -sS -X POST https://relay.upthos.com/v1/images/uploads \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-F "[email protected]"
响应:
{
"code": 200,
"data": {
"url": "https://r2.upthos.com/inputs/...",
"expires_at": 1715564400
}
}
注意:
- 单次单文件。PNG / JPEG / WebP。
- 服务端校验上限 2 MiB。建议客户端先压一下,几百 KB 是甜点区。
- URL 公开,别上传你不想分享的东西。
- 拿到
url通过image_urls: ["..."]传给下一个 submit。
什么时候应该用异步
- 长任务会被 CF 100s idle 超时砍掉
- 移动端会进后台
- 要可分享 URL(画廊、历史、社交嵌入)
- 要 partial 预览(
progress_image_url,需显式传partial_preview: true) - 要中途取消(UX 成本:一个按钮)
价格
图像价格按 resolution → 真实 USD 配在「渠道管理 → 渠道定价 → 按图计费」里,乘以图片数和展示 fx_rate(约 6.82 CNY/USD)。结果就是 CNY 零售价。跨分组完全一致,订阅档位的折扣不影响 —— 订阅折扣只作用在文本/代码 token 上。
gpt-image-2 标准价:
| 分辨率 | 实际尺寸 | 单张价格(CNY) |
|---|---|---|
| 1K | 1024×1024 | ¥0.041 |
| 2K | 1024×1536 或 1536×1024 | ¥0.082 |
| 4K | (支持时) | ¥0.123 |
gpt-image-2.5-flare 与 gpt-image-2.5-sunburst 与上表 完全同价(官方 token 费率与 gpt-image-2 一致),同样只看 resolution。
quality 是上游识别字段(low / medium / high / auto),不影响计费,价格只看 resolution。默认开 high 就好。
如果你传的 model 没在渠道定价里配,会回落到老的 image_price_{1k|2k|4k} 分组配置(这条老路径仍然打 group_rate,是历史兼容包袱)。目前所有 gpt-image-* 模型都已在渠道定价里。
错误码对照
| HTTP | Body | 含义 |
|---|---|---|
401 |
authentication_error |
没传 / 传了无效 API key |
402 |
INSUFFICIENT_BALANCE |
估算 cost 超过可用余额(队列前预检) |
403 |
permission_error |
保留位,目前图生没在用 |
404 |
not_found_error |
Key 所在分组不是 OpenAI 平台(比如挂在 Anthropic / Gemini 上) |
413 |
request_entity_too_large |
请求体 > 10 MB。注意部分上游有更紧的 5 MB 墙,base64 大图会先触发——建议先走 /v1/images/uploads 再用 image_urls 引用。 |
429 |
rate_limit_error |
网关层限流命中。退避。 |
503 |
service_unavailable |
Image generation is not enabled on this server —— 异步 worker 没启动;同步路径还能跑。 |
已废弃端点
下面的路径还在工作,但响应带 Deprecation: true + Link: rel="successor-version" header。未来版本会移除,方便时迁一下:
| 已废弃 | 改用 |
|---|---|
GET /v1/tasks/:id |
GET /v1/images/tasks/:id |
POST /v1/tasks/batch |
POST /v1/images/tasks/batch |
POST /v1/tasks/:id/cancel |
POST /v1/images/tasks/:id/cancel |
路径选择速查表
- OpenAI SDK / 标准工具 → 同步
/v1/images/generations。openai-python/openai-node现成代码零改动。 - Codex CLI slash command → 异步
/v1/images/tasks。详见 Codex 图像生成指南。 - Web UI / 带进度条的聊天应用 → 异步 +
progress_image_url轮询。 - 移动端 → 一定异步。
- 后台批量 → 异步 +
/tasks/batch廉价轮询。
两条路径共用上游池,共用价目表 —— 图像本身没有任何差异。