# Vimox Router API 文档

- Base URL：`https://router.vimox.cn`
- API Key：`<your-api-key>`
- 鉴权说明：所有端点需携带 API Key 或 Vimox OAuth token（Authorization: Bearer、x-api-key；Gemini 也支持 x-goog-api-key）。响应含 X-Trace-Id 头，可用于排障对账。

## Key 权限、模型可见性与图片空请求

使用同一 Key 调用 `GET /v1/models` 检查实时可用模型。Python `client.models()`、Node `client.models()`、Go `client.Models(ctx, &result)` 均读取此接口；随包静态模型目录仅供参考，不是当前 Key 的授权凭证。白名单为空表示不额外限制，目录仍受分组、模型启用、有效价格与套餐限制。`maxPlanVisible=true` 明确表示“仅 MAX 会员可见”，与 `maxPlanFree`（MAX 免费）独立；非 MAX 用户可能看不到已配置价格的模型。管理员要向普通付费调用开放，应同时关闭模型组和来源的仅 MAX 可见限制，保留价格，不应给单个 Key 伪造套餐。

`vimox-image`、`vimox-image-2k`、`vimox-image-4k` 是独立公开别名，可使用同一个上游模型；各自的价格和可见性独立，以当前 Key 的 `/v1/models` 为准。复制别名不应移走或隐藏原模型。

外部 Vimox Key 的本地镜像不替代远端有效性校验；撤销或身份不匹配不能退化成本地身份放行。401 表示无效凭证，403 表示模型白名单或路由范围拒绝，认证依赖异常应单独排查，不能据此给用户扩大权限。

不要用仅含 `model` 的 `POST /v1/images/generations` 或 `/v1/images/edits` 检查可见性。非空 `prompt` 与参考图均缺失时 Router 返回 HTTP 400、`error.code=bad_request`，不调用上游、不扣生图费用，诊断台账仍保留；参考图独立生成是否受支持由模型决定。上游 422 需要结合 `X-Trace-Id` 和错误详情判断，不等同于权限不足。现有三语言客户端方法、请求字段、类型和错误透传结构无需变化；本说明对应服务端源码，实际行为以部署版本为准。

## 门户模型状态（公开、只读）

`GET /users/model-status` 是门户辅助接口，不属于 `/v1` 模型调用接口，无需 API Key。返回 `windowStart`、`windowEnd`、`admin` 和 `models`。每个模型包含 `model`、`successRate`、`avgDurationMs`、`avgFirstTokenMs`、`avgOutputTokensPerSecond`、`avgGenerationMs` 与 24 个 `hours` 区间；每个区间为 `startAt`、`endAt`、`successRate`。时间戳和耗时单位为毫秒，输出速度为 tokens/s；没有样本的指标为 `null`。仅有效管理会话会额外获得模型级及每小时 `requestCount`，普通用户响应不包含调用次数。已有模型 API、SDK 客户端方法、鉴权及计费协议保持不变。

同步调用示例：`curl https://router.vimox.cn/users/model-status`。该 GET 无请求体、无需轮询；门户关闭返回 404，统计暂不可用返回 503。

## 决策分类与 Jev 兼容：System One

`vimox-decision`、`jev-latest`、`jev-preview` 与 Jev 版本模型统一属于“决策”（`catalogType=decision`），用户门户及 `/admin/settings/` 均提供对应筛选；`mediaType=request` 和 `openai-compat` 协议保留。Jev 继续使用现有计费方式与价格，目录分类不等同于输入 token 计费。

管理端“Vimox Qwen”（`vimoxqwen`）的模型目录已登记 `vimox-decision`，可通过“同步上游模型”补齐 ID，无需手动添加。账号 Base URL 仍须实际支持 `/v1/systemone` 和该模型；同步目录不会自动更换上游地址。

`POST /v1/systemone` 一次同步评估 `state` 和 typed `questions`，返回 `answers` 与 token `usage`，不需要轮询。`vimox-decision` 是决策分类模型；`jev-latest`、`jev-preview` 和 `jev-1.13.0` 是原有 TypeSafe Jev 别名，保持原调用方式与价格设置。

### POST /v1/systemone

请求体：`{"state":"Help!","model":"vimox-decision","questions":{"urgent":{"type":"noul","instructions":"Is this urgent?"}}}`。`state` 可为字符串、对象或数组；`questions` 的题型为 `noul`、`choice` 或 `score`；`images` 可选传公网 HTTP(S) URL、Base64 或 Data URI 字符串数组（可混用）。调用 `vimox-decision` 时，Router 按模型配置费率只对 `usage.input_tokens` 收费；缓存拆分与输出 token 不计费，Jev 仍使用其原计费配置。

成功响应保留 System One 结构：`model`、`answers` 与 `usage`（含可用的 `input_tokens`、`output_tokens`）。`choice` / `score` answer 还会包含 `probabilities` 与 `confidence`。

Python 使用 `client.decision(state=..., questions=..., images=[...])`，Node 使用 `client.decision({ state, questions, images })`，Go 使用 `client.Decision(ctx, input, &output)` 调用决策模型。原有 Python `system_one`、Node `systemOne` 和 Go `SystemOne` 仍默认使用 `jev-latest`。

TypeSafe 上游在 `429` 或 `529` 时会返回限流/过载错误；Router 会按统一失败转移语义处理，并保留上游错误状态与响应体。


### vimox-decision URL 图片读取

