ai-api 图片转发网关 · 接口文档
对外一个极简接口做图片生成;内部转发到 highwayapi / otuapi,单入口 + 自动故障转移,出图落地成本站稳定 URL。
概览
| 基址 | https://ai-api.dahe2016.com |
|---|---|
| 数据格式 | 请求/响应均为 application/json(图生图的参考图可传 URL 或 base64) |
| 调用方只需关心 | 提示词 prompt + 比例 ratio + 文生图/图生图 mode(+ 尺寸档 size / 张数 n) |
| 多渠道容错(对调用方透明) | 后端多渠道互为备份;某渠道故障时网关自动切换到可用渠道出图再返回,你完全无需感知、也无需做任何处理,照常拿 data[].url 即可。 |
鉴权
除只读/页面类端点外,写操作需在请求头带网关 key:
复制Authorization: Bearer <你的网关KEY>
key 错误或缺失 → 401。新增/吊销 key 由服务端 .env 管理(一行一个,行首加 # 即吊销)。
生成图片
POST/v1/images
请求字段
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
prompt | string | 必填 | — | 文本提示词,中英文均可 |
model | string | 可选 | gpt-image-2 | gpt-image-2(快,~20–90s)/ banana(Nano Banana 2,画质强但走异步任务、可能 2–4 分钟,客户端超时设 ≥300s) |
ratio | string | 可选 | 3:4 | 比例,取值见下;auto=交给模型判断。banana 目前主用渠道仅 1:1 / 9:16 / 16:9 / auto,其余按 auto |
mode | string | 可选 | t2i | t2i=文生图 / i2i=图生图 |
image | string | string[] | i2i 必填 | — | 参考图,单张或数组。三种都行:在线 URL / DataURL(data:image/png;base64,...)/ 裸 base64(无在线图、只有本地文件时直接传 base64 即可,网关会自动识别图片类型补成 DataURL) |
size | string | 可选 | 1k | 尺寸档 1k/2k/4k。2k/4k 仅 highwayapi 支持,otuapi 一律按 1k |
n | integer | 可选 | 1 | 出图数 [1, 10]。网关对上游并发 n 次单图请求,绝不传 N |
ratio 取值: auto1:13:44:32:33:29:1616:91:22:11:33:19:2121:9
示例 · 文生图(curl)
复制curl -X POST https://ai-api.dahe2016.com/v1/images \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"小红书封面 香港保险避坑 扁平插画 红黄撞色大标题","ratio":"3:4","n":2}'
示例 · 图生图(curl)
复制curl -X POST https://ai-api.dahe2016.com/v1/images \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"mode":"i2i","image":"https://example.com/ref.jpg","prompt":"改成夜景霓虹风格","ratio":"3:4"}'
没有在线 URL(只有本地图)时,把 image 换成图片的 base64 即可,例如 Python:image = base64.b64encode(open("a.png","rb").read()).decode() 再放进 body。
Python
复制import httpx
r = httpx.post(
"https://ai-api.dahe2016.com/v1/images",
headers={"Authorization": "Bearer "+KEY},
json={"prompt":"...", "ratio":"3:4", "n":1},
timeout=320)
for it in r.json()["data"]:
print(it["url"])
JavaScript (fetch)
复制const r = await fetch("/v1/images", {
method:"POST",
headers:{ "Content-Type":"application/json",
"Authorization":"Bearer "+KEY },
body: JSON.stringify({prompt:"...", ratio:"3:4", n:1})
});
const d = await r.json();
console.log(d.data.map(x=>x.url));
响应
响应体永远是 JSON。HTTP 状态:200=至少 1 张成功(可能部分失败,看 errors)|502=全部失败|400=参数错误|401=key 无效。
下面这个例子请求 2 张(n=2),成功 1 张、失败 1 张——同时展示 data[] 和 errors[] 两种结构:
复制{
"created": 1782286822,
"ratio": "3:4", "mode": "t2i", "size": "1k",
"requested": 2, "succeeded": 1, "failed": 1,
"data": [
{
"url": "https://ai-api.dahe2016.com/img/5a8e1395abcd.png",
"provider": "otuapi",
"upstream_size": "auto",
"width": 1086, "height": 1448,
"bytes": 2000215, "elapsed_ms": 51000
}
],
"errors": [
{
"index": 1,
"tried": [
{ "channel": "otuapi", "error": "HTTP 403: insufficient_user_quota" },
{ "channel": "highwayapi", "error": "failed after 4 retries: HTTP 504" }
],
"elapsed_ms": 62000
}
]
}
顶层字段
| 字段 | 类型 | 说明 |
|---|---|---|
created | int | 生成时间戳(秒) |
ratio / mode / size | string | 本次实际使用的比例 / 模式 / 尺寸档(回显) |
requested | int | 请求张数(= 入参 n) |
succeeded | int | 成功张数(= data 长度) |
failed | int | 失败张数(= errors 长度) |
data | array | 成功的图,每项见下;全失败时为 [] |
errors | array | 失败的图,每项见下;全成功时为 [] |
data[] — 每张成功图
| 字段 | 类型 | 说明 |
|---|---|---|
url | string | 本站稳定链接,永久有效,可直接 <img src> 引用(这是你要用的图片地址) |
provider | string | 实际出图渠道:otuapi 或 highwayapi(故障转移时可能是备用渠道,对你无影响) |
upstream_size | string | 上游实际 size 参数:otuapi 恒为 auto(比例靠提示词控);highwayapi 为精确像素如 1536x2048 |
width / height | int | 成品图真实像素 |
bytes | int | 图片字节大小 |
elapsed_ms | int | 这张图耗时(毫秒) |
errors[] — 每个失败项
| 字段 | 类型 | 说明 |
|---|---|---|
index | int | 这是第几张(从 0 起) |
tried | array | 各渠道的尝试记录 [{channel, error}],主备都试过的报错都在里面,便于排查 |
elapsed_ms | int | 这张图耗时(毫秒) |
data[] 取每个 url 即可(succeeded 张)。要严谨就判一下 failed>0 时看 errors[].index 知道哪几张没出、为什么。图片托管
GET/img/{filename} — 网关把上游图下载落地后,以本站稳定 URL 提供(免鉴权,可直接 <img> 引用)。
url 不会过期。落地图超过 IMAGE_TTL_DAYS 天会被自动清理(默认 7 天)。健康检查
GET/healthz
复制{ "ok":true, "primary":"highwayapi", "order":["highwayapi","otuapi"],
"failover":true, "available":["highwayapi","otuapi"],
"gateway_keys":1, "auth":"enabled", "otu_key":true, "hw_key":true }
请求统计
按网关 key(标签)统计请求次数 + 出图成功/失败数 + 各渠道分担。统计随每次 /v1/images 累加,持久化、重启不丢。可视化见 /admin。
GET/v1/stats — 读取统计(需 KEY)
复制{
"since": 1782200000,
"total": { "requests": 128, "images_ok": 240, "images_failed": 3 },
"by_key": {
"default": { "requests": 100, "images_ok": 190, "images_failed": 2, "last_ts": 1782284733 },
"partner1": { "requests": 28, "images_ok": 50, "images_failed": 1, "last_ts": 1782280000 }
},
"by_channel": { "highwayapi": 230, "otuapi": 10 }
}
POST/v1/stats/reset — 清零(需 KEY,用于新计费周期)
by_key 的标签 = .env 里 AIAPI_KEY_标签=token 的标签部分。key 只在 .env 维护(一行一个、# 吊销),网页不配置 key。比例 ↔ 后端 映射参考
调用方只传 ratio,网关按下表翻译。highwayapi 走精确 size,otuapi 走提示词描述。
| ratio | highwayapi · 1k size | highwayapi · 2k | highwayapi · 4k | otuapi |
|---|---|---|---|---|
| 1:1 | 1024x1024 | 2048x2048 | — | 统一 size:auto+ 比例进提示词 (约 1k 原生分辨率, 如 3:4 出 1086×1448) |
| 3:4 | 1536x2048 | — | 2160x3840 | |
| 4:3 | 2048x1536 | — | 3840x2160 | |
| 9:16 | 1152x2048 | 1152x2048 | 2160x3840 | |
| 16:9 | 2048x1152 | 2048x1152 | 3840x2160 | |
| 2:3 | 1024x1536 | — | — | |
| 3:2 | 1536x1024 | — | — | |
| 21:9 | 2048x880 | — | — | |
| 9:21 | 880x2048 | — | — |
注:highwayapi 某档无对应精确尺寸时回退到 1k 表;再没有则用 auto + 提示词兜底。1:2 / 2:1 / 1:3 / 3:1 也支持(1k)。
错误与坑
| HTTP | 含义 |
|---|---|
| 200 | 至少 1 张成功(也可能部分失败,看 errors[]) |
| 400 | 参数错误(ratio/size 不支持、i2i 缺 image、n 超限等) |
| 401 | 网关 key 错误或缺失 |
| 502 | 全部渠道都失败(errors[] 有每个渠道的报错) |
- 延迟:单张约 20–90s(同步出图 = 整张图生成时间);客户端超时建议 ≥300s。
- 并发:对外可并发;网关对上游始终 n=1 多次请求(传 N 会掉质量)。
- 冷启动 504:highwayapi 偶发,网关已自动重试 3 次;仍失败才转备用。
- 图别长期引用上游链:用网关返回的
url(本站落地,永久有效)。