VIVA API · RUNTIME DOCUMENTATION
将安全的语音输入与文本处理接入你的应用
此页面描述当前服务已实现的运行时接口。客户端只使用 Viva 签发的短期令牌;供应商密钥、邮件密码与管理员密码永远不返回客户端。完整机器契约见 /openapi.yaml,实时语音消息契约见 api/asyncapi.yaml。
- 本地 API 地址
- http://127.0.0.1:8080
- 本地文档地址
- http://127.0.0.1:8080/docs/
- 内容类型
- application/json; charset=utf-8
认证与安全模型
Viva 同时支持邮箱验证码登录,以及唯一账号名称或已验证邮箱加密码登录;两种方式对应同一个 user_id、积分和历史记录。密码只在 HTTPS/TLS 加密通道中传输,并由服务端使用 Argon2id 校验。客户端不需要接收、保存或管理 Viva 自定义的非对称公钥:TLS 握手会通过服务器证书自动完成服务端身份验证与密钥协商。
业务请求使用短期 Bearer Access Token;Refresh Token 强制轮换并检测重放。默认部署 VIVA_DPOP_REQUIRED=false,不把本机设备密钥作为登录成功的必要条件。客户端信息与来源 IP
/v1/client/bootstrap、OTP 请求与验证、密码登录和密码设置都必须携带稳定安装 ID。JSON body 使用 device_id(bootstrap 使用 install_id),也可通过 X-Viva-Device-ID 提供回退值。ID 长度为 8–128,只能包含字母、数字、- _ . :;建议生成随机 UUID 并持久化到应用本地存储。浏览器会话必须使用 UUID。
客户端还可上传产品名称、平台、版本、系统版本 / 构建号、CPU 架构、硬件型号、语言和时区。来源 IP 只能由服务端从 TCP 连接和可信代理链解析,客户端不得在 JSON 中自行声明 IP;可信代理请求缺少有效转发来源时同样拒绝认证。请勿上传序列号、MAC 地址、电脑名或操作系统用户名。
登录防刷与临时封禁
OTP 和密码认证同时按来源 IP、账号或邮箱、稳定安装 ID、组合维度与全局预算限流。缺少有效来源 IP 或安装 ID 时返回 400 AUTH_CONTEXT_REQUIRED;短时间内连续提交错误验证码或错误密码,会对命中的维度临时封禁并返回 429 AUTH_RATE_LIMITED 和 Retry-After。客户端必须在倒计时结束前禁用自动重试,成功登录也不能用来绕过已经生效的共享防刷预算。
积分与用量
注册用户获得试用积分。ASR / LLM 请求会记录用量、供应商直接成本和扣减积分;查询余额后再发起消耗型请求。用户仅能读取自己的账本与会话,管理员读取的数据会按安全策略脱敏。
/v1/auth/otp/request请求邮箱验证码
验证码只通过已配置的 SMTP 服务发送,响应中绝不返回验证码。成功响应含 challenge_id 与 expires_at;下一步验证必须使用同一个 challenge。purpose 支持 login_or_register(默认)、register、login 与 recent_auth。
curl "$VIVA_BASE_URL/v1/auth/otp/request" \
-H "Content-Type: application/json" \
-H "X-Viva-Device-ID: 550e8400-e29b-41d4-a716-446655440000" \
-d '{"email":"user@example.com","purpose":"login","device_id":"550e8400-e29b-41d4-a716-446655440000"}'可能返回:400 AUTH_CONTEXT_REQUIRED、429 OTP_RATE_LIMITED、503 EMAIL_PROVIDER_UNAVAILABLE、503 OTP_DELIVERY_BUSY 或 502 OTP_DELIVERY_FAILED。
/v1/auth/otp/verify验证 OTP,登录或创建账户
{
"email": "user@example.com",
"code": "123456",
"challenge_id": "<来自 request 的 UUID>",
"device_id": "550e8400-e29b-41d4-a716-446655440000"
}原生客户端成功响应包含 created、user、credits、access_token、refresh_token 和 expires_at。网页传 web_session: true 时不返回 Refresh Token,长期凭证只写入 Secure、HttpOnly、SameSite Cookie。默认部署不要求 device_key 或 DPoP 请求头。
/v1/auth/password/login账号或邮箱密码登录
{
"account": "viva_user 或 user@example.com",
"password": "<account-password>",
"device_id": "550e8400-e29b-41d4-a716-446655440000"
}account 可填写注册时设置的唯一账号名称或已验证邮箱;旧客户端仍可提交 email 兼容字段。未知账号、未设置密码和密码错误都返回 401 PASSWORD_AUTH_FAILED 与同一文案,客户端不应根据错误猜测账号是否存在。成功响应与 OTP 登录相同。
/v1/auth/password/setup注册、设置或重设密码
先调用 OTP request:新用户注册或设置密码使用 purpose: register,忘记密码使用 purpose: recent_auth。密码需为 8–128 个字符,不能包含邮箱 @ 前的账号部分;允许密码管理器生成的空格和符号。
{
"email": "user@example.com",
"password": "<new-password>",
"code": "123456",
"challenge_id": "<来自 request 的 UUID>",
"device_id": "550e8400-e29b-41d4-a716-446655440000"
}验证码消费、账号创建或更新、Argon2id 密码凭据写入在同一状态事务中完成。密码原文不记录、不持久化、不返回。
/v1/auth/refresh轮换 Refresh Token
{ "refresh_token": "<refresh_token>" }旧 Refresh Token 只能使用一次;重放会使该设备的 Token family 失效。已登录用户还可调用 POST /v1/auth/logout 注销当前设备,或 POST /v1/auth/logout-all 注销所有设备。
/v1/auth/session/restore安全恢复网页登录
OTP、密码登录或密码设置传 web_session: true;可选 remember_me: true。服务端仅返回短期 Access Token,并写入 Secure、HttpOnly、SameSite Cookie。恢复请求必须同源并提交不可猜测的 Cookie;设备 ID 只用于风控、审计和设备管理,不会因浏览器存储变化阻止登录。部署显式开启 DPoP 后才额外要求匹配 proof。
临时会话 12 小时空闲/24 小时绝对过期;保持登录为 30 天空闲/90 天绝对过期。通过 GET /v1/me/sessions 查看设备,DELETE /v1/me/sessions/{session_id} 下线单台设备,POST /v1/me/sessions/revoke-others 下线其他设备。
/v1/me账户、设备、积分与使用情况
curl "$VIVA_BASE_URL/v1/credits/balance" \
-H "Authorization: Bearer $ACCESS_TOKEN"已登录用户可使用 GET /v1/me、GET /v1/me/sessions、GET /v1/usage/summary、GET /v1/credits/balance 和 GET /v1/credits/transactions。默认使用 Authorization: Bearer <access_token>;只有部署显式启用 DPoP 时才改用 DPoP 授权头与逐请求 proof。
/v1/asr/tickets申请 ASR ticket,再连接语音流
先申请 60 秒有效、单次使用的 ticket,服务会预留积分;再用 wss://…/v1/asr/stream?ticket=<ticket> 升级 WebSocket。不要把 Provider 凭证放在客户端。
curl -X POST "$VIVA_BASE_URL/v1/asr/tickets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"protocol_capabilities":["voice_final_v1"]}'完成后可通过 GET /v1/asr/sessions 查询当前用户的会话与结算状态。实时消息字段以 api/asyncapi.yaml 为准。
/v1/text/polish大模型文本润色
非流式接口返回润色结果、用量与扣费。POST /v1/text/polish/stream 使用 SSE 返回 meta、delta、final、usage、done 或 error 事件。
curl "$VIVA_BASE_URL/v1/text/polish" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"text":"嗯,这个这个方案可以上线","mode":"both"}'客户端完成处理后,调用 POST /v1/llm-requests/{request_id}/client-outcome 回报是否已经交付给用户;这能区分“上游成功”与“用户端超时 / 未显示”。
/v1/admin/security/sessions管理员安全管理
管理员控制台使用受保护的 HttpOnly 会话 Cookie。安全管理接口支持 cursor、limit(1–100,默认 50)、query、created_from 与 created_to;游标绑定筛选条件,变更筛选后必须从第一页重新请求。
| 接口 | 用途 |
|---|---|
GET /v1/admin/security/sessions | 分页读取管理员会话,可按 status、device_id 筛选。 |
POST /v1/admin/security/devices/{device_id}/revoke | 强制设备下线;需要 confirmation: "FORCE_OFFLINE" 和管理员重新验证。 |
GET /v1/admin/security/login-events | 分页读取管理员登录事件,可按 outcome、reason、device_id 筛选;仅保存 IP 网段提示与 HMAC 指纹。 |
GET / PUT /v1/admin/security/ip-allowlist | 查询或更新管理员 IP 白名单;清空白名单需明确确认,更新不能把当前登录 IP 锁在外面。 |
错误、限流与排查
| HTTP 状态 | 常见代码 | 客户端处理 |
|---|---|---|
| 400 | INVALID_REQUEST / AUTH_CONTEXT_REQUIRED / PASSWORD_POLICY_INVALID | 检查 body、稳定安装 ID、客户端版本、challenge_id、密码规则与参数格式;来源 IP 由服务端或可信代理修复。 |
| 401 | UNAUTHORIZED / OTP_INVALID / PASSWORD_AUTH_FAILED | 重新认证;密码失败不代表账号一定存在。 |
| 402 | CREDITS_EXHAUSTED | 查询余额并补充积分。 |
| 429 | AUTH_RATE_LIMITED / OTP_RATE_LIMITED | 严格按 Retry-After 等待,在到期前不要自动重试。 |
| 502 / 503 / 504 | OTP_DELIVERY_FAILED / PASSWORD_AUTH_BUSY / LLM 上游错误 | 保留 X-Request-ID,使用指数退避后再试。 |
所有响应都携带 X-Request-ID。提交问题时提供该值即可;不要发送 Access Token、Refresh Token、OTP、账号密码、管理员密码或 Provider API Key。