`images` 最多 16 项，支持公网 HTTP(S) URL、Data URI 和裸 base64，允许按顺序混用。URL 原样转交服务读取；SDK 和 Router 不预先下载，也不自动上传 URL 指向的图片。Jev 的图片能力由其上游决定，本节不改变 Jev 协议。

URL 使用默认端口（HTTP 80 / HTTPS 443），不接受内网地址、URL 用户名/密码或片段，不跟随重定向。单个远程图片最大 10 MiB、每请求下载合计最大 32 MiB；最多并行下载 4 张，单张超时 10 秒、整组超时 20 秒。COS 私有图需提供在排队和下载期间有效的签名 URL；路径和签名查询参数保持原样，日志中不得保存签名。

```json
{"model":"vimox-decision","state":"判断包裹是否损坏","images":["https://example.com/package.jpg"],"questions":{"damaged":{"type":"noul","instructions":"是否明显破损？"}},"think_mode":"never","return_details":true,"return_thought":false}
```

服务端先下载并校验图片，再调用现有模型；任一图片失败则整次请求失败，不用缺图结果代替成功，也不自动重试推理。URL 校验、下载失败、超限或超时返回 HTTP 422，`detail[].loc` 指向 `images` 或对应索引。错误不回显 URL、签名或下载响应正文；上游限流仍可能返回 429。

`return_details: true` 时返回 `timing_ms.image_fetch`（图片接入阶段毫秒数）和 `image_input: {"url_count": 1, "download_bytes": 12345}`。`timing_ms.wall` 保持原模型计时口径，不包含新增 URL 下载；两者均不等于包含 Router 的端到端耗时。base64-only 或无图片时 URL 下载统计为零。不传 `return_details` 时不增加这些响应字段。

URL 只改变传输方式，不改变像素或 token 计费口径，也不保证更快。优先复用已上传 COS 的适当分辨率图片；比较 URL/base64 时使用同一图片字节。不要自动重试结果不明的收费请求。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/systemone' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"state":"Help! My payouts have been failing for 3 days.","model":"jev-latest","questions":{"is_urgent":{"type":"noul","instructions":"Does this convey urgency?"}}}'
~~~

## 其他分类：Vimox 图片分割（vimox-split）

`vimox-split` 是同步图片分割接口。支持文本描述、原图坐标框或正负点提示；文本模式由 Grounding DINO 定位候选物体，随后由 SAM 生成像素 mask。默认 `profile=fast` 使用 SAM 2.1 Tiny；传入 `boxes` 或 `points` 时跳过 DINO。接口路径为 `POST /v1/vimox-split/segment`，使用 `Authorization: Bearer <your-api-key>` 鉴权。

### POST /v1/vimox-split/segment

请求必须使用 `multipart/form-data`，必填字段为 `model=vimox-split` 和图片文件 `image`；`prompt`、`boxes` 与 `points` 至少提供一个。支持 PNG、JPEG、WebP，图片最多 25 MiB / 24 MP。可选字段 `box_threshold`、`text_threshold` 范围为 0-1；`max_detections` 范围为 1-64，默认值依次为 0.30、0.25 和 12。`profile` 为 `fast`（默认）、`balanced` 或 `quality`；`image_max_edge` 为 0（不缩图）或 256-4096；`mask_max_edge=0` 表示原图尺寸；`output_format` 可为 `rle`、`mask_png`、`crop`、`boxes`；`use_cache` 默认 true。`boxes` 是原图坐标 JSON 数组 `[[x1,y1,x2,y2]]`，提供后跳过 DINO；框选结果的 `score` 为 null。`points` 是原图像素坐标 JSON 数组 `[[x,y,label],...]`，label=1 为正点（目标），0 为负点（排除区域），1–64 个点，基于 EXIF 校正后的原图；可省略 prompt，与 boxes 互斥，提供后跳过 DINO。

成功响应为同步 JSON。每个 object 提供 `label`、检测分数 `score`、原图像素 `[x1,y1,x2,y2]` 格式的 `bbox`、mask 面积 `area_px` 和按 `output_format` 返回的 `mask`/`crop`。RLE mask 的 `format` 为 `coco_rle`，`size` 按 `[height,width]` 排列，`counts` 使用 COCO compressed-RLE 字符串（不是普通整数数组）；设置 `mask_max_edge` 后，响应会附带 `mask_scale`、`mask_area_px` 和 `area_is_estimate=true`。没有匹配目标时 `objects` 是空数组；无效文件或字段返回 Router 通用 JSON 错误。

Python 使用 `client.segment_image(image, prompt, ...)`，Node 使用 `client.segmentation.segment(image, { prompt, ... })`，Go 使用 `client.SegmentImage(ctx, image, options, &result)`。

~~~bash
curl 'https://router.vimox.cn/v1/vimox-split/segment' \
  -H "Authorization: Bearer <your-api-key>" \
  -F "model=vimox-split" \
  -F "prompt=red apple" \
  -F "image=@product.png;type=image/png" \
  -F "box_threshold=0.30" \
  -F "text_threshold=0.25" \
  -F "max_detections=12" \
  -F "profile=fast" \
  -F "output_format=rle" \
  -F "use_cache=true"
~~~

已有坐标框时可省略 `prompt` 并跳过 DINO：

