模型网关 API
第一版模型网关提供最小可测的模型中转能力:模型列表、文本模型调用、音频转文本。
当前 Base URL:
/api/model-gateway/v1后续接入动态子域名后,再扩展为独立 Inference API / Audio API 域名。
端点索引
GET /api/model-gateway/v1/models
返回当前 API Key 可用的 OpenAI-compatible 模型列表。
POST /api/model-gateway/v1/chat/completions
执行文本或多模态 Chat Completions。支持普通 JSON 响应与流式 SSE,消费归因到调用方 Team。
POST /api/model-gateway/v1/audio/transcriptions
使用 multipart/form-data 上传 file 并指定 model,返回 OpenAI-compatible 音频转写结果。
Authentication
公开 API 调用使用现有团队 API Key。支持两种认证方式:
# X-API-Key header
curl -H "X-API-Key: YOUR_KEY" /api/model-gateway/v1/models
# Bearer Token
curl -H "Authorization: Bearer YOUR_KEY" /api/model-gateway/v1/modelsAPI Key、团队余额、API Key 限额和扣费均复用现有体系。
官方移动端可以使用 OAuth access token 调用同一组端点:
curl -H "Authorization: Bearer wno-ACCESS_TOKEN" \
/api/model-gateway/v1/models移动端 OAuth token 必须具备 mobile:full scope;AI-Vibe-Board 使用 vibe-board:cloud scope。后端会把该用户映射到个人默认 project/team,并创建或复用一个隐藏的 Mobile App API Key 作为账单锚点。这个系统 API Key 不会返回给客户端,也不会在用户 API Key 管理界面展示或允许删除。
Driver V2 使用 vibe-board:cloud scope 调用同一网关,并以独立 usage source 记账。 客户端不提交 provider URL、provider key 或计费身份;这些都由服务端和 OAuth 会话决定。
普通 Supabase JWT 不属于模型网关用户态认证范围;未授权 OAuth app、匿名请求和 scope 不足的 token 会被拒绝。
Endpoints
| Endpoint | Description |
|---|---|
GET /models | List available text, vision and ASR models |
POST /chat/completions | OpenAI-compatible chat completion, supports streaming |
POST /audio/transcriptions | OpenAI-compatible audio transcription |
Models
curl -H "Authorization: Bearer YOUR_KEY" \
/api/model-gateway/v1/models响应:
{
"object": "list",
"data": [
{
"id": "qwen3:32b",
"object": "model",
"created": 0,
"owned_by": "WaiNao",
"capabilities": ["text"],
"billing": {
"unit": "token",
"unit_size": 1000000,
"price_input_credits": 190,
"price_output_credits": 1000
}
},
{
"id": "glm-4-5v",
"object": "model",
"created": 0,
"owned_by": "WaiNao",
"capabilities": ["text", "vision"],
"billing": {
"unit": "token",
"unit_size": 1000000,
"price_input_credits": 190,
"price_output_credits": 1000
}
},
{
"id": "sense-voice-small",
"object": "model",
"created": 0,
"owned_by": "WaiNao",
"capabilities": ["asr"],
"billing": {
"unit": "second",
"unit_size": 1,
"price_per_unit_credits": 0.03
}
}
]
}仅返回已发布、已上架、已配置计费且有可用供应链的文本模型、视觉模型和 ASR 模型。
capabilities 说明:
text:支持文本生成,Token 计价。vision:支持图片输入(多模态)。视觉模型仍为 Token 计价,通常同时携带text;该标记表示模型可接受image_url内容(issue #1253 前视觉能力标记未透出,现已修复)。asr:支持音频转写,按秒计价。
billing 始终以积分给出客户端展示价格:Token 模型直接使用计费规则中的权威积分售价,非 Token 模型按站点共享汇率派生积分单价且保留小数精度。普通 API Key 与 OAuth 调用方的响应中完全不包含任何 *_cents 属性。
只有调用凭据归属用户持有 site:admin grant 时,响应才会在相同积分价格之外额外包含原始 cents,例如:
{
"billing": {
"unit": "token",
"unit_size": 1000000,
"price_input_credits": 190,
"price_output_credits": 1000,
"price_input_cents": 63,
"price_output_cents": 333
}
}Team owner/admin、官方 OAuth App、mobile:full 和 vibe-board:cloud scope 都不会自动获得 cents。权限查询异常时按非管理员处理:积分价格仍返回,cents 完全省略。
Chat Completions
curl -X POST /api/model-gateway/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3:32b",
"messages": [{"role": "user", "content": "帮我润色这段文字"}],
"stream": false
}'流式调用:
curl -X POST /api/model-gateway/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3:32b",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
}'支持字段:
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | /models 返回的模型 ID |
messages | array | yes | OpenAI Chat messages |
stream | boolean | no | true 时返回 SSE |
temperature | number | no | 透传到内部 AI service |
max_tokens / max_completion_tokens | number | no | 映射为内部 maxOutputTokens |
stop | string or string[] | no | 停止词 |
tools | array | no | OpenAI function tools |
tool_choice | string or object | no | none / auto / required 或指定 function |
stream_options.include_usage | boolean | no | 流式 [DONE] 前追加 usage 尾帧 |
计费:按现有文本模型 token 价格记录 model_usage。
工具循环
assistant 工具消息允许 content: null 或缺省,但必须同时带非空 tool_calls。 role=tool 消息必须带非空字符串 tool_call_id;tool_calls 每项必须有非空字符串 id、type=function、非空 function.name 和字符串 function.arguments,畸形值在调用 上游前返回 400 invalid_message。非流式响应会返回 message.tool_calls 与 finish_reason: "tool_calls":
{
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": { "name": "device_status", "arguments": "{}" }
}]
},
"finish_reason": "tool_calls"
}],
"usage": {
"prompt_tokens": 100,
"completion_tokens": 20,
"total_tokens": 120,
"prompt_tokens_details": { "cached_tokens": 64 }
}
}流式响应以 delta.tool_calls[].function.arguments 逐段追加 JSON 参数;公开 index 按工具 元信息首次到达顺序连续分配,参数片段早到时缓冲到首个元信息 delta 一起带出,客户端按 index 重组即可,支持多工具交错与文本+工具混合。请求带 "stream_options":{"include_usage":true} 时,在 [DONE] 前返回一个 choices: [] 的 usage chunk;未请求时不发送该尾帧。
终态与取消:上游返回错误、工具元信息不完整、声明 tool_calls 却无完整工具、工具协议 请求在无真实 finish_reason 时截断(EOF)或响应为空,均判定失败;流式已返回 HTTP 200 时以 error SSE 帧加 [DONE] 终止,不会出现成功 finish_reason 或 usage 尾帧(非工具 且已有非空文本的旧式 EOF 截断保留兼容成功)。客户端断开或取消时取消信号透传上游,返回 499 request_cancelled,晚到数据不会拼接成新的成功响应。
Audio Transcriptions
curl -X POST /api/model-gateway/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_KEY" \
-F "file=@sample.wav" \
-F "model=sense-voice-small" \
-F "language=auto" \
-F "response_format=json"响应:
{ "text": "转写结果" }第一版约束:
model必填,必须是/models返回的capabilities含asr的模型。response_format仅支持json。- 服务端必须能解析音频时长,无法确定时长时返回 422。
- 文件大小上限为 25 MiB。
计费:按 ASR 模型 billing_rules.billing_unit = second 的秒级价格记录 model_usage,保留音频毫秒精度,失败不扣费。
豆包录音极速版上架后可选择 model=volcengine-bigasr-flash,客户端请求格式不变。服务端将其映射为 doubao 渠道的 volcengine-openspeech-auc-flash 协议,只读取 OpenSpeech 凭据;此 adapter 上限为 20 MiB,仅支持 WAV/MP3/OGG/OPUS。模型仍须通过发布、权限与余额门禁,未上架时不会出现在模型列表中。
OpenSpeech Key 所在项目还须开通 volc.bigasr.auc_turbo。供应商返回 403 requested resource not granted 表示资源授权未就绪;保存 Key 或跳过聊天探针不能代替真实音频测试。后端在 Bun 下使用 npm Undici 的完整 dispatcher 实现,以保留 DNS 固定和正确的连接清理。
上游地址或服务配置导致的 HTTP 拒绝按上游失败返回,不会误报为用户音频无效。配置有后备渠道时继续尝试,只有成功转写才计费。
Errors
错误响应使用 OpenAI-compatible 结构:
{
"error": {
"message": "Missing API key or authorization header",
"type": "authentication_error",
"code": "missing_api_key"
}
}常见状态:
| Status | Code | Description |
|---|---|---|
| 400 | invalid_message / invalid_stream_options | 消息体或历史 tool_calls / tool_call_id 畸形,或 stream_options 非对象,未调用上游 |
| 401 | missing_api_key / invalid_api_key | API Key 缺失或无效 |
| 402 | insufficient_quota | 团队余额不足 |
| 403 | api_key_credit_limit_exceeded / insufficient_scope | API Key 限额已用尽,或 OAuth scope 不允许访问模型网关 |
| 404 | model_not_found | 模型不存在或不可用于该接口 |
| 422 | audio_duration_unavailable | 无法确定音频时长,拒绝执行以避免错误计费 |
| 499 | request_cancelled | 客户端在完成前取消;取消已同步透传给上游 |
| 502 | model_upstream_error / asr_upstream_failed / invalid_tool_call / unexpected_eof / missing_completion / chat_completion_failed | 上游模型供应链失败,或上游丢失工具元信息、异常截断、无有效终态,不能投影为成功响应 |
普通插件 OAuth
申请并正常审核发布 model-gateway:invoke,用户确认后使用插件自身 delegated token 调用本页三个接口(模型目录、流式/非流式对话、音频转写)。Host 只需 oauth:delegate;不使用 Host 专属 vibe-board:cloud,不按 official 标记或 Voice client ID 放行。
该权限会使用授权用户默认团队额度;用量记录 source 为 plugin_model_gateway,oauthAppId 为调用插件的 OAuth 应用 row ID。已有刷新、撤销、scope 定义版本及 revision 资格校验继续生效。插件 manifest 的云能力平台批准不能替代 OAuth scope 与用户授权。