模型网关 API
管理员模型 key 映射草稿
管理员可通过 /admin/model-key-mappings 独立配置 A 渠道模型 key 到 B 渠道模型的精确变体映射,支持普通人工切换和计划弃用两种用途。每条配置只命中一个来源 (provider, model_id, protocol);同一公开 key 下其他渠道变体不受影响。管理 API 提供列表、新建、编辑、预览、审计与归档。
当前所有映射均为草稿,不会改变任何公开调用。 数据库强制 enabled=false;尝试启用返回 409。对外模型身份、价格与扣费归属确定并完成运行时和真实渠道验收前,这项配置不能提供转发服务。
模型网关提供模型目录,以及聊天、转写、向量、重排、语音、图片、原生 Jev 和异步视频接口。OAuth 应用使用模型调用能力;普通 API Key 保留各任务的既有授权设置。具体操作与可用性由模型目录声明。
八类模型能力的实施合同与现有 API 的逐项差异,见模型能力接口实施合同。新增端点会逐项上线;以下端点仍是当前可用范围。
当前 Base URL:
/api/model-gateway/v1后续接入动态子域名后,再扩展为独立 Inference API / Audio API 域名。
端点索引
GET /api/model-gateway/v1/models
无参保留文本、视觉和 ASR 的历史目录。OAuth 应用使用 ?task=all 获取完整已发布模型库;按任务筛选可用 ?task=tts 等参数。发布后不再设置网关专用的模型白名单或探针时效许可。
无 task 参数时沿用原有文本、ASR、视觉列表。可选 ?task=chat|asr|vision|embedding|rerank|tts|video|decision|all 只列该任务的模型;显式任务保留已发布模型的完整能力、原价与 availability;供应暂不可用不会从目录消失。调用仍检查有效渠道、真实协议适配和凭据,不另设网关探针许可。task=rerank 的价格按 search_unit 返回,普通调用方只看到积分价格,管理员可额外看到美分单价。task=video 的异步任务合同见下文。无效 task 返回 400。
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 音频转写结果。
个别模型有更严的单文件限制(如 qwen3-asr-flash 单文件不超过 5 分钟、7 MB)。超限时若该模型还有其它供应变体则自动改走后备,否则返回 413 audio_duration_too_long / audio_file_too_large。
POST /api/model-gateway/v1/embeddings
提交 model 和非空文本 input(字符串或最多 128 项的字符串数组),可选 dimensions;encoding_format 仅支持 float。返回 OpenAI-compatible 向量列表与供应商报告的 token 用量。
普通 API Key 继续按任务授权。团队 owner 可在 PATCH /teams/:teamId/api-keys/:keyId 传入 {"model_gateway_embeddings_enabled":true},为指定普通 API Key 开启;旧 Key 默认关闭,系统 Key 不可开启。OAuth 应用的统一 model-gateway:invoke 已包含此端点;旧 model-gateway:embeddings scope 保留窄权限兼容。mobile:full、vibe-board:cloud 不扩大到此端点。
向量模型与其它任务共用已发布模型库、供应配置和价格。模型需具备 embedding 能力及实际可用的向量协议,维度必须受该供应支持。目录保留暂不可用模型并说明原因;调用使用真实 token 用量和持久计费回执。OAuth 知识库同步入库与文本检索共用此执行链,不经过 Flow,也不另设知识库模型许可。
/api/model-gateway/v1/video/generations
公开视频任务采用异步 Operation:创建后通过任务 ID 查询、取消或读取已发布文件。具体合同见下文。
POST /api/model-gateway/v1/rerank
按 Cohere v2 的文本重排格式提交 model、query、非空字符串数组 documents 和可选的 top_n。响应保留原文档的 index、relevance_score 和供应商报告的 meta.billed_units.search_units。首版不支持对象文档、max_tokens_per_doc 等无法在当前渠道无损表达的参数;传入这类字段会返回 400。
此端点另需普通 API Key 显式开启 model_gateway_rerank_enabled=true,或 OAuth token 拥有统一 model-gateway:invoke / 旧 model-gateway:rerank scope。调用复用后台已发布 search_unit 价格与精确可用渠道,不再次要求网关专属探针。按返回的 search_units 扣费成功后才交付结果。价格、供应商凭据与发布流程沿用后台现有配置;模型未发布或无实际可用供应时拒绝调用。
管理员在候选上架表单按“美分/搜索单位”填写重排单价,也可通过 POST /admin/billing-rules/prepare 传 billing_unit=search_unit 与正数 price_per_unit_cents 建草稿,再用 approve-pricing 审核。后台发布流程继续要求精确渠道 rerank yes/v1 探针;管理员连通性检查直接调用 /rerank。向量模型的检查则调用 /embeddings,原有 Chat 检查流程不变。
POST /api/model-gateway/v1/audio/speech
接受 JSON model、非空 input、可选 voice、必填 project_id 和可选的 response_format(mp3、opus、wav、pcm 中该模型支持的子集)。voice 省略时使用模型默认音色;response_format 省略时使用模型默认格式。input 整体最多 4096 个 UTF-8 字节,各模型另有码点上限(见下表),暂不支持流式输出。成功响应是原始音频字节,Content-Type 对应音频格式,X-Wainao-Storage-File-Id 是自动写入项目存储的文件 ID,X-Wainao-Storage-Expires-At 是扣费后发布时确定的到期时间。项目生成文件默认保存 7 天,项目管理员可改为 24 小时或 30 天。文件先以不可读状态入库;只有正价扣费成功并完成发布后才返回音频成功响应。存储、扣费或发布失败时返回 JSON 错误,已扣费但待发布的文件由后台持续重试发布。
可用模型、音色与默认值以 GET /models?task=tts 每项的 tts.voices / tts.default_voice 为准(服务端把公开音色转换为供应商所需的值,调用方不能提交供应商 key、自定义地址或供应商完整音色名)。当前适配:
| 模型(供应) | 默认音色 | 输出格式(默认) | 输入上限 | 计费口径 |
|---|---|---|---|---|
| CosyVoice2(硅基) | alex | mp3 / opus / wav / pcm(mp3) | 4096 UTF-8 字节 | 每百万 UTF-8 字节 |
| MOSS-TTSD v0.5(硅基) | alex | mp3 / opus / wav / pcm(mp3) | 4096 UTF-8 字节 | 每百万 UTF-8 字节,按原文计(服务端自动补的 [S1] 说话人标签不计费) |
| step-tts-mini / step-tts-2 / stepaudio-2.5-tts / stepaudio-3-tts(阶跃) | wenrounvsheng | mp3 / wav(mp3) | 1000 字符 | 每万字符 |
| qwen3-tts-flash(通义) | Cherry | wav(wav) | 600 字符 | 每万字符 |
| qwen-audio-3.0-tts-flash(通义) | longanhuan_v3.6 | mp3 / wav(mp3) | 2000 字符 | 每万字符 |
| qwen-audio-3.0-tts-plus(通义) | longanlingxin | mp3 / wav(mp3) | 2000 字符 | 每万字符 |
| qwen-audio-3.1-tts-flash(通义) | yuxiaoyun_v3.1 | mp3 / wav(mp3) | 2000 字符 | 按上游实际返回的输入/输出 token 结算 |
「字符」指 Unicode 码点数,不区分中英文。不在该模型音色清单内的 voice 返回 400 unsupported_voice;不支持的格式返回 400 unsupported_response_format;超过该模型上限的输入返回 400 input_too_long,均在计费与请求供应商之前拒绝。按 token 结算的模型若上游没有返回可核验的 token 用量,本次不交付音频、不扣费,返回 502 speech_usage_unavailable。计费按该模型已发布规则的单位结算,价格单位与模型适配器不一致的变体不会被选用。
普通 API Key 保留单独任务授权:团队 owner 用 PATCH /teams/:teamId/api-keys/:keyId 设置 {"model_gateway_tts_enabled":true},旧普通 Key 默认关闭,系统 Key 不可开启。OAuth 应用使用统一 model-gateway:invoke 或旧 model-gateway:tts scope。调用者还必须有 project_id 项目的写权限,且项目与计费团队一致。可传 Idempotency-Key(最多 128 字节)安全重试:相同请求返回同一项目存储文件,不重复生成和扣费;相同键搭配不同请求返回 409,文件到期或被删除后不能重放成功。省略 response_format 的请求与显式 mp3 共用同一幂等身份(历史兼容):若同一键已生成的文件格式与本次显式指定的格式不一致(例如先省略得到 WAV,再显式要 mp3),返回 409 idempotency_conflict,不会重新合成;省略格式的重试会重放已存文件。必须有已发布模型、可用供货与实际语音适配器。当前附件交付还需扣费凭据,零价或单字节不足最小计量粒度的 TTS 在目录标 billing_delivery_unavailable;不通过额外 OAuth 权限解决。
若扣费流水已确认而文件仍待发布,同一幂等键会按原文件和原流水继续发布,即使暂定保留期已过或模型后来下架;未扣费文件过期、丢失或无法预约时不会事后扣费。已发布文件按发布时确定的保留期限判断是否还能重放。
团队存储已满时返回 507 storage_quota_exceeded,不会请求供应商;生成后若实际音频超出剩余额度,上传失败且不返回成功音频。首次生成前的配额预检失败会释放幂等键,配额恢复后可用同一键重试。
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 (legacy response) |
GET /models?task=tts | List verified speech generation models |
GET /models?task=image-generation | List verified text-to-image models |
GET /models?task=image-edit | List verified single-reference image editing models |
GET /models?task=video | List published video models with actual supply availability and configured prices |
POST /chat/completions | OpenAI-compatible chat completion, supports streaming |
POST /images/generations | Generate one image and save it to the specified project's Storage |
POST /images/edits | Generate one image using one reference image and save it to project Storage |
POST /audio/transcriptions | OpenAI-compatible audio transcription |
POST /embeddings | OpenAI-compatible text embeddings; separate credential permission |
POST /rerank | Cohere v2-compatible text reranking; separate credential permission |
POST /video/generations | 创建异步视频任务,返回 202 Operation |
GET /video/generations/:id | 查询 Operation |
POST /video/generations/:id/cancel | 请求取消,返回 Operation |
GET /video/generations/:id/content | 下载成功且未过期的项目视频文件 |
异步视频生成
视频复用已发布模型的 video_generation 能力、原有按次价格和受支持供应适配器。供应必须挂接到该公开模型,数据库类型为 video,唯一默认协议路由可用且未弃用;历史 endpoint_kind=null 可以沿已有视频适配执行,显式 chat、asr 等冲突类型仍拒绝。非默认历史路由不参与选择。渠道禁用、凭据、项目权限及余额检查保持有效,目录可用不代表供应商实时生成成功。
后台挂接已有单位价格时可使用 POST /admin/model-provider-costs/:id/attach 的 pricing_policy="keep_existing":视频按次、语音识别按秒均复用原有效价格,不要求补假的 token 价格,也不改原价。单位大小必须大于零,价格可以明确为零;缺价或无效汇率会拒绝,查询失败不会按默认汇率放行。
OAuth 统一 model-gateway:invoke 已包含视频创建、查询、取消和下载;旧 model-gateway:video 保留兼容。mobile:full 和 vibe-board:cloud 保持原范围。普通团队 API Key 仍由 Team owner 开启“允许异步视频生成”,新旧密钥默认关闭;系统 API Key 不能直接获得视频权限。创建与取消需要调用方用户对 project_id 有项目写入权限;查询和下载需要读取权限。任务还绑定创建时的凭据主体,同团队其他密钥不能读取。
创建请求必须带 Idempotency-Key,同一凭据下重试相同请求会返回原任务;相同键用于不同参数返回 409。请求在一个数据库事务内冻结当前报价、预扣账户额度并占用在途名额,然后入队;不在 HTTP 响应内等待供应商生成。余额、Key限额或预留失败时不创建任务,也不调用供应商。
curl -X POST /api/model-gateway/v1/video/generations \
-H "X-API-Key: YOUR_KEY" \
-H "Idempotency-Key: your-unique-job-id" \
-H "Content-Type: application/json" \
-d '{"model":"已上架的视频模型 key","project_id":"项目 UUID","prompt":"a red ball rolling","image_size":"960x960"}'可选字段:image_file_id(图生视频时必须指向同项目可读的 PNG/JPEG/WebP 文件,最多 10 MiB)、negative_prompt、seed。支持的 image_size 为 1280x720、720x1280、960x960。duration、aspect_ratio 等未完成计价与映射的字段会返回 400。
返回示例:
{
"name": "video/generations/任务 UUID",
"done": false,
"metadata": {
"model": "已上架的视频模型 key",
"project_id": "项目 UUID",
"status": "queued",
"created_at": "2026-09-23T00:00:00Z",
"updated_at": "2026-09-23T00:00:00Z"
}
}GET /video/generations/:id 的 done=true 表示成功、失败或取消。成功时 response.file_id 是项目 Storage 文件 ID,response.expires_at 是项目管理员配置的生成文件到期时间,response.content_url 是受本端点权限保护的下载路径。文件默认保留 7 天,项目管理员可改为 24 小时、7 天或 30 天。原始供应商 URL、提示词与内部计费信息不会出现在 Operation 中。成功文件也可在项目“存储”中查看。
供应商确认成功后,预扣转为已结算,不再扣第二笔;随后下载、保存并发布项目文件。成功文件必须有完整账证才能交付。已发布的 request 价格直接复用后台配置,明确的零价和订阅特权也走同一任务/账证合同,不伪造钱包扣款。
供应商返回 application/octet-stream 时,仅在完整字节通过 MP4 容器结构与视频轨校验后接收,并以 video/mp4 保存和交付。扩展名或 MIME 本身不能替代此校验;未知二进制、HTML、图片及缺失 MIME 继续拒绝。公网地址校验、DNS pin、重定向拒绝及下载大小/超时限制保持有效;这项兼容不扩大输入图片的格式范围。
提交前取消或供应商明确失败,可按原账证释放费用及 Key 使用量。已经提交、网络超时、轮询超时或取消请求都不能证明供应商没有消费:状态不明时保留预留和在途名额,不重复提交、不自动退款,由后台依据绑定的供应商证据对账。跨周期等无法安全原路退款的情况保持待对账,不宣称已退款。
供应商成功后的文件交付有独立 1 小时重试预算,耗尽后返回 delivery_failed 并释放在途名额,已经确认的模型消费仍保留。若后台随后恢复了同一个付费文件,Operation 状态保持 delivery_failed,但 /content 在验证文件已发布、账证一致且当前文件未过期后可返回 200。未交付返回 409,文件过期或删除返回 410;下载和重试不重新生成或扣费。以文件当前 expires_at 为准,旧任务缓存不会错误截断恢复后的保留期。
模型资格来自统一已发布模型库与实际可用渠道,不增加网关专用模型白名单或探针时效要求。任务在实际提交前再次检查冻结的同一供应;已停用且确定尚未提交时失败并释放预留。已经提交的任务继续按原供应商任务 ID 追踪结果。
Per-team 在途上限
每个团队默认最多 3 个在途视频任务。达到上限返回 429 video_inflight_limit_reached;同幂等键重试仍返回原任务。unknown、租约过期及旧版已提交但结果不明的任务仍占用名额;不能把本地超时直接转成已退款。
MODEL_GATEWAY_VIDEO_MAX_INFLIGHT_PER_TEAM 可设为 1–50 的整数,非法值告警并回退默认。数据库在同团队锁内同时检查名额、余额和 Key 限额,避免并发穿透。平台升级期间新创建暂时关闭,双节点 API 与 worker 更新后由管理员通过 视频预留管理接口 受控开启;历史任务、账本与审计不会被清除。
Realtime audio/video contract (not available yet)
The reserved public paths are POST /api/model-gateway/v1/realtime/sessions and WS /api/model-gateway/v1/realtime/ws. The existing /ws/realtime endpoint is for project change notifications and is unrelated to model conversations.
Session creation accepts a JSON body with model, input_modalities (audio and video) and output_modalities (audio and text). After exact model/channel verification and billing readiness, it will return a short-lived one-use ws_path. The WebSocket event contract uses input.audio.append (base64 PCM), input.audio.end, input.video.frame (base64 JPEG/PNG), input.text, and session.cancel. Responses use session.ready, input.committed, output.audio.delta, output.text.delta, response.done (carrying response_id and, when the provider reports it, per-modality usage), response.cancelled, and error.
Current status: session creation returns an error and the WebSocket does not upgrade. No realtime model is added to GET /models. New ordinary API Keys have the model_gateway_realtime_enabled permission off by default. OAuth needs the unified model-gateway:invoke scope (or the legacy narrow model-gateway:realtime scope). The hidden OAuth billing key never grants the task permission. The current billing service cannot charge Live text, audio and video separately, and no configured direct Gemini Live supply is available; the gateway does not require a second private probe permit. Enabling the key or OAuth scope alone does not make a session available.
Provider translation follows the capability of each actual channel. The Gemini Live WebSocket protocol accepts concurrent audio, video frames and text. The OpenAI GPT-Realtime model page lists video as unsupported, so an audio-only OpenAI session cannot qualify for this audio/video contract. The repository currently has no direct Google Live provider registration or verified realtime audio/video test. A Qwen-Omni Realtime translation prototype (16 kHz PCM audio plus JPEG frames over its native workspace WebSocket) exists behind the same closed gate; the public text input event has no verified Qwen equivalent in that prototype and is rejected.
图片生成与参考图编辑
GET /models 无 task 参数时仍返回原有 Chat、视觉输入和 ASR 目录。图片使用两个独立任务枚举:image-generation 对应文生图,image-edit 对应单张参考图编辑;未定义的 task 值返回 400。目录保留后台已发布图片模型,并按渠道图片适配器、渠道与价格声明可用性;不另要求网关付费实测许可。零价图片目前因附件交付需要扣费凭据而不可用。
当前图片渠道:OpenRouter(文生图与参考图编辑,按 token 或按张计价);SiliconFlow(按模型区分任务,只按张计价,例如 Qwen/Qwen-Image 为文生图、Qwen/Qwen-Image-Edit-2509 为参考图编辑,生成图片带渠道默认的「AI 生成」水印)。某个模型只支持其中一个任务时,另一个任务目录里显示 availability.reasons: ["unsupported_operation"],调用返回 404、错误码 unsupported_operation。按张计价时响应 usage 的 token 数为 0,费用按成功交付的张数结算;生成或下载失败不扣费。
普通 API Key 的“图片生成”和“参考图编辑”分别显式开启,旧 Key 默认关闭;OAuth 统一 model-gateway:invoke 已包含两个任务;旧 model-gateway:images-generate 与 model-gateway:images-edit 保留各自窄权限。请求必须明确指定 project_id,调用者需有该项目写权限,并受团队存储配额与余额限制。系统用途 Key 不可调用这两个任务。
调用上游前按「该渠道单张图片最大可能大小」预检存储:OpenRouter 为 20 MiB,SiliconFlow 为 5 MiB。项目套餐的单文件上限低于该值,或团队剩余空间放不下这么大的一张图时,直接返回 507 storage_quota_exceeded,不请求供应商、不扣费。免费套餐(单文件 5 MiB)可以使用 SiliconFlow 模型;OpenRouter 模型需要单文件上限 ≥ 20 MiB 的套餐。实际产物超过渠道上限时按生成失败处理,不扣费、不交付。
文生图 JSON 请求的最小合同:
{
"model": "<image-generation 目录模型 ID>",
"prompt": "画一只猫",
"project_id": "<项目 UUID>",
"n": 1,
"response_format": "b64_json"
}n 只接受 1,response_format 只接受 b64_json,两者可省略。参考图编辑使用 multipart/form-data,字段为 model、prompt、project_id、一张 image 文件,可选 response_format=b64_json。输入图片只接受内容与 MIME 一致的 PNG、JPEG 或 WebP,最大 10 MiB。编辑语义是用参考图引导生成;不承诺局部遮罩编辑或完整 OpenAI Edits 兼容。mask、input_fidelity、多图、尺寸、质量、背景、流式等当前无法无损转换的参数均返回 400,未知参数也会拒绝,不会静默忽略。
成功响应的 data[0].b64_json 为生成图片。响应头 X-Wainao-Storage-File-Id 是项目 Storage 文件 ID,X-Wainao-Storage-Expires-At 是发布时间起计算的到期时间,X-Wainao-Request-Id 用于排查;跨域调用可读取这些头。项目管理员可设置新生成文件保留 24 小时、7 天(默认)或 30 天,已有文件不随设置变化。文件先以私有 pending 状态保存,只有成功记账并原子发布后才返回图片;扣费或发布失败不交付图片。已扣费而发布暂时失败时,后台保留文件并持续重试和告警。
建议每次请求传唯一 Idempotency-Key 请求头。相同 Key 和相同请求可在临时计费/发布故障后重试,不再重复调用付费图片供应商;成功重放返回 X-Wainao-Idempotent-Replay: true。同 Key 不同请求返回 409。若没有提供该头,请求失败后无法通过原请求自动恢复,已生成但未扣费的私有文件会在该项目保留期再加 1 天后清理,期间计入团队存储配额。
| POST /audio/speech | OpenAI-compatible binary speech response; generated file saved to project Storage |
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": "qwen-audio-3-0-tts-flash",
"object": "model",
"created": 0,
"owned_by": "Qwen",
"capabilities": ["tts"],
"billing": {
"unit": "char",
"unit_size": 10000,
"price_per_unit_credits": 171.42
},
"recommendation": "good",
"tts": {
"voices": [
{ "id": "longanhuan_v3.6", "name": "龙安欢", "gender": "female", "lang": "zh" },
{ "id": "longanfengyue", "name": "龙安风悦", "gender": "female", "lang": "zh" },
{ "id": "longanxiaoxin", "name": "龙安小昕", "gender": "female", "lang": "zh" },
{ "id": "longjielidou_v3.6", "name": "龙杰力豆", "gender": "male", "lang": "zh" }
],
"default_voice": "longanhuan_v3.6"
}
},
{
"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 的历史目录集合。task=all 展示完整已发布模型库;以每项 availability / operations 判断配置就绪性,供应暂不可用的条目仍保留。
capabilities 说明:
text:支持文本生成,Token 计价。vision:支持图片输入(多模态)。视觉模型仍为 Token 计价,通常同时携带text;该标记表示模型可接受image_url内容(issue #1253 前视觉能力标记未透出,现已修复)。asr:支持音频转写,按秒计价。tts:支持语音合成(task=tts时列出),计价单位见billing.unit:char(每unit_size个字符)、utf8_byte(每unit_size个 UTF-8 字节)或token(按上游实际 token 结算)。
可选字段(只出现在普通数组形态的目录中;driver_config=effective、视频、图片专用列表不变):
recommendation:平台推荐评级,good(推荐)/fair(一般)/not_recommended(不推荐)。未评级的模型不输出该字段。tts:语音合成模型的公开音色{ voices: [{ id, name, gender, lang }], default_voice }。voice参数传id;省略时使用default_voice。
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。
统一 model-gateway:invoke 的 OAuth 调用默认自动选路,可调用仅配置 Responses 或 Anthropic Messages 的已发布文本模型。普通 API Key 和旧客户端 scopes 保留原有默认选路。
普通 API Key 或旧客户端需要自动选路时可在请求头添加 X-Wainao-Task-Routing: strict。头部存在但值不是 strict 时返回 400。显式启用后,纯文本请求只在运行时有效的渠道中选择,依次优先 Chat、Responses、Anthropic Messages;没有有效渠道时返回 no_available_text_route。工具或图片请求会跨协议筛选,实际调用的渠道必须处于有效状态,且同一变体分别通过 tool_use、multimodal_image 实测能力门禁。过期缓存不会替代 strict 模式的能力实测结果;能力未知或不足时不会发往该渠道。尚未完成能力实测的模型可能被 strict 门禁拒绝,接入前请先确认目标渠道的测试结果。
两种模式的公开请求、JSON/SSE 响应和现有计费模型 ID 均保持 Chat Completions 约定;strict 不改变身份和余额准入。
工具循环
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。
- 计费时长口径(2026-10-16 起):不采用上传方写在文件头里的时长数字。WAV(PCM / float,单一 data 块)由采样参数与音频数据真实字节数计算;MP3 逐帧累计并核对码率;m4a / webm / ogg 在「文件大小 ÷ 声明时长」得出的码率处于合理区间时采用声明值(mp4 须只有一条音轨且无空编辑等非平凡编辑列表,ogg 须为单一逻辑流)。参数异常、码率不合理或无法解析时,服务端用解码器实测时长并以此计费(不与声明值取小)。单文件限制、服务时长上限与扣费都用同一个值;合法文件与旧口径可能有毫秒级差异(编码器填充)。
- 服务端解码最多量到 600 秒,仍未结束按超长返回 413
audio_duration_too_long;解码失败、超时或无音轨返回 422audio_duration_unavailable;服务端解码器不可用返回 503audio_decode_unavailable、读取或解码排队已满返回 503audio_decode_busy(读取音频之前即按文件大小判断)。以上 503 均未调用供应商、不扣费,可稍后重试。恰好 600 秒不算超长。 - 文件大小上限为 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 固定和正确的连接清理。
ASR 服务从音频读取到供应商响应共用 120 秒期限(不包含 multipart 上传及路由鉴权)。超过期限返回 504/asr_timeout,仍使用独立预算保存消费证据和结算状态;账证 RPC 每次最多 2 秒、最多两次,写入证据及结算合计最多等待 8 秒。未知结果不自动尝试后备供应商,也不当作免费或自动退款;成功转写后的记账故障不会触发重新转写。客户端保留原 Idempotency-Key 和平台 requestId,查询已接受请求的回执。
Flash 的供应商 X-Api-Request-Id 等于本次已落库的消费事件 UUID。管理员可按平台 requestId/eventId 关联 provider_phase 日志,定位 DNS、请求、响应头或正文阶段;evidence.diagnostics 保留供应商 log ID、状态和耗时。日志与账证均不保存音频或转写原文。旧事件没有供应商关联 ID 时不能用本约定倒推。
上游地址或服务配置导致的 HTTP 拒绝按上游失败返回,不会误报为用户音频无效。仅明确的本地拒绝或 Flash 鉴权、限流、音频业务拒绝可继续后备;超时、传输失败、无效或空正文等未知结果停止后备并保留待对账。
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 | 无法确定音频时长,拒绝执行以避免错误计费 |
| 503 | audio_decode_unavailable | 需要服务端解码核定计费时长,但解码器不可用(含解码容量因异常子进程耗尽,需运维重启服务);未调用供应商、不扣费 |
| 503 | audio_decode_busy | 计费时长核定的读取预算、解码排队或临时文件容量已满;未调用供应商、不扣费,稍后重试 |
| 499 | request_cancelled | 客户端在完成前取消;取消已同步透传给上游 |
| 504 | asr_timeout | ASR 整段执行超时;结果未知时查询原请求回执,勿创建新请求重试 |
| 502 | model_upstream_error / asr_upstream_failed / invalid_tool_call / unexpected_eof / missing_completion / chat_completion_failed | 上游模型供应链失败,或上游丢失工具元信息、异常截断、无有效终态,不能投影为成功响应 |
普通插件 OAuth
申请并正常审核发布 model-gateway:invoke,用户确认后使用插件自身 delegated token 调用本页模型接口(目录、对话、转写、向量、重排、TTS、图片、视频及原生 Jev;具体以已实现的 operations 为准)。Host 只需 oauth:delegate;不使用 Host 专属 vibe-board:cloud,不按 official 标记或 Voice client ID 放行。
该权限会使用授权用户默认团队额度;用量记录 source 按实际操作区分(聊天为 plugin_model_gateway),oauthAppId 为调用插件的 OAuth 应用 row ID。已有刷新、撤销、scope 定义版本及 revision 资格校验继续生效。插件 manifest 的云能力平台批准不能替代 OAuth scope 与用户授权。
模型入口权益判定(2026-09-22)
模型网关聊天(JSON/SSE)、音频转写及 /services/passthrough/asr/transcriptions 在鉴权、权限及现有准入检查后,按实际计费团队、真实模型和当前有效订阅判断免扣。转写/Graphiti 别名先解析为记账使用的模型。命中后台免扣清单的有效订阅,即使用户余额为零或没有余额行,也可进入调用;实际消耗仍由现有计费链路写特权流水,不扣用户余额。
响应头 X-Wainao-Entitlement 返回 standard 或 subscription_privilege,表示请求入口当时的服务端权益判定;不是最终异步结算回执,执行期间订阅到期或配置变化时,以实际记账结果为准。客户端正常调用和展示,不据此自行跳过权限或决定扣款。该头通过 CORS 暴露,未进入模型准入的错误响应可能不带此头,旧响应 body 保持兼容。
清单为空、模型未命中、订阅失效/过期或特权读取失败时继续标准余额检查;有余额可按量调用,无余额返回原有 402 insufficient_quota。API Key 限额、scope、限流及 Driver 成本服务可用性检查保持生效。软额度只用于后台评估,不产生“额度用尽”硬停。无模型的运行/文档入口保持原余额门禁。
模型和参数校验现在先于余额判断:非法参数或无效别名优先返回对应请求错误,不保证先返回 402。权限错误仍先于业务处理。
图片请求在供应商执行前冻结完整价格与计费模式;携带 Idempotency-Key 时该报价持久保存。已存储结果重试沿用原报价,模型调价或下架不会改变已受理请求的金额。历史请求没有冻结报价时,只能复用身份、文件及用量均吻合的原流水;两者均缺失则返回待恢复错误,不按当前价格补扣。
OAuth 原生 Jev
原生通道只做代理和积分计费,不运行 Flow、不执行 Decision Schema 翻译。首期支持 TypeSafe 家族 Jev,不支持 NanoJev 和流式。
- App 获得统一
model-gateway:invoke能力并由用户重新同意,随后使用Authorization: Bearer <access_token>。旧 mobile/vibe-board scopes、普通和 system API Key 均不授予原生调用;OAuth 不使用X-API-Key。 - 查询
GET /api/model-gateway/v1/models?task=decision。返回的native[]含平台调用url、routeId、providerModel、method:POST、protocol:typesafe-systemone、stream:false和模型 token 价格。不公开供应商地址或凭据。 - 向目录的
POST /api/model-gateway/v1/native/:model/:routeId提交 Jev 原生 JSON,正文model必须等于providerModel;原生state、questions和扩展字段保持原样,不填平台 Decision Schema。公开计费 model 与 routeId 必须属于同一当前有效供应。
task=all 返回完整已发布模型库、原价和全部 capability,无参数保留旧集合。operations[] 给出实际调用接口和可用性;配置故障条目不隐藏。视频使用上述真实视频供应检查,Realtime 标 realtime_metering_unavailable,图片/TTS 附件无法取得扣费凭据时标 billing_delivery_unavailable。peer 模型保留签约身份与可信付款团队绑定状态。目录不保证余额或供应商实时健康。
请求必须是未压缩 application/json;请求/响应上限各 2 MiB,总传输超时 30 秒,stream:true 外呼前拒绝。平台替换供应商认证头,不转发用户 token、Cookie、任意客户端头,也不跟随供应商重定向。正常响应保留供应商状态、Content-Type 和解压后的原始 JSON 字节;已知平台凭据回显会脱敏。压缩/长度/cookie/location 等上游头不透传,不包装 __jev__、不重算概率。
原生与 Flow 共用同一模型 token 价格,新 token 冻结报价使用后台精确积分价格,历史无 priceBasis 的账证仍按原分价回放。按实际 usage.input_tokens/output_tokens 收取积分,无 Flow 固定运行费;付款团队沿用 OAuth 网关规则。外呼前记录费用意图,网络未知结果不自动重试或切换供应。缺用量、非法用量、断线或结算暂未确认进入待恢复账证,不补零、不临时改为按次价。保留 X-Wainao-Request-Id 供账证排查,此 scope 不额外开放账务查询 API;X-Wainao-Billing-State 为 settled 或 pending。浏览器可读取这两个响应头。
支持最长 200 字符的 Idempotency-Key。幂等键绑定原始正文摘要与 model/routeId;同请求重放返回 409 request_already_accepted 与原 requestId,变更绑定返回 409 idempotency_conflict,不会重跑供应商或缓存重放原生响应。