~~~bash
curl 'https://router.vimox.cn/v1/vimox-split/segment' \
  -H "Authorization: Bearer <your-api-key>" \
  -F "model=vimox-split" -F "image=@product.png" \
  -F 'boxes=[[120,80,850,940]]' -F 'profile=fast' -F 'output_format=rle'
~~~

点提示也可省略 `prompt` 并跳过 DINO，不能与 `boxes` 同传：

~~~bash
curl 'https://router.vimox.cn/v1/vimox-split/segment' \
  -H 'Authorization: Bearer <your-api-key>' \
  -F 'model=vimox-split' -F 'image=@product.png' \
  -F 'points=[[120,180,1],[500,420,0]]' -F 'profile=fast' -F 'output_format=rle'
~~~

`image_max_edge=0` 表示不缩图，其他非零取值为 256–4096。`output_format=boxes` 在点提示下仍需运行 SAM，返回由 mask 计算的包围盒；文本/框提示则跳过 SAM。

使用 Python 官方 `pycocotools` 解码 `counts`：

~~~python
from pycocotools import mask as mask_utils

item = result["objects"][0]
rle = {
    "size": item["mask"]["size"],
    "counts": item["mask"]["counts"].encode("ascii"),
}
mask = mask_utils.decode(rle)  # uint8，shape=(height, width)
assert int(mask.sum()) == item["area_px"]
~~~

Python `client.segment_image(image, prompt=None, points=[[120,180,1],[500,420,0]])`、Node `client.segmentation.segment(image, { points: [[120,180,1],[500,420,0]], profile: "fast", outputFormat: "rle" })`、Go `client.SegmentImage(ctx, image, vimox.SplitOptions{Points: [][3]float64{{120,180,1},{500,420,0}}}, &result)` 都同步返回上述 JSON；无目标时检查空 `objects`，不要把 compressed `counts` 当成未压缩 RLE 数组处理。更完整的接口说明见 Router [`Vimox 图片分割 API`](../../docs/api/Vimox图片分割API.md)。

响应示例：

~~~json
{"id":"request-uuid","model":"vimox-split","image_size":{"width":1024,"height":1024},"objects":[{"id":0,"label":"red apple","score":0.91,"bbox":[120.0,80.0,850.0,940.0],"area_px":312000,"mask":{"format":"coco_rle","size":[1024,1024],"counts":"..."}}]}
~~~

## 其他分类：Vimox 图片深度图（vimox-image-depth）

`vimox-image-depth` 将单张图片转换为连续灰度相对深度图。接口同步返回图片二进制，宽高保持与输入一致；默认使用 JPEG 质量 92 减小文件体积，也可选择无损 PNG。深度值表示相对远近，不是带单位的真实距离。

### POST /v1/vimox-image-depth/depth

请求使用 `multipart/form-data`，必填字段为 `model=vimox-image-depth` 和图片文件 `image`。支持 PNG、JPEG、WebP，图片最多 25 MiB / 24 MP。`format` 可选 `jpeg`（默认，也接受 `jpg`）或 `png`；`quality` 范围为 70–100，默认 92，PNG 编码不使用该质量值。

成功时响应 `Content-Type` 为 `image/jpeg` 或 `image/png`，响应头 `X-Image-Width`、`X-Image-Height` 和 `X-Image-Format` 描述输出图片；错误使用 Router 通用 JSON 错误结构。

Python `client.image_depth(image, quality=92)` 返回 `bytes`；Node `client.imageDepth(image, { quality: 92 })` 返回 `ArrayBuffer`；Go `client.ImageDepth(ctx, image, options)` 返回 `[]byte`。

~~~bash
curl 'https://router.vimox.cn/v1/vimox-image-depth/depth' \
  -H "Authorization: Bearer <your-api-key>" \
  -F "model=vimox-image-depth" \
  -F "image=@input.png;type=image/png" \
  -F "format=jpeg" \
  -F "quality=92" \
  --output depth.jpg
~~~

## 其他分类：视频解析（xlf）

`xlf` 是同步的视频解析接口：输入文本或平台分享网址，返回一个可播放的视频 URL。它不是视频生成任务，不需要轮询。

### POST /v1/xlf/parse

请求体：`{"model":"xlf","input":"https://weixin.qq.com/sph/example"}`。兼容字段 `url`、`text`，以及兼容上游的 `POST /v1/parseVideoUrl` 路径由 Router 处理。

成功响应至少包含 `url` 或 `video_url`：

~~~json
{"url":"https://cdn.example/video.mp4","video_url":"https://cdn.example/video.mp4"}
~~~

Python 使用 `client.parse_video_url(input)`，Node 使用 `client.parseVideoUrl(input)`，Go 使用 `client.ParseVideoURL(ctx, input, &output)`。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/xlf/parse' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"xlf","input":"https://weixin.qq.com/sph/example"}'
~~~

## POST /v1/chat/completions

OpenAI Chat Completions 兼容

支持流式（SSE，data: [DONE] 结束）与非流式。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/chat/completions' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"<model>","stream":true,"messages":[{"role":"user","content":"..."}]}'
~~~

## vimox-audio 音频理解

`vimox-audio` 是文本类型的音频理解模型，通过 `POST /v1/chat/completions` 接收音频。`audio_url` 必须能由推理服务器访问；本地文件可先通过 `POST /v1/files/upload` 上传并取得 COS URL。成功响应保留标准 `usage.prompt_tokens`、`usage.completion_tokens`、`usage.total_tokens`，Router 会记录 token 用量。输入/输出费率暂未配置，管理端设置费率后按 token 扣费。

