# API 错误

ViewMax v1 错误信封、HTTP 状态码、全部错误消息，以及何时重试。

## 错误响应

每个 v1 错误都是包含 `code`、`message` 和 `error` 对象的 JSON，没有 `data`。

```json
{
  "code": -1,
  "message": "viewmax-c1 text-to-video supports duration 1s|2s|3s|4s|5s|6s|7s|8s|9s|10s|11s|12s|13s|14s|15s, got 30s",
  "error": {
    "type": "invalid_request",
    "hint": "Fix the request using this message, then retry. Refresh GET /api/v1/models before repeating an unsupported model or option.",
    "docs": "https://viewmax.studio/docs/api/errors"
  }
}
```

| 字段            | 说明                                                                                                           |
| --------------- | -------------------------------------------------------------------------------------------------------------- |
| `code`          | `-1`、`-1001`（未认证）或 `-1002`（积分不足）                                                                  |
| `message`       | 出错原因，消息列表见下文                                                                                       |
| `error.type`    | `invalid_request`、`content_rejected`、`unauthorized`、`insufficient_credits`、`not_found` 或 `internal_error` |
| `error.hint`    | 下一步操作，包括重试是否有用                                                                                   |
| `error.docs`    | 文档链接                                                                                                       |
| `error.task_id` | 请求在失败前已创建任务时出现                                                                                   |

## 状态码

| HTTP  | `code`  | `error.type`           | 何时出现                                         | 是否重试？                      |
| ----- | ------- | ---------------------- | ------------------------------------------------ | ------------------------------- |
| `400` | `-1`    | `invalid_request`      | 请求、模型、模式或选项无效，或模型拒绝了这些设置 | 否，先修正请求                  |
| `400` | `-1`    | `content_rejected`     | 提示词或源素材被安全检查拒绝                     | 否，更换内容                    |
| `401` | `-1001` | `unauthorized`         | 缺少或无效的 API key                             | 否，发送有效 key                |
| `402` | `-1002` | `insufficient_credits` | 余额低于费用，未创建任务                         | 否，先充值                      |
| `404` | `-1`    | `not_found`            | 任务不存在、属于其他账户，或端点不存在           | 否                              |
| `405` | —       | —                      | 路径存在但不支持此方法，响应体为空               | 否，使用文档中的方法            |
| `500` | `-1`    | `internal_error`       | 服务商或服务器故障                               | 检查 `error.task_id` 后重试一次 |
| `503` | `-1`    | `internal_error`       | 内容安全检查暂时不可用                           | 是，稍后重试                    |

## 是否应该重试？

