媒体 API
POST/omni/media/v1/images/generations/tasks

图像生成

图像生成分两个步骤:先创建任务(回 202 + task id),再轮询到终态、下载签名 URL。把 client 指向媒体 base URL https://api.atptoken.ai/omni/media/v1,用项目 atp- key 验证。gateway 会把你的 unified model 路由到图像 provider(例如 gpt-image-2);名称用 GET /v1/models 确认。流程与视频生成一致。

  • 输出写入对象存储、以带签名的边缘 URL(https://media-<env>.atptoken.ai/v/...)返回,TTL 30 分钟——不会内嵌 base64。请尽快取用。
  • 当 project 余额 ≤ 0,请求会以 402 insufficient_quota 拒绝。
先用同一把 key 确认模型

媒体模型依环境与 project 开放。请先调用 GET https://api.atptoken.ai/v1/models;未出现在响应中的模型,代表这把 key 目前不能使用。

创建任务

curl https://api.atptoken.ai/omni/media/v1/images/generations/tasks \
  -H "Authorization: Bearer atp-..." -H "Content-Type: application/json" \
  -H "Idempotency-Key: img-job-001" \
  -d '{ "model": "gpt-image-2", "prompt": "a watercolor cat", "size": "1024x1024", "quality": "high", "n": 1 }'
# → 202 { "id": "img_..." }
FieldTypeDescription
modelstring · 必填unified 图像模型(`image` 池)
promptstring · 必填文本提示
sizestring依模型而异;OpenAI 图像常用 `1024x1024`
qualitystring转发给 OpenAI 方言上游(如 `high`/`medium`)
ninteger张数 1–4(默认 `1`)

网络失败重试创建时沿用同一个 Idempotency-Key;真正的新任务用新 key。

轮询至终态

每 3–8 秒轮询一次:

curl https://api.atptoken.ai/omni/media/v1/images/generations/tasks/img_... \
  -H "Authorization: Bearer atp-..."
# → { "status": "succeeded", "data": [ { "url": "https://media-prod.atptoken.ai/v/image/...png?exp=...&sig=..." } ], "usage": { "prompt_tokens": 37, "completion_tokens": 7024, "total_tokens": 7061 } }
  • status 流转:queuedrunningsucceededfailedcancelledexpired
  • 成功任务的 data[].url30 分钟时效的签名 URL;过期后任务仍显示 succeededexpired: trueurl 为 null——请立即下载(要重拿只能重新生成)。
  • usage 上报 token 用量供账务核对;failed 任务带结构化 error 对象。
MethodPath动作
POST/omni/media/v1/images/generations/tasks创建
GET/omni/media/v1/images/generations/tasks/{id}轮询
GET/omni/media/v1/images/generations/tasks列表
DELETE/omni/media/v1/images/generations/tasks/{id}取消

Python 示例

最小的创建+轮询流程:

import os, time, requests

BASE = "https://api.atptoken.ai/omni/media/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['ATP_API_KEY']}",
    "Content-Type": "application/json",
}

resp = requests.post(
    f"{BASE}/images/generations/tasks",
    headers={**HEADERS, "Idempotency-Key": "img-job-001"},
    json={
        "model": "gpt-image-2",
        "prompt": "a watercolor cat",
        "size": "1024x1024",
        "quality": "high",
        "n": 1,
    },
    timeout=60,
)
resp.raise_for_status()
task_id = resp.json()["id"]

while True:
    task = requests.get(
        f"{BASE}/images/generations/tasks/{task_id}", headers=HEADERS, timeout=60
    ).json()
    if task["status"] in ("succeeded", "failed", "cancelled", "expired"):
        break
    time.sleep(5)

if task["status"] == "succeeded":
    for i, item in enumerate(task["data"]):
        image = requests.get(item["url"], timeout=120).content  # signed URL, 30-min TTL
        with open(f"result_{i}.png", "wb") as f:
            f.write(image)
else:
    raise RuntimeError(task.get("error"))

错误

400
缺 `model` 或 `prompt`。
402
`insufficient_quota`:project 余额 ≤ 0;充值后再发(不要重试轰炸)。
404
任务不存在或不属于此 project(轮询时)。
422
该模型没有图像 provider。
502
上游生成失败。