~~~bash
curl 'https://router.vimox.cn/v1/chat/completions' \
  -H "Authorization: Bearer <your-api-key>" \
  -H 'Content-Type: application/json' \
  -d '{"model":"vimox-audio","stream":false,"messages":[{"role":"user","content":[{"type":"text","text":"请逐句转录对白，标注起止时间、情绪和关键声音事件。"},{"type":"audio_url","audio_url":{"url":"https://example.com/clip.mp3"}}]}]}'
~~~

响应中的 `usage.prompt_tokens`、`usage.completion_tokens` 和 `usage.total_tokens` 可直接读取。SDK：Python `client.analyze_audio(url, prompt)`、Node `client.audio.analyze(url, prompt)` 或 `client.analyzeAudio(url, prompt)`、Go `client.AnalyzeAudio(ctx, url, prompt, options, &result)`。音频分析通常需要较长超时：Python 可将 `VimoxClient` 的 `timeout` 设置为 1800 秒，Node 可传入 `{ signal: AbortSignal.timeout(1800000) }`，Go 可将 `client.HTTPClient.Timeout` 设为 30 分钟并给 `ctx` 设置相应期限。费率为空期间 Router 仍记录用量，但不会收取 ViMoney。

## POST /v1/responses

OpenAI Responses 兼容

Codex CLI 默认协议（wire_api = 'responses'）。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/responses' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"<model>","stream":true,"input":[{"role":"user","content":[{"type":"input_text","text":"..."}]}]}'
~~~

## POST /v1/messages

Anthropic Messages 原生

支持 x-api-key / Bearer；未指定时注入 anthropic-version: 2023-06-01，并白名单转发 anthropic-version / anthropic-beta。响应与 SSE 均保持原生格式。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/messages' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"<model>","max_tokens":1024,"stream":true,"messages":[{"role":"user","content":"..."}]}'
~~~

## POST /v1beta/models/{model}:generateContent

Gemini 原生（流式加 :streamGenerateContent）

支持 v1alpha/v1beta/v1 与 x-goog-api-key；流式端点为 {model}:streamGenerateContent?alt=sse。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1beta/models/<model>:generateContent' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"parts":[{"text":"..."}]}]}'
~~~

## 应用层加密文本（可选）

为降低提示词在调试抓包或中间代理中的明文暴露风险，支持文本协议的客户端可以先调用
`GET /v1/secure/keys`，再把原始 JSON 按 SDK 的 `secureText` / `secureTextRequest` 方法
封装后提交到 `POST /v1/secure`。协议使用一次性 X25519 会话公钥、HKDF-SHA256 和
AES-256-GCM；公钥 60 秒有效且每个 `key_id` 只能使用一次。Router 解密后继续执行原有
鉴权、限额、计费、路由和 SSE 响应，因此响应格式不变。

该通道仅适用于 Chat、Responses、Anthropic Messages 和 Gemini 文本请求。含图片、视频或
音频内联数据的请求继续使用原有端点；HTTPS、API Key 安全存储和证书校验仍不可省略。
原有 `/v1/*` 协议保持兼容，旧客户端无需升级。

## POST /v1/embeddings

向量化

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/embeddings' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"<model>","input":"..."}'
~~~

## POST /v1/images/generations

图片生成。适用于 `/v1/models` 中 `protocols` 包含 `openai-images` 的模型。同步/异步描述的是响应生命周期，不改变图片协议：同步请求等待结果并直接返回 `data` 图片数组；异步请求先返回任务信息，再通过任务查询接口取得最终图片。

常用参数：`prompt`、`size`、`aspect_ratio`、`image_size`、`n`、`response_format`、`timeout_ms`。JSON 参考图建议使用 data URI/base64；能公开访问的参考图也可按模型能力传 URL。

支持 URL 参考图的模型（例如 `seedream-5.0`）使用既有 `image` 字段：单张传 HTTPS URL，多张按顺序传 URL 数组。上传成功或历史中能看到参考图后，生成请求仍必须显式携带该字段，例如 `{"model":"seedream-5.0","prompt":"保留主体，改为水彩风格","image":["https://example.com/reference-1.png","https://example.com/reference-2.png"],"image_size":"2K"}`。Python `image_generate_with_references`、Node `images.generateWithReferences`、Go `ImageGenerateWithReferences` 已使用此字段提交直传 COS 后的 URL；无需新增客户端方法或类型。模型不支持远程 URL 时，改用 multipart 文件或 data URI/base64。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/images/generations' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2.5","prompt":"一张电影感的城市夜景","size":"1024x1024","aspect_ratio":"1:1","n":1,"response_format":"url"}'
~~~

同步响应直接从 `data[]` 读取 `url` 或 `b64_json`，不包含任务 ID，不需要轮询。`gpt-image-2.5` 默认使用此同步模式。

### 异步图片提交与轮询

异步型号（如 `gpt-image-2-1k-async`、`gpt-image-2-2k`、`gpt-image-2-3.5k`、`gpt-image-2-4k` 及 2.5 分辨率档位）仍使用图片端点提交，不要将图片生成请求改成 Videos 协议。另有显式异步模式：`gpt-image-2`、`gpt-image-2-1k`、`gpt-image-2.5` 这些默认同步型号可由调用方主动 POST `/v1/videos` 创建任务。无论哪种方式，图片模型身份仍由 `openai-images` 标识。

