文档
图像生成
两个端点:文生图和图像编辑 / 图生图。两者都会返回永久有效的结果 URL:Kunavo 会将每张图像归档到自己的 CDN。
Kunavo 提供 /v1/images/generations(文生图)和 /v1/images/edits(图生图 / 编辑)端点。默认情况下,两者都是同步的——调用会一直阻塞,直到上游处理完成,然后返回结果 URL;也可以通过 "async": true 或 webhook_url 使用 异步模式。
文生图
端点:POST /v1/images/generations。使用 OpenAI SDK 的 images.generate 方法,或直接使用 curl。
img = client.images.generate(
model="nano-banana-pro",
prompt="a red origami crane on a white desk, soft window light",
size="1024x1024",
)
print(img.data[0].url)常用参数
| 参数 | 类型 | 备注 |
|---|---|---|
model | string | /v1/models 中的任意图像模型 slug。 |
prompt | string | 文本提示词。始终必填。 |
size | string | OpenAI 风格的 "1024x1024"。会映射为上游的宽高比。 |
quality | standard|hd | 在支持的模型中使用(gpt-image)。 |
resolution | 1K|2K|4K | 分层模型的解析等级 — 见下文的 Resolution tiers。按等级计费。 |
n | int | 图像数量。大多数模型无论如何都只返回 1 张。 |
input | object | 备用方案 — 见下文的 Raw input。 |
files.kunavo.com 链接:Kunavo 会将每张图像归档到自己的 CDN,因此与原始上游 URL 不同,它们永不过期。如果某张图像未能归档,它的 URL 就是上游的临时 URL,位于其他域名下:请下载该图像并重新托管。分辨率档位
若干图像模型按输出分辨率分档计价。传入 resolution 选择档位;省略时则使用默认档位。实际计费以生成的档位为准。
| 模型(及其 -edit 变体) | 档位——各档价格 | 默认值 |
|---|---|---|
| nano-banana-2 | 1K $0.0469 · 2K $0.0707 · 4K $0.1057 | 1K |
| nano-banana-pro | 1K / 2K $0.067 · 4K $0.12 | 2K |
| gpt-image-2 | 1K / 2K / 4K — $0.0633(统一价格) | 1K |
veo-3 系列也按分辨率分档;各档价格请见每个模型的 /models 页面。
resolution = 4K 且尺寸为正方形,调用会自动降至 2K,并按 2K 计费。图像编辑 / 图生图
端点:POST /v1/images/edits。单图编辑时,通过 image 传入 HTTPS URL 或 data: base64 格式的源图像;多图参考时使用 image_urls。
# Image edit / image-to-image: pass the source image URL
import requests
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue, keep composition",
"image": "https://your-cdn.com/source.png",
},
)
print(resp.json()["data"][0]["url"])多图参考
部分模型(Nano Banana Edit、GPT-Image-2 Edit)支持多张参考图像。
# nano-banana-edit accepts multiple reference images
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "nano-banana-edit",
"prompt": "merge subject from img1 with background from img2",
"image_urls": [
"https://your-cdn.com/subject.png",
"https://your-cdn.com/background.png",
],
},
)支持编辑的模型
nano-banana-edit——Google Nano Banana 编辑gpt-image-2-edit——OpenAI 图生图
提供源图像
图像编辑和图生视频都需要模型能够获取源图像。你有三种方式可选,请根据应用场景选择:
- 你已有公开 URL——直接将其作为
image(视频则使用image_url)传入即可。 - 你有本地文件——通过
POST /v1/files上传一次,然后重复使用返回的永久 URL。 - 你的代码中有原始字节——将其作为
data:base64 URI 内联;Kunavo 会为其提供托管服务。
方案 A——通过 POST /v1/files 上传
发送 multipart/form-data,并附带 file 字段(或 JSON { "file": "data:..." })。你会收到一个永久的 files.kunavo.com URL——文件大小上限为 25 MB。
# Upload a local file → get a permanent Kunavo URL
import requests
with open("source.png", "rb") as f:
up = requests.post(
"https://api.kunavo.com/v1/files",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
).json()
# up["url"] is now a permanent https://files.kunavo.com/... URL
edit = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": up["url"],
},
).json()
print(edit["data"][0]["url"])方案 B——内联 base64
无需单独上传:将 data: URI 放入 image / image_url 字段即可。Kunavo 会解码该 URI,将其托管在 CDN 上,并将托管 URL 提供给模型。
# Or skip the upload step — pass base64 inline, we host it for you.
import base64, requests
with open("source.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": f"data:image/png;base64,{b64}",
},
)POST /v1/video/generations 也适用相同方式——对于 Veo 等图生视频模型,image_url 可接受 https URL 或 data: base64 URI。响应格式
两个端点都会返回 OpenAI 标准的图像响应:
{
"created": 1779360636,
"data": [
{ "url": "https://files.kunavo.com/image/.../result.png" }
]
}延迟和超时
图像生成通常需要 5–60 秒,具体取决于模型。在默认同步模式下,Kunavo 会保持连接,并轮询上游最多 540 秒,之后返回 504。请相应设置客户端超时;也可以使用 异步 API,在数秒内提交任务,并按自己的时间安排轮询:
- Nano Banana / Nano Banana 2:通常少于 10 秒。
- Nano Banana Pro / GPT-Image-2:15–60 秒。
- 多参考图 + 高级档位:最长约 2 分钟。
异步 API(提交 + 轮询 / webhook)
默认情况下,两个图像端点都是同步的——调用会保持连接,直到上游完成渲染,然后返回标准 OpenAI 图像响应。对于批量任务、速度较慢的高级档位,或无法保持长请求的无服务器调用方,请在 /v1/images/generations 或 /v1/images/edits 中添加 "async": true(或 webhook_url)。
提交后会立即返回一个 img_* ID;轮询 GET /v1/images/{id},直到 status 为 completed 或 failed;也可以注册 webhook,完全跳过轮询。
# Async: add "async": true (or a webhook_url) to either image endpoint.
# The call returns instantly with an img_ id instead of holding the connection.
import requests, time
API = "https://api.kunavo.com/v1"
H = {"Authorization": f"Bearer {API_KEY}"}
submit = requests.post(
f"{API}/images/generations",
headers=H,
json={"model": "gpt-image-2", "prompt": "a red panda", "async": True},
).json()
task_id = submit["id"] # "img_abc..."
status = submit["status"] # "queued"
# Poll GET /v1/images/{id} until terminal — or skip polling and use a webhook.
while status not in ("completed", "failed"):
time.sleep(3)
r = requests.get(f"{API}/images/{task_id}", headers=H).json()
status = r["status"]
if status == "completed":
print(r["output"]["url"])
else:
print("failed:", r["error"])任务对象
| 字段 | 类型 | 备注 |
|---|---|---|
id | string | img_* 任务 ID——传递给 GET /v1/ |
status | string | queued | in_progress | completed | failed。 |
output | object|null | 完成时返回:{ url, urls, archived }。如果某张图像未能归档,其 URL 就是上游的临时 URL,此时 archived 为 false。 |
error | object|null | 失败时返回:{ code, message }。 |
expires_at | int|null | 提交后满 30 天时的 Unix 秒数:至少在此之前都可以轮询该任务。其结果 URL 不会过期。 |
GET /v1/images/{id} 按所有者隔离:查询不属于你的 ID 时会返回 404,与从未签发过的 ID 无法区分。建议的轮询间隔为 3 秒,并使用指数退避,最长约 30 秒。Webhook 回调
提交时传入 webhook_url(https),任务终止时 Kunavo 会 POST 一个经过签名的 image.completed / image.failed 事件——其封装和签名方式与视频和音乐 webhook 相同:
X-Kunavo-Webhook-Id——稳定的事件 ID,重试期间保持不变(可用其去重)。X-Kunavo-Webhook-Timestamp——计算签名时的 Unix 秒数。X-Kunavo-Webhook-Signature——针对{timestamp}.{rawBody}计算的sha256=HMAC-SHA256,密钥为你的 webhook 密钥。
原始输入直通选项
对于 Kunavo 未映射的模型专属参数(seed、负面提示词、输出格式),请传入 input。它会按原样发送至上游,替代我们的适配器原本会构建的输入。
用于选择模型价格档位的字段是例外:resolution,在 Ideogram 上则是 rendering_speed。对于设有档位的模型,该字段始终会以该模型的某个档位发送,并按该档位计费。如果 input 未提供该字段,或提供的值不是该模型的任何档位,则会发送默认档位并按默认档位计费。设置了 input 时,不会读取请求顶层的同名字段。
# Raw upstream 'input': sent as written, in place of what our adapter builds.
# "resolution" sets the billed tier: 2K here, the default tier when left out.
resp = client.images.generate(
model="nano-banana-2",
prompt="", # ignored when input is set
extra_body={"input": {
"prompt": "a futuristic cyberpunk skyline at dusk",
"aspect_ratio": "16:9",
"resolution": "2K",
"output_format": "png",
}},
)input 时,你会绕过 Kunavo 的验证。如果上游拒绝你的字段,我们会返回 422——请查看 错误文档 和模型上游文档。