# GPT Image 2 示例文档 本文档基于用户站 `https://apicodex.xyz` 的接入方式整理,包含: - 文生图示例 - 带参考图示例 - 支持的比例列表 - 实测返回结构 - 同步返回与异步轮询的兼容写法 ## 接口地址 ```text POST https://apicodex.xyz/v1/images/generations ``` ## 鉴权 请求头使用 Bearer Token: ```python headers = { "Authorization": "Bearer ", "Content-Type": "application/json", } ``` ## 支持的比例 当前整理到的 `size` 比例共有 13 种: - `1:1` - `16:9` - `9:16` - `4:3` - `3:4` - `3:2` - `2:3` - `5:4` - `4:5` - `2:1` - `1:2` - `21:9` - `9:21` 说明: - 上述 13 种比例按你提供的接口说明整理 - 本文档里实际请求验证过的是 `16:9` 建议只通过 `size` 传比例,不要在 `prompt` 里重复写比例。 ## 文生图示例 ```python import requests url = "https://apicodex.xyz/v1/images/generations" payload = { "model": "gpt-image-2", "prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格", "n": 1, "size": "16:9", } headers = { "Authorization": "Bearer ", "Content-Type": "application/json", } response = requests.post(url, json=payload, headers=headers, timeout=300) print(response.json()) ``` ## 带参考图示例 注意:不要把参考图放进 `/v1/images/generations` 的 `image_urls` 字段。当前实测该字段会被忽略,返回 usage 中 `input_tokens_details.image_tokens` 仍为 `0`。带图请求应走: ```text POST https://apicodex.xyz/v1/images/edits ``` ### 参考图为 URL ```python import requests image_url = "https://example.com/photo.jpg" image_resp = requests.get(image_url, timeout=60) image_resp.raise_for_status() url = "https://apicodex.xyz/v1/images/edits" data = { "model": "gpt-image-2", "prompt": "把这张照片变成水彩画风格", "size": "1:1", } files = [ ("image[]", ("photo.jpg", image_resp.content, image_resp.headers.get("Content-Type") or "image/jpeg")), ] headers = { "Authorization": "Bearer ", } response = requests.post(url, data=data, files=files, headers=headers, timeout=300) print(response.json()) ``` ### 参考图为 base64 ```python import requests import base64 url = "https://apicodex.xyz/v1/images/edits" data = { "model": "gpt-image-2", "prompt": "把这张照片变成水彩画风格", "size": "1:1", } image_bytes = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAA...") files = [ ("image[]", ("reference.png", image_bytes, "image/png")), ] headers = { "Authorization": "Bearer ", } response = requests.post(url, data=data, files=files, headers=headers, timeout=300) print(response.json()) ``` ### 多张参考图 ```python import requests url = "https://apicodex.xyz/v1/images/edits" data = { "model": "gpt-image-2", "prompt": "把这两张照片融合成一张海报", "size": "4:3", } files = [ ("image[]", ("photo-a.jpg", open("photo-a.jpg", "rb"), "image/jpeg")), ("image[]", ("photo-b.png", open("photo-b.png", "rb"), "image/png")), ] headers = { "Authorization": "Bearer ", } try: response = requests.post(url, data=data, files=files, headers=headers, timeout=300) print(response.json()) finally: for _, file_tuple in files: file_tuple[1].close() ``` ## 实测结果 本仓库在 `2026-04-22`(America/Los_Angeles)对以下请求做了真实测试: ```json { "model": "gpt-image-2", "prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格", "n": 1, "size": "16:9" } ``` 实测结论: - 请求返回 `HTTP 200` - `size: "16:9"` 被接口接受 - 当前实测返回是“同步结果”,不是 `task_id` - 顶层字段为 `created` 和 `data` - `data[0]` 中包含 `b64_json` 和 `revised_prompt` - 本次实测的 `revised_prompt` 为 `黄昏里的橘猫窗台景` - 本次解码后的样例图尺寸为 `1196x1315`,没有严格匹配 `16:9` 实测返回结构可概括为: ```json { "created": 1776919131, "data": [ { "b64_json": "", "revised_prompt": "黄昏里的橘猫窗台景" } ] } ``` 本次测试产物已保存到仓库临时目录: - `tmp/imagegen/gpt-image-2-16-9-response.json` - `tmp/imagegen/gpt-image-2-16-9-sample.png` ## 同步返回时的取图方式 如果接口直接返回 `b64_json`,可以这样保存图片: ```python import base64 import requests url = "https://apicodex.xyz/v1/images/generations" payload = { "model": "gpt-image-2", "prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格", "n": 1, "size": "16:9", } headers = { "Authorization": "Bearer ", "Content-Type": "application/json", } response = requests.post(url, json=payload, headers=headers, timeout=300) data = response.json() img_b64 = data["data"][0]["b64_json"] with open("output.png", "wb") as f: f.write(base64.b64decode(img_b64)) ``` ## 异步轮询写法 你提供的说明里写的是“提交后返回 `task_id`,再轮询 `/v1/tasks/{task_id}`”。如果后续该上游切回异步模式,可以用下面这种兼容写法: ```python import base64 import time import requests url = "https://apicodex.xyz/v1/images/generations" headers = { "Authorization": "Bearer ", "Content-Type": "application/json", } payload = { "model": "gpt-image-2", "prompt": "a corgi astronaut on the moon, cinematic, 8k", "size": "16:9", "n": 1, } resp = requests.post(url, json=payload, headers=headers, timeout=300) resp.raise_for_status() data = resp.json() # 情况 1:直接同步返回 base64 if isinstance(data, dict) and data.get("data") and data["data"][0].get("b64_json"): with open("output.png", "wb") as f: f.write(base64.b64decode(data["data"][0]["b64_json"])) print("saved output.png") # 情况 2:返回 task_id,需要轮询 elif isinstance(data, dict) and data.get("data", {}).get("id"): task_id = data["data"]["id"] task_url = f"https://apicodex.xyz/v1/tasks/{task_id}" time.sleep(10) while True: task_resp = requests.get(task_url, headers=headers, timeout=60) task_resp.raise_for_status() task = task_resp.json() status = task["data"]["status"] if status == "completed": print(task["data"]["result"]["images"][0]["url"][0]) break if status == "failed": raise RuntimeError(task["data"]["error"]["message"]) time.sleep(5) else: raise RuntimeError(f"unexpected response: {data}") ``` ## 如果是异步结果,取图字段 如果接口返回的是任务模式,则最终图片 URL 取值为: ```text data.result.images[0].url[0] ``` 任务状态说明: - `pending`: 已提交或排队中 - `processing`: 上游处理中 - `completed`: 成功 - `failed`: 失败 ## 注意事项 - 单张图接口耗时可能较长,建议客户端超时至少设到 `300s` - 本次实测中,`size: "16:9"` 虽然被接口接受,但返回图片尺寸并未严格命中 `16:9`;如果你的业务依赖固定画幅,建议在下载后自行校验并按需裁切 - 如果使用异步模式,首次轮询建议在提交后等待 `10~20` 秒 - 轮询间隔建议 `3~5` 秒,不要毫秒级高频轮询 - 建议失败时做有限次重试,尤其是 TLS 或上游网络抖动场景 - 如果服务端返回的是 `b64_json`,说明当前是同步模式,不需要再调 `/v1/tasks/{task_id}`