图片端点异步提交示例：

~~~bash
API_KEY="<your-api-key>"
BASE="https://router.vimox.cn"
MODEL="gpt-image-2-2k"

TASK=$(curl "$BASE/v1/images/generations" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"model\":\"$MODEL\",\"prompt\":\"一张电影感的城市夜景\",\"size\":\"2048x2048\",\"aspect_ratio\":\"1:1\",\"image_size\":\"2K\",\"n\":1}")

ID=$(printf '%s' "$TASK" | node -pe "JSON.parse(require('fs').readFileSync(0,'utf8')).id")
POLLING_URL=$(printf '%s' "$TASK" | node -pe "JSON.parse(require('fs').readFileSync(0,'utf8')).polling_url || ''")
[ -z "$POLLING_URL" ] && POLLING_URL="/v1/videos/$ID?model=$(node -e "process.stdout.write(encodeURIComponent(process.argv[1]))" "$MODEL")"

while true; do
  STATUS=$(curl "$BASE$POLLING_URL" -H "Authorization: Bearer $API_KEY")
  echo "$STATUS"
  STATE=$(printf '%s' "$STATUS" | node -pe "const v=JSON.parse(require('fs').readFileSync(0,'utf8')); v.status || v.state || ''")
  case "$STATE" in
    succeeded|completed|complete|done|success) break ;;
    failed|error|cancelled|canceled) exit 1 ;;
  esac
  sleep 5
done
~~~

`size`、`aspect_ratio`、`image_size`、`n`、`response_format`、`timeout_ms` 为通用候选参数，是否生效及字段优先级以具体模型上游能力为准。异步图片任务在成功交付前会先持久化到 COS。

同步图片编辑使用 `POST /v1/images/edits`，通过 multipart 上传参考图；成功后直接读取 `data`，无需轮询：

~~~bash
curl 'https://router.vimox.cn/v1/images/edits' \
  -H "Authorization: Bearer <your-api-key>" \
  -F "model=gpt-image-2.5" \
  -F "prompt=把照片处理成电影感夜景" \
  -F "image=@input.png;type=image/png" \
  -F "size=1024x1024"
~~~

## POST /v1/images/edits

图片编辑（multipart）

编辑/参考图建议用 multipart 文件上传；支持 `image`、`mask` 等字段，具体以模型上游能力为准。同步型号直接返回图片；支持异步的型号从此端点提交后返回 `image.task`，再按上方“异步图片提交与轮询”说明获取最终结果。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/images/edits' -H "Authorization: Bearer <your-api-key>" -F "model=<image-model>" -F "prompt=..." -F "image=@input.png" -F "size=1024x1024"
~~~

## POST /v1/files/upload

上传图片、视频或音频到 COS

使用平台 Key 鉴权，不依赖门户开关。file 必填且每次一个，kind 可选（image、video、audio）；文件最大 20 MB。成功后返回稳定的 COS 公网 URL。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/files/upload' -H "Authorization: Bearer <your-api-key>" -F "file=@reference.png;type=image/png" -F "kind=image"
~~~

## OpenAI Audio / IndexTTS

`index-tts-2.5` 使用 OpenAI Audio 兼容协议。先上传参考音频取得 `voice`，再调用
`/v1/audio/speech`；上传接口返回的 24 位十六进制 id 只作为本 Router Key 的音色引用。
支持 ZH、EN、JA、ES、AR，标准合成入口返回 WAV。参考音频支持 wav、mp3、flac、m4a、ogg、aac，
单文件默认上限 50 MiB。音频模型按实际输出 WAV 时长计费，价格目录中的 `per_second` 为每秒 ViMoney，
不足 1 秒按 1 秒计费。

## POST /v1/index-tts/upload

上传 IndexTTS 音色参考音频并取得 voice id。该 voice id 用于后续语音合成。

~~~bash
curl 'https://router.vimox.cn/v1/index-tts/upload' \
  -H "Authorization: Bearer <your-api-key>" \
  -F "file=@reference.wav;type=audio/wav"
~~~

## POST /v1/audio/speech

使用 `index-tts-2.5` 合成语音，成功时响应为 WAV 音频字节。`voice` 填写上传音色接口返回的 id。
可选字段：`response_format`（当前为 `wav`）、`speed`、`emotion_source_id`、`emo_vector`（8 个数）、
`emo_alpha`、`use_emo_text`、`emo_text`、`use_random`、`duration_factor`（0.5-2.0）。
`duration_factor` 显式提供时优先于 `speed`；省略时由 `1 / speed` 推导。情绪控制互斥并按
`emotion_source_id`（参考情绪音频）> `emo_vector` > `emo_text` 选择，`emo_text` 会自动启用文本情绪。
自然中文对白可从 `emo_alpha: 0.4-0.6`、`use_random: false` 开始，避免过强情绪导致合成腔。

~~~bash
curl 'https://router.vimox.cn/v1/audio/speech' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"index-tts-2.5","input":"我真的很想你。","voice":"<voice-id>","response_format":"wav","language":"ZH","emo_text":"悲伤克制，带轻微哽咽，吐字清楚","use_emo_text":true,"emo_alpha":0.5,"use_random":false,"duration_factor":1.0}' \
  --output speech.wav
~~~

## POST /v1/files/presign