1. `400`、`401`、`402`、`404`：不要重复同一请求，按消息修正。
2. `503`：稍后重试同一请求。
3. 没有 `error.task_id` 的 `500`：稍等片刻后重试一次。
4. 任何带 `error.task_id` 的错误：先查询 `GET /api/v1/tasks/{task_id}`。
   - `failed`：积分已退回。阅读[失败载荷](https://viewmax.studio/zh/docs/api/tasks)，必要时再创建新任务。
   - `pending` 或 `processing`：模型仍可能交付该任务。请继续轮询而不是重试；新请求会再次扣费。
5. 重试创建请求时，如果不确定第一次请求是否到达 ViewMax，请复用同一个 `Idempotency-Key`。已存在的任务会直接返回，不会重复扣费。

## Idempotency-Key

在每个创建请求上发送 `Idempotency-Key`：`POST /api/v1/videos`、`images`、`music`、`speech` 和 `sound-effects`。

- key 为 1–200 个可见 ASCII 字符、不含空格，例如 UUID。其他格式返回 `400`，消息为 `Idempotency-Key must be 1-200 visible ASCII characters without spaces`。
- 重复的 key 返回首次请求创建的任务及其原始 `costCredits`，不会扣费。不会比较请求体。
- key 的作用域是你的账户，在所有创建端点间共享。
- 即使原任务已失败，重放也会返回它。新的尝试请使用新 key。
- 不带该请求头时，每个 `POST` 都会创建并扣费一个新任务。

## 400 `invalid_request` 消息

尖括号表示随请求变化的值。

### 所有创建端点

| 消息                                                                    | 原因                                                                 | 处理                                                   |
| ----------------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------ |
| JSON 解析器消息，例如 `Unexpected end of JSON input`                    | 请求体不是合法 JSON                                                  | 使用 `Content-Type: application/json` 发送 JSON 对象   |
| `request body must be an object`                                        | 请求体是 JSON 但不是对象                                             | 发送 JSON 对象                                         |
| `Idempotency-Key must be 1-200 visible ASCII characters without spaces` | `Idempotency-Key` 请求头格式错误                                     | 使用 UUID 或其他短令牌                                 |
| `model is required`                                                     | 缺少 `model`（videos、images）                                       | 发送 `GET /api/v1/models` 中的 ID                      |
| `prompt is required`                                                    | 缺少 `prompt` 或为空                                                 | 发送非空提示词                                         |
| `options must be an object`                                             | `options` 不是对象                                                   | 以 JSON 对象发送 options                               |
| `image_urls must be an array of URLs`                                   | `image_urls` 不是字符串数组                                          | 发送公开 HTTP(S) URL 数组                              |
| `This capability is unavailable.`                                       | 模型或模式已停用，例如 Motion Control                                | 换用其他模型；重试仍会失败                             |
| `the generation request uses unsupported settings`                      | 任务创建后模型拒绝了这些设置。任务已失败并退款，`error.task_id` 有值 | 读取该任务的 `taskInfo.errorMessage`，调整后创建新任务 |
| `invalid params or unsupported model for scene`                         | 该模型不支持此模式                                                   | 从目录中选择模型和模式                                 |

### 视频（`POST /api/v1/videos`）

| 消息                                                                                                                       | 原因                                           | 处理                                      |
| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------- |
| `video_urls must be an array of URLs`                                                                                      | `video_urls` 不是字符串数组                    | 发送公开 HTTP(S) URL 数组                 |
| `mode must be one of text-to-video\|image-to-video\|video-to-video\|frames-to-video\|reference-to-video, got <mode>`       | 未知模式                                       | 使用五种模式 ID 之一                      |
| `unsupported video model: <model>`                                                                                         | 未知模型 ID                                    | 使用 `GET /api/v1/models` 中的 `id`       |
| `video model temporarily unavailable: <model>. The provider is not serving this model right now — pick a different model.` | 模型已下线，例如 `sora-2`                      | 换用其他模型                              |
| `<model> does not support mode <mode>`                                                                                     | 模式不在该模型的 `modes` 中                    | 选择列出的模式                            |
| `<model> prompt must be <max> characters or fewer, got <length>`                                                           | 去除首尾空白后的提示词超过 `max_prompt_length` | 缩短提示词                                |
| `image_urls must contain valid http(s) URLs`                                                                               | URL 不是以 `http://` 或 `https://` 开头        | 发送公开 HTTP(S) URL（`video_urls` 同理） |
| `<model> <mode> requires image_urls`                                                                                       | 该模式需要图片                                 | 添加图片 URL                              |
| `<model> <mode> requires image_urls (at least 2)`                                                                          | `frames-to-video` 需要首帧和尾帧               | 发送两个图片 URL                          |
| `<model> <mode> requires video_urls`                                                                                       | `video-to-video` 需要源视频                    | 添加一个视频 URL                          |
| `<model> <mode> does not accept image_urls; supported inputs: <inputs>`                                                    | 该模式不接受图片（或视频）                     | 移除该输入或换用其他模式                  |
| `<model> <mode> supports at most <n> image_urls, got <count>`                                                              | 输入过多（`video_urls` 同理）                  | 减少 URL 数量                             |
| `<model> <mode> requires options.source_video_duration_seconds when video_urls is provided`                                | 按秒计费的模型收到了视频                       | 发送源视频时长（秒）                      |
| `<model> <mode> supports duration <values>, got <value>`                                                                   | 不支持的 `duration`                            | 使用该模式 `durations` 中的值             |
| `<model> <mode> supports duration <values> at <resolution>, got <value>`                                                   | 该分辨率下不提供此时长                         | 调整时长或分辨率                          |
| `<model> <mode> supports resolution <values>, got <value>`                                                                 | 不支持的 `resolution`（列表为空表示不要发送）  | 使用 `resolutions` 中的值，或省略         |
| `<model> <mode> supports aspect_ratio <values>, got <value>`                                                               | 不支持的 `aspect_ratio`                        | 使用 `aspect_ratios` 中的值，或省略       |
| `<model> <mode> supports audio false, got true`                                                                            | 该模式没有音频开关                             | 移除 `audio` 或发送 `false`               |

示例：`kling-2-6 text-to-video supports duration 5s|10s, got 30s`；`runway text-to-video supports duration 5s at 1080p, got 10s`。

### 图片、音乐、语音和音效

| 消息                                                                                       | 端点            | 处理                                              |
| ------------------------------------------------------------------------------------------ | --------------- | ------------------------------------------------- |
| `scene must be one of text-to-image\|image-to-image, got <scene>`                          | `images`        | 使用列出的 scene                                  |
| `unsupported image model: <model>. Supported models: <ids>`                                | `images`        | 使用 `GET /api/v1/models?type=image` 中的 ID      |
| `<model> supports scene <scenes>, got <scene>`                                             | `images`        | 选择该模型支持的 scene                            |
| `image-to-image requires image_urls`                                                       | `images`        | 添加图片 URL                                      |
| `Invalid GPT Image 2.5 quality`、`resolution`、`aspect ratio` 或 `pixel dimensions`        | `images`        | 使用 GPT Image 2.5 模型列出的值                   |
| `options.duration_seconds must be a number from 3 to 300`                                  | `music`         | 发送 3 到 300 之间的数字                          |
| `options.duration is not supported; use options.duration_seconds`                          | `music`         | 改用 `duration_seconds`（`music_length_ms` 同理） |
| `text is required`、`voice_id is required`                                                 | `speech`        | 两个字段都要发送                                  |
| `unknown voice_id: <id>. Call GET /api/v1/voices (MCP: list_voices) for available voices.` | `speech`        | 使用 `GET /api/v1/voices` 中的 ID                 |
| `options.duration_seconds must be a number from 0.5 to 22`                                 | `sound-effects` | 发送范围内的数字                                  |
| `options.prompt_influence must be a number from 0 to 1`                                    | `sound-effects` | 发送范围内的数字                                  |

## 400 `content_rejected` 消息

| 消息                                           | 原因                                                                                                                 | 处理                           |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| `input content was rejected by safety filters` | 提示词提及禁止用途（deepfake、换脸或冒充他人）。在创建任务和扣费前检查，即使出现在否定指令中（如“不要换脸”）也会命中 | 删除相关措辞；原样重试仍会失败 |
| `input content was rejected by safety filters` | 任务创建后模型审核拒绝了提示词或素材。任务已失败并退款，`error.task_id` 有值                                         | 更换内容后创建新任务           |
| `Prompt was blocked by content safety review.` | 内容安全审核拦截了提示词                                                                                             | 修改提示词                     |

## 其他状态

| HTTP  | 消息                                                                             | 说明                                                                      |
| ----- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `401` | `unauthorized`                                                                   | 参见[认证](https://viewmax.studio/zh/docs/api/authentication)                                   |
| `402` | `insufficient credits`                                                           | 在创建任务前检查，包括两个请求争用同一余额的情况。`error.docs` 指向价格页 |
| `404` | `task not found`                                                                 | 任务 ID 不存在或属于其他账户                                              |
| `404` | `endpoint not found`                                                             | 未知的 `/api/...` 路径。参见 [OpenAPI](https://viewmax.studio/openapi.json)                     |
| `500` | `the generation service is temporarily unavailable`                              | 模型服务故障或无响应。重试前检查 `error.task_id`                          |
| `500` | `media generation failed`                                                        | 其他失败。重试前检查 `error.task_id`                                      |
| `500` | `the generation service is busy; try again later`                                | 模型服务限流，稍后重试                                                    |
| `500` | `the generation request was cancelled`                                           | 请求在上游被取消，重试一次                                                |
| `503` | `Content safety check is temporarily unavailable. Please try again in a moment.` | 稍后重试                                                                  |

轮询 `GET /api/v1/tasks/{taskId}` 时出现的 `500` 是暂时性的：继续轮询同一任务即可。
