LUMITRANSLATE API

从一份清晰的协议开始。

萤火翻译 API 提供受授权的模型目录、完整性校验与 Android 版本分发。模型查询、配置查询和模型文件下载均需要授权;官网、文档、健康检查与安装包版本查询公开。

服务地址

https://lumitranslate.cocbc.com/api/v1
本站不提供在线翻译。App 中的远程翻译需配置你自己的 OpenAI 兼容服务;请勿将此分发 API 地址填入翻译供应商设置。

两种授权方式

官方 App:首次使用时在 Android Keystore 中创建独立 P-256 签名密钥,通过硬件证明校验官方签名、锁定启动与设备持钥证明。通过后自动获得一小时访问凭证;用户无需填写 API Key。无法通过证明的设备显示配对码,由管理员人工审核,审核前不能下载。

你的其他客户端:管理后台 创建独立 API Key,指定有效期及权限。完整密钥只展示一次。请求通过 Authorization: Bearer <API_KEY> 发送,不放入 URL、不嵌入公开 APK。

curl -fsS \
  -H "Authorization: Bearer $LUMI_API_KEY" https://lumitranslate.cocbc.com/api/v1/models

权限:config:read 查询配置、models:read 查询模型、models:download 获取下载链接。只授予查询权限时,downloadUrl 返回 null。撤销 API Key 或停用设备,会使已有凭证及下载链接失效;正在传输的 HTTP 响应会继续到连接结束。

接口目录

方法与路径用途参数
GET /health服务存活状态
GET /config客户端配置 · config:read
GET /models分页模型目录 · models:readpage:默认 1;pageSize:默认 20,最大 100
GET /models/{model_id}模型元数据 · models:readq4_k_m / q6_k / q8_0
GET /releases/latest最新应用版本platform=android;channel=stable 或 preview,默认 stable

App 设备协议

所有路径均相对于 /api/v1。JSON 请求与响应;签名为 SHA256withECDSA 的 DER 编码后标准 Base64;nonce 为 32 字节随机数的标准 Base64。证书列表按叶证书到根证书顺序,每项为 DER 的标准 Base64。

  1. POST /device/challenges,新设备发送 {},返回 data.id、nonce、expiresAt。挑战有效期 180 秒、仅能消费一次。
  2. 用 nonce 解码后的字节作为 Android Keystore 的 attestationChallenge 创建 P-256 密钥;对 UTF-8 文本 LumiTranslate enroll id nonce 签名(其中 id/nonce 替换为响应原值,换行为 LF)。
  3. POST /device/enrollments 发送 challengeId、name、certificates、signature。ACTIVE 返回 deviceId、accessToken、expiresAt;PENDING 返回 deviceId、pairingCode、message。状态非 ACTIVE 时没有访问凭证。
  4. 刷新令牌时,先以 {"deviceId":"…"} 请求新挑战,再签名 LumiTranslate token id nonce;向 POST /device/tokens 提交 deviceId、challengeId、signature。
  5. accessToken 作为 Bearer 使用。expiresAt 为 UTC Unix 秒;客户端提前 60 秒刷新。不要持久化短期令牌,只保存 deviceId 和 Keystore 密钥。设备删除数据或卸载重装后需重新注册。

此协议不以包名、请求头或 APK 内的固定字符串作为身份凭证。硬件证明信任根与撤销状态按 Android 官方机制验证;不支持的设备进入人工审核。

安全下载与检查更新

  1. 获取 /models 或单个模型详情。仅当 available=true 且 downloadUrl 非空才开始下载。
  2. 比较本机记录与服务器返回的 sha256。哈希变化表示模型文件已更新;revision 表示上游仓库版本。
  3. downloadUrl 下载到以哈希区分的临时文件。URL 固定在本站并包含版本及短期 ticket,不指向第三方。API Key 链接最多 2 小时有效;设备链接不会超过访问凭证有效期。不要记录或分享 ticket。过期后重新请求元数据,继续使用原临时文件续传。
  4. 断点续传使用 Range: bytes=N-。收到 206 时校验 Content-Range 的起点与总长度;收到 200 时从头写入,不能追加。
  5. 核验 sizeBytes 和整个文件的 sha256。成功后原子替换本机文件并保存哈希、版本记录;失败时保留旧模型。
# 获取元数据
curl -fsS -H "Authorization: Bearer $LUMI_API_KEY" https://lumitranslate.cocbc.com/api/v1/models/q4_k_m

# 将 downloadUrl 填入 MODEL_URL,断点续传
curl --fail --location --continue-at - "$MODEL_URL" -o model.gguf.part

# 核对输出与 API 的 sha256,再将文件改名为 model.gguf
sha256sum model.gguf.part

二进制下载需要有效 ticket,支持 GET、HEAD、200、206、304 和 416。无票据、票据篡改、跨文件使用或撤销后返回 401/403。它们使用标准 HTTP 文件响应,不包装 JSON。文件路径不可变,旧版文件在客户端迁移期间保留。

关键字段含义
id稳定的量化变体标识,用于查询和选择
revision / sha256上游 commit / 文件 SHA-256
sizeBytes / fileName精确字节数 / 建议文件名
available / downloadUrl是否可下载;不可用或无下载权限时 URL 为 null
minRamMb / architectures建议内存与当前客户端支持的架构
license / licenseUrl / sourceUrl许可证、完整许可证文本与上游来源

应用版本

当前预览渠道使用 /releases/latest?channel=preview。比较 versionCode 判断是否有新版本,安装前检查 APK SHA-256 与 signingCertificateSha256。应用更新是用户发起的操作。

预览版本用于体验与测试;没有正式版本时,stable 渠道返回 404 RELEASE_NOT_FOUND。不会用测试版本冒充正式版。

统一响应、缓存与限流

{
  "error": {
    "code": "MODEL_NOT_FOUND",
    "message": "模型不存在。"
  },
  "requestId": "用于定位请求的唯一标识"
}

成功响应包含 datarequestId;列表额外包含 pagination。所有 JSON API 返回 X-Request-ID。错误码使用稳定的英文常量,message 用于用户提示。

缺少或失效凭证返回 401,权限不足返回 403,参数无效返回 422,资源不存在返回 404,不支持的方法返回 405,限流返回 429,内部错误返回 500。API 每个来源 IP 每分钟最多 120 次请求,429 附带 Retry-After 秒数;后台登录有额外限制。

目录响应提供 ETag。下次请求带上 If-None-Match,内容没有变化时返回 304。必须保存上次完整响应,304 没有正文。requestId 不参与内容版本判断。下载 ticket 定期变化也会改变 ETag;它不是模型更新标识,模型更新应比较 sha256。响应为 private,不能由共享缓存跨用户复用。

在线试用

选择接口并发送请求,这里将显示实时响应。

扩展约定

v1 内以增加可选字段和能力开关扩展功能。客户端应忽略未知字段,不能依赖 JSON 字段顺序。删除字段、改变字段类型或语义需要新主版本,并提前公告弃用期。

账户、在线翻译、任务队列和术语表是后续扩展方向,当前未启用。未来可通过独立受鉴权的资源 /translations/jobs/glossaries 扩展;启用前须同时发布对应 OpenAPI、权限作用域和能力开关。

管理接口采用独立的 /api/admin/v1 命名空间,通过后台会话鉴权。管理面板位于 /wzmanaged