签发一次短期、Content-Type 绑定的 COS PUT 地址。SDK 客户端使用它直传本地参考素材，媒体字节不会经过 Router；上传成功后将响应的 `url` 用作图片或视频的参考 URL。COS Bucket 必须为 SDK 调用来源配置 CORS，并允许 `PUT` 与 `Content-Type`。

~~~bash
curl 'https://router.vimox.cn/v1/files/presign' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"kind":"image","contentType":"image/png"}'
~~~

## POST /v1/videos

视频生成：创建任务

支持 JSON URL/data URI 与 multipart 文件上传。multipart 可使用 input_reference、reference_image、reference_video、reference_audio，重复字段可上传多个素材。duration、resolution、ratio、generate_audio 等可选参数必须由目标模型明确支持后再添加。视频生成是异步任务，提交后返回 id、status、polling_url，不代表视频已完成。

MiniMax `minimax-h3-933-700p` 推荐使用 `reference_videos` 数组；兼容旧客户端的 `reference_video_urls` 数组会被 Router 转为同一素材字段。SDK 的视频创建方法保留未知模型参数，因此可直接传入该别名。

`vimox-depth` 与 `vimox-depth-fast` 只需提供一个源视频（`reference_videos`）；提示词可省略，且无需传 `duration`、`resolution`、`ratio` 或 `aspect_ratio`。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/videos' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"<video-model>","prompt":"..."}'
~~~

### multipart 参考文件上传

~~~bash
curl 'https://router.vimox.cn/v1/videos' -H "Authorization: Bearer <your-api-key>" -F "model=<video-model>" -F "prompt=让主体自然运动" -F "input_reference=@reference.png;type=image/png"
~~~

深度视频模型的 JSON 请求示例：

~~~bash
curl 'https://router.vimox.cn/v1/videos' \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"vimox-depth-fast","reference_videos":["https://example.com/input.mp4"]}'
~~~

## GET /v1/videos/{id}?model={model}

视频任务轮询

轮询必须携带 model query，用于路由回创建任务的模型；含 / 的模型名需要 URL 编码。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/videos/{id}?model=<model>' -H "Authorization: Bearer <your-api-key>"
~~~

## GET /v1/videos/{id}/content?model={model}

视频结果下载

任务成功后下载结果文件；如状态响应已包含 video_url，也可直接使用返回的结果地址。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/videos/{id}/content?model=<model>' -H "Authorization: Bearer <your-api-key>"
~~~

## GET /v1/models

本 Key 可用模型列表

返回 OpenAI 风格 {object:'list',data:[...]}，并包含 mediaType、protocols、parameters 用于自动生成对接说明；按分钟计费模型还会返回 `priceVimoneyPerMinute` / `priceVimoneyPerMinuteMicros` 与 `billingMode: per_minute`。
视频模型的 `parameters` 会与 `capabilities.durationSeconds`、`capabilities.aspectRatios` 和 `capabilities.resolutions` 对齐；客户端可根据能力数组生成时长、画幅和清晰度选项。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/models' -H "Authorization: Bearer <your-api-key>"
~~~

## GET /v1/usage

用量与额度（本页数据源）

查询参数：days（1-90）、tzOffsetMinutes、keyId。OAuth 登录默认聚合当前账号全部 Key，keyId 只能筛选当前账号所属 Key。

### 请求示例

~~~bash
curl 'https://router.vimox.cn/v1/usage' -H "Authorization: Bearer <your-api-key>"
~~~


# Vimox ASR

`POST /v1/audio/transcriptions`，Bearer 鉴权，`multipart/form-data`，同步返回 JSON。
默认按分钟计费，不足 1 分钟按 1 分钟；若模型目录明确配置 `per_second`，则按实际秒数计费。
对外模型名 `vimox-asr`；Whisper large-v3 FP16 转录、WhisperX 中英文词级对齐、CAM++ 说话人分离。

| 字段 | 说明 |
| --- | --- |
| model | 必填，`vimox-asr` |
| file | 必填，音频或含音轨的视频，最大 20 MiB、3600 秒；支持 FFmpeg 可解码的 WAV/MP3/FLAC/M4A/MP4 等 |
| language | 可选，Whisper 小写语言代码；省略自动检测 |
| align | `true`（默认）或 `false`；已部署 `zh`/`en` 对齐，其他语言须关闭 |
| diarize | `true`（默认）或 `false`；有效语音必须超过 5 秒，短音频须关闭 |
| num_speakers | 可选整数 1–10；省略自动估计 |
| response_format | `verbose_json`（默认）或 `json`，两者均返回下述完整结构 |

```bash
curl https://router.vimox.cn/v1/audio/transcriptions --max-time 600 \
  -H "Authorization: Bearer $VIMOX_API_KEY" \
  -F model=vimox-asr -F file=@input.mp3 \
  -F language=zh -F align=true -F diarize=true
```

响应包含 `model`、`task=transcribe`、`text`、`language`、`duration`（秒）、`segments[]`、
`words[]`、`speakers[]`、`diarization[]` 和 `processing`。`segments` 包含 start/end/text 和
可选 words/speaker；`words` 包含 word 和可选 start/end/score/speaker。无法可靠对齐的词可能
缺少时间；不得自行假定每个词都有时间。`diarization` 为 start/end/speaker 区间，时间均为秒。
`SPEAKER_00` 等标签只在当前文件内有效，不识别真实身份，也不跨文件保持一致。

