# 图片生成 API

使用 POST /api/v1/images 创建图片生成任务，并了解响应、积分与错误处理。

## 创建图片任务

`POST /api/v1/images` 会先校验请求、扣除积分并提交任务，然后才返回响应。多数模型随后异步生成：每 5–10 秒轮询一次 [`GET /api/v1/tasks/{taskId}`](https://viewmax.studio/zh/docs/api/tasks)，直到状态变为 `success`、`failed` 或 `canceled`，再从 `data.taskUrls` 读取图片。

```http
POST https://viewmax.studio/api/v1/images
Authorization: Bearer sk-your-api-key
Content-Type: application/json
Idempotency-Key: kite-poster-001
```

## 请求体

| 字段         | 必填 | 类型     | 说明                                                                                                     |
| ------------ | ---- | -------- | -------------------------------------------------------------------------------------------------------- |
| `model`      | 是   | string   | `GET /api/v1/models?type=image` 返回的模型 `id`                                                          |
| `prompt`     | 是   | string   | 非空，首尾空白会被去掉                                                                                   |
| `scene`      | 否   | string   | `text-to-image` 或 `image-to-image`；必须是该模型 `modes` 中的键                                         |
| `image_urls` | 否   | string[] | 提供方无需鉴权即可下载的 `http://` 或 `https://` 图片 URL。`image-to-image` 至少一张；ViewMax 不限制数量 |
| `options`    | 否   | object   | 模型目录中列出的生成控制项                                                                               |

未传 `scene` 时：`image_urls` 非空则为 `image-to-image`，否则为 `text-to-image`。

### `options`

| 字段           | 类型   | 说明                                                                                                                                                                                                             |
| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `aspect_ratio` | string | `modes.<scene>.aspect_ratios` 中的值，如 `1:1`、`16:9` 或 `9:16`                                                                                                                                                 |
| `quality`      | string | `modes.<scene>.qualities` 中的值，不区分大小写：`1K`/`2K`/`4K`（Nano Banana 2、Wan 2.7）、`Basic`/`High`（Seedream 5.0）、`Medium`/`High`（GPT Image 1.5）、`Low`/`Medium`/`High`/`XHigh`/`Max`（GPT Image 2.5） |
| `resolution`   | string | GPT Image 2.5：`1K`（默认）、`2K` 或 `4K`。其他模型在未传 `quality` 时把它当作 `quality`                                                                                                                         |
| `size`         | string | 仅 GPT Image 2.5：精确像素，如 `1536x1024`（边长为 16 的倍数，最长边不超过 3840，宽高比不超过 3:1，总像素 655,360–8,294,400）。会覆盖 `aspect_ratio` 和 `resolution`                                             |

无法识别的值按模型分别处理：

- GPT Image 2.5（`gpt-image-2.5`、`gpt-image-2.5-sunburst`）返回 400：`Invalid GPT Image 2.5 quality`、`Invalid GPT Image 2.5 resolution`、`Invalid GPT Image 2.5 aspect ratio` 或 `Invalid GPT Image 2.5 pixel dimensions`。其默认值为 `Medium`、`1K` 和 `1:1`。
- 其他模型会把无法识别的 `quality` 替换为列表中的第一个值，把无法识别的 `aspect_ratio` 替换为默认值，并按替换后的值计费。`aspect_ratios` 列表为空的模型会原样透传该值，不做校验。请先对照目录再发送。

## 示例

```bash
curl -X POST https://viewmax.studio/api/v1/images \
  -H "Authorization: Bearer $VIEWMAX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: kite-poster-001" \
  -d '{
    "model": "nano-banana-2",
    "scene": "text-to-image",
    "prompt": "A paper kite crossing a bright summer sky",
    "options": { "aspect_ratio": "16:9", "quality": "2K" }
  }'
```

该请求消耗 8 积分；在下文所述的套餐额度内为 `0`。

## 成功响应

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "8b2d4f6a-1c3e-4a5b-9d7f-0e2c4a6b8d10",
    "userId": "usr_123",
    "mediaType": "image",
    "model": "nano-banana-2",
    "prompt": "A paper kite crossing a bright summer sky",
    "options": "{\"aspect_ratio\":\"16:9\",\"quality\":\"2K\"}",
    "status": "pending",
    "createdAt": "2026-09-29T08:00:00.000Z",
    "updatedAt": "2026-09-29T08:00:01.000Z",
    "deletedAt": null,
    "taskId": "job_def",
    "taskInfo": null,
    "taskResult": null,
    "taskUrls": [],
    "costCredits": 8,
    "scene": "text-to-image",
    "visibility": "user",
    "creditId": "cr_456",
    "waivedCredits": 0,
    "fairUseKey": null
  }
}
```

字段说明见[视频生成 API](https://viewmax.studio/zh/docs/api/video-generation)中的**任务字段**。`taskUrls` 始终是数组，`success` 之前为空。

## 幂等

每次创建请求都发送 `Idempotency-Key`（1–200 个可见 ASCII 字符，不含空格）。重复使用同一个键会返回原任务及其 `costCredits`，不会再次扣费；服务端不比较请求体，同一账号的所有创建端点共用这些键。超时后用同一个键重试；有意发起新尝试时换用新键。不带该请求头时，每次 POST 都会创建新任务并扣费。

## 积分与退款

- 任务创建时扣除积分。余额低于费用时返回 402，不创建任务。
- 以 `failed` 或 `canceled` 结束的任务会自动退还积分，占用的套餐额度也会归还。
- Pro 和 Ultra 用户使用 `gpt-image-2`、`gpt-image-2.5`、`gpt-image-2.5-sunburst`、`nano-banana-2` 和 `grok-imagine` 时，在与 ViewMax 网页共用的每日额度内消耗 `0` 积分（目前 Pro 每个 UTC 日 25 张，Ultra 100 张）。额度内 `costCredits` 为 `0`，`waivedCredits` 为原价，并写入 `fairUseKey`。其他模型，以及这些模型超出额度后，都会正常扣费。

## 估算费用

没有费用预览端点。请根据 `GET /api/v1/models?type=image` 中的 `modes.<scene>` 计算：

| 目录字段                                                                    | 费用                           |
| --------------------------------------------------------------------------- | ------------------------------ |
| `credits[quality]`                                                          | 所发送（或默认）质量对应的价格 |
| `credits_per_generation`                                                    | 没有 `credits` 时的每张价格    |
| `credits_by_resolution_and_aspect_ratio[resolution][aspect_ratio][quality]` | GPT Image 2.5                  |

## 错误

所有错误都使用[错误信封](https://viewmax.studio/zh/docs/api/errors)。

| HTTP | `error.type`           | `message` 示例                                                           | 处理方式                                                                                                              |
| ---- | ---------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| 400  | `invalid_request`      | `unsupported image model: <id>. Supported models: ...`                   | 使用 `GET /api/v1/models?type=image` 中的 `id`                                                                        |
| 400  | `invalid_request`      | `scene must be one of text-to-image\|image-to-image, got <value>`        | 发送有效的 `scene`                                                                                                    |
| 400  | `invalid_request`      | `image-to-image requires image_urls`                                     | 至少补充一个图片 URL                                                                                                  |
| 400  | `invalid_request`      | `image_urls must contain valid http(s) URLs`                             | 发送 `http://` 或 `https://` URL                                                                                      |
| 400  | `invalid_request`      | `Invalid GPT Image 2.5 quality`                                          | 发送目录中列出的值                                                                                                    |
| 400  | `invalid_request`      | `the generation request uses unsupported settings`，并带 `error.task_id` | 提供方拒绝了这些设置，任务已失败并退还积分。读取该任务的 `taskInfo.errorMessage`，调整后用新的 `Idempotency-Key` 重试 |
| 400  | `content_rejected`     | `input content was rejected by safety filters`                           | 含禁止用途措辞（深度伪造、换脸、冒充他人）或被提供方审核拒绝。修改内容，不要原样重试                                  |
| 402  | `insufficient_credits` | `insufficient credits`                                                   | 未创建任务。补充积分前不要重试                                                                                        |
| 500  | `internal_error`       | `the generation service is temporarily unavailable`                      | 带 `error.task_id` 时任务已失败并退还积分，可重试一次。若 hint 说明结果未知，请轮询该任务，不要重试                   |
| 503  | `internal_error`       | —                                                                        | 内容安全检查暂不可用，稍后重试                                                                                        |