`processing` 包含总秒数、各阶段耗时、音频处理倍速、batch size 和实际使用的推理/分离引擎。
转录可识别多语言，中英混合采用检测到的主要语言对齐，混合术语的词级精度需业务样本验证。
CAM++ 不保证区分同时重叠讲话；小于 30 秒或超过 10 人的录音质量可能下降。

错误：400 参数/解码/语音过短或对齐语种不支持；401 鉴权失败；413 文件过大；
422 解码超时；429 队列满（含 `Retry-After`）；500 推理失败；503 后端不可用。
单 GPU 部署 2 个实例，每实例一次执行一个任务、最多 4 个在途请求（含上传、执行及等待），
合计最多 2 个执行任务和 8 个在途请求；这不是 8 路实时转录承诺。
建议客户端超时至少 600 秒；长任务及排队时可配置更长，不应自动无限重试。

Python：`VimoxClient(key, timeout=600).transcribe_audio("input.mp3", language="zh")`。
Node：`client.audio.transcriptions(blob, {language: "zh"})`，也可用 `transcribeAudio`。
Go：`client.TranscribeAudio(ctx, file, vimox.TranscriptionOptions{Language: "zh"}, &result)`，
返回类型可使用 `TranscriptionResult`，并设置适合长任务的 HTTP/context 超时。

## vimox-talk 数字人对口型

MuseTalk 1.5 视频模型，`POST /v1/videos` multipart 上传 `video` + `audio`，返回异步任务。Python `client.lip_sync_video("input.mp4", "speech.wav")`；Node `client.videos.lipSync(videoBlob, audioBlob)`；Go `client.LipSyncVideo(ctx, videoFile, audioFile, nil, &result)`。单 GPU 默认 `batch_size=8`，队列满返回 429；详情见 `docs/api/Vimox数字人对口型API.md`。

# 用户并发与离线模型目录

用户有两个独立并发池：文本模型默认 10；图片、视频、音频、向量、决策、解析及其他非文本模型共享默认 10。按 Vimox 用户 ID 合并全部 API Key 和 OAuth；本地 Key 使用 `key:<key-id>`。单模型 `maxConcurrency` 继续叠加生效。

后台“访问控制 → 用户并发”（`/admin/access/concurrency/`）可修改默认值和指定用户额度。用户留空的池继承默认值，0 表示不限；删除用户覆盖恢复默认。保存后对新请求生效，不取消已运行请求。

同步和流式调用到响应结束或断开时释放用户名额。异步图片、视频等任务提交后，排队及生成中持续占用，成功、失败、取消等终态释放。任务查询和下载不重复占用。异步任务占位存储在 SQLite 中，重启后仍可查询和释放；用户停止轮询时，额度满后的后台复查会更新任务状态，客户端可遵循 Retry-After 重试。单模型限制保持请求并发口径，异步提交响应结束即释放模型名额。

Router 并发超限返回 HTTP 429、`Retry-After: 5` 和 `X-Trace-Id`。客户端必须显示 `error.message`，保留 reason 与 trace 用于诊断：

```json
{"error":{"code":"rate_limited","reason":"user_concurrency_limited","message":"您的其他模型并发额度已满：当前占用 10，上限 10。图片、视频、音频及其他非文本模型共享此额度，排队和生成中的异步任务也占用名额；请等待请求或任务完成，或联系管理员提高您的其他模型并发额度。","scope":"user","bucket":"other","model":"minimax-h3-93-700p","current":10,"limit":10,"retryable":true}}
```

文本池 `bucket=text`；非文本池 `bucket=other`。单模型限制为 `reason=model_concurrency_limited`、`scope=model`、`bucket=null`。不要只凭 HTTP 429 推断是哪层限制，上游也可能返回 429。Node `VimoxError.details`、Python `VimoxError.details`、Go `Error.Details()` 保留这些字段。

## 门户与轻量用量查询

`/users/pricing`（模型列表与价格）、`/users/connect` 和 `/users/apidocs` 可免登录查看。公开模型页展示目录快照；登录后按当前账号权限展示可用模型与价格。`/users/models` 为个人模型用量统计，仍需登录。账户用量、账单和密钥管理仍需鉴权。最近请求、每日用量、账单、邀请码、创作工具、价格、模型统计分别使用 `/users/recent`、`/users/daily`、`/users/billing`、`/users/invitations`、`/users/tools`、`/users/pricing`、`/users/models`，支持刷新与浏览器历史。

门户默认查询当地当天（`days=1`），每页 20 条；可选择 7/30/90 天。先显示账户与近期记录，历史汇总独立加载，完整 API 文档在打开文档页时渲染。OAuth Key 范围缓存按主站和账号隔离，同账号请求合并，不同账号不共用网络锁。首次 OAuth 查询仍依赖主站完整 Key 清单。

```http
GET /v1/usage?days=1&tzOffsetMinutes=480&view=recent&recentLimit=20
Authorization: Bearer <API Key or OAuth token>
```

`days` 为 1–90，API 未传时仍默认 7；按客户端时区的今日零点往前计算。`view=recent` 不做历史用量汇总；`view=summary` 不读近期列表；省略 view 返回完整信息。近期列表及 recentTotal 均按 days 过滤；usage.total 仍是累计总用量。普通 Key 仅查询自身；OAuth 默认汇总当前用户全部有效 Key，keyId 仅可选择本人 Key。

`recentLimit` 为 1–100；后续页推荐同时传最后一行的 `createdAt` 与 `traceId`，分别作为 `recentBefore` 和 URL 编码的 `recentBeforeTrace`。游标是严格之前，避免相同时间戳重复；修改 days 或 keyId 后重置游标。兼容 `recentPage`。

Node：`client.usage({days: 1, tzOffsetMinutes: 480, view: "recent", recentLimit: 20})`。Python：`client.usage(days=1, tz_offset_minutes=480, view="recent", recent_limit=20)`。Go：`client.UsageWithOptions(ctx, vimox.UsageOptions{Days: 1, View: "recent", RecentLimit: 20}, &result)`；原 Usage 方法保持兼容。

## 离线目录

在 Router 仓库根执行 `npm run sync:model`。脚本读取根 `.env` 的 `ROUTER_API_KEY`（或环境变量 VIMOX_API_KEY / ROUTER_API_KEY），从 HTTPS `/v1/models` 获取该 Key 当前可见的全部公开信息，保留价格、能力、参数、协议和扩展字段，验证后写入 `vimox-sdk/docs/model-catalog.json` 及三种语言资源。不会输出密钥，网络或响应校验失败保留已有目录。私有渠道标识不得进入公开目录。

Node：`import { getModelCatalog } from "@vimox/router-sdk/catalog"; const catalog = getModelCatalog();`，亦可从主入口导入；JSON 子路径为 `@vimox/router-sdk/model-catalog.json`。Python：`from vimox import get_model_catalog; catalog = get_model_catalog()`。Go：`catalog, err := vimox.ModelCatalog()`。这些函数无需凭证或网络，每次返回独立对象。

目录是同步时的快照，不会在其他项目运行时自动追踪线上变化；维护者同步后，消费项目需要更新所引用的 SDK。实时可用性和用户权限始终以服务端为准。打包和发布须由授权发布流程完成。


## Thinking 响应与纯文本输入（2026-10-25）

`vimox-audio` 的模型 ID 和 `/v1/chat/completions` 不变，支持纯文本消息，也支持用户消息中的 `text` + `audio_url`（最多 4 段）。无需为纯文本请求提供空音频。

最终答案读取 `choices[0].message.content`，思考过程读取可选的 `choices[0].message.reasoning_content`。流式时分别读取 `choices[0].delta.content` 和 `choices[0].delta.reasoning_content`，按 SSE 空行分帧；保留结束帧、usage 和 `[DONE]`。仅有思考内容不代表已有最终答案，不要把思考内容自动当作答案。

`max_tokens` 包括思考与答案。音频 Worker 会在总输出预算内预留答案额度，必要时结束未闭合思考并续写；仍无答案时返回 HTTP 502 `empty_model_response`，而非成功空文本。`usage` 为真实两阶段 token 用量之和（包含续写输入）。当前音频 SSE 在推理完成后依次发送字段，不提供逐 token 实时输出。

Python `chat_completions(model="vimox-audio", stream=False, messages=[{"role":"user","content":"你好"}])` 返回字典，保留 `message.reasoning_content`；Node `chatCompletions` 保留同字段，SSE 可用 `{responseType:"response"}` 取得原始 Response；Go `ChatCompletions` 可解码到 `ChatCompletionResponse` 或 `map[string]any`，原始 SSE 可接收到 `[]byte`。Python/Go 当前同步辅助方法不提供增量 SSE 迭代器。

新增公开类型 `ChatCompletionMessage`、`ChatCompletionChoice`、`ChatCompletionResponse`，Node 另含 `ChatCompletionChunk`，Python 可从 `vimox.chat_types` 导入。模型目录中的文本分类、音频输入能力、端点和鉴权保持现行配置。本次只更新源码与文档，未构建、打包或发布 SDK 下载产物；线上门户未同步。


## 画布视频积分授权（2026-10-26）

视频继续使用 `POST /v1/videos`、`GET /v1/videos/{id}?model=...` 和 `/content`，平台 Bearer 鉴权不变。模型来自账号同步后的 `/v1/models`，只选择 video/openai-videos；不在 SDK 离线目录编造 canonical ID 或上游积分价格。

`credit_ceiling` 是调用方明确批准的上游积分上限，与 Router 的 ViMoney 账单独立。需要确认或超限时返回 HTTP 400，错误码 `generation_confirmation_required`，包含原 id、polling_url、required_action=confirm 和 credit_confirmation；先展示报价并获得批准，再用原 model、resume_task_id=id、credit_ceiling POST /v1/videos。不要重新提交提示词或创建节点；已受理任务只轮询，不重复运行。GET 查询不触发生成，成功视频仅返回持久 COS URL。

Python：`client.video_resume(task_id, model, approved_ceiling)`。
Node：`client.videos.resume(taskId, model, approvedCeiling)`。
Go：`client.VideoResume(ctx, taskID, model, approvedCeiling, &output)`。
初次 400 的 task 信息在 SDK 错误体中；三个客户端的等待方法在遇到 required_action=confirm 时停止，保留任务信息给调用方。调用方仍使用原平台身份，原模型和原任务绑定账号。

本次同步仓库内 SDK 源码、类型、文档及回归用例。线上未同步；未构建 SDK ZIP 或发布包，离线模型快照待获得真实账号目录并由授权发布流程刷新。完整管理员配置与恢复约束见 Router 文档 docs/api/channels/video-dreamina-canvas.md。
