Skip to content

公开 API

公开访问的 API 路由,无需认证。返回公开配置数据。

基础路径

/public

认证方式

无需认证。所有端点均公开访问,使用 publicCors 中间件支持跨域请求。


端点列表

GET /public/client-config

获取移动端远程配置。接口无需认证,后端只读取 site_settings 中的客户端白名单分组:

前端接入方法、模型清单下载规则和 Tab 功能开关约定见 移动端远程配置接入

endpoints.apiBaseUrl/oauthBaseUrl/modelGatewayBaseUrl 的 origin 部分按发起请求的域名(Host/X-Forwarded-Host)动态推导,不是 site_settings 里存的固定值;modelManifestUrl/modelBaseUrl/modelDownloadBaseUrl 强制 https://。详见 移动端远程配置接入

  • client.endpoints
  • client.models
  • client.thresholds
  • client.flags
  • client.transcribe
  • client.dyj1
  • client.firmware
  • client.vibeBoard

systemsecretsnotification.novu_admin 等后端内部配置不会通过该接口返回。

请求参数

参数位置类型必填默认值说明
groupsQuerystring全部分组逗号分隔分组,如 endpoints,models;未知分组会被忽略
platformQuerystring预留给 App 端平台灰度,当前不改变返回内容
appVersionQuerystring预留给版本灰度,当前不改变返回内容

缓存

  • 响应包含 ETag,客户端可在后续请求携带 If-None-Match
  • 配置未变化时返回 304 Not Modified

响应格式

json
{
  "version": 1782349200000,
  "updatedAt": "2026-06-25T01:00:00.000Z",
  "groups": {
    "endpoints": {
      "apiBaseUrl": "https://block2-api.wainao.chat",
      "modelGatewayBaseUrl": "/api/model-gateway/v1",
      "modelManifestUrl": "https://example.com/mobile/models/manifest.json",
      "modelBaseUrl": "https://example.com/mobile/models"
    },
    "flags": {
      "enableLocalAsr": true,
      "enableModelDownload": true,
      "enableTabAiFriends": true
    }
  }
}

响应字段说明

字段类型说明
versionnumber当前响应视图中最新配置行的 updated_at 毫秒时间戳;无配置时为 0
updatedAtstring | null当前响应视图中最新配置行更新时间;无配置时为 null
groupsobject命中的客户端配置分组,key 去掉 client. 前缀

错误码

HTTP 状态码说明
304ETag 命中,配置未变化
500获取客户端远程配置失败

GET /public/firmware/:model/:module/:fileName

既有固件对象的长期稳定入口。module 只允许 main|wifi;服务端按白名单参数重建对象路径,每次请求生成短期 HTTPS signed URL 并返回 302。响应带 Cache-Control: no-store

GET /public/vibe-board/firmware/:channel/:sha256/:fileName

AI-Board-01 content-addressed 固件入口。channel 只允许 stable|betasha256 必须为 64 位小写 hex,文件扩展名只允许 .bin。请求方不能指定 bucket 或 storagePath。

GET /public/vibe-board/app/:platform/:sha256/:fileName

Vibe Board 桌面 App content-addressed 稳定入口。平台仅允许 macos-arm64|macos-x86_64|windows-x86_64,扩展名必须与平台匹配,服务端据此重建私有对象路径并核对已登记资产。首次 GET/Range 会把私有 storage 对象流式写入内容寻址的有界本地缓存,完成 size/SHA-256 校验与原子发布后,再由 BunFile 直接交付;响应不返回或暴露 storage signed URL:

  • 完整 GET 返回 200、安装包 body、Content-TypeContent-LengthContent-Disposition: attachmentAccept-Ranges: bytes
  • HEAD 返回同一资产的元数据响应头且无 body。
  • 单段 Range: bytes=... 返回 206 与正确的 Content-Range;非法、多段或不可满足 Range 返回 416
  • 完整 GET 与 206 均返回正确 Content-Length;HTTP/1.1 不使用 chunked 代替已知长度。
  • 本地缓存按 SHA singleflight,默认总上限 512 MiB;单个客户端断开不会取消仍有其他等待者的共享回源。
  • 后端启动会同时校验当前上传上限与数据库既有 App asset 最大尺寸;缓存降容低于任一值会 fail-fast,避免既有下载在启动后永久 502
  • 缓存回源正文使用滚动式 30 秒停滞超时;每收到一个 chunk 会重新计时,超时会中止上游并清理 part、singleflight 与容量预留,返回 504
  • URL 含不可变 SHA-256,成功响应使用 Cache-Control: public, max-age=31536000, immutable
  • 参数非法返回 400,合法形状但未登记或上游对象不存在返回 404,storage 暂时不可用返回 502/504

固件与 App 下载入口均无需登录。既有 firmware 路由继续使用短期 signed URL 302;App 路由不再要求客户端跟随 storage 重定向。


GET /public/devices/bluetooth-filters

获取蓝牙设备名前缀过滤规则。从 hw_product_models 表读取状态为 active 的产品型号的蓝牙前缀配置。

一个型号可携带多个前缀(2026-06-13 一代机归并后),每个前缀产出一条 filter,前端应对同一 productModelId 的多条 filter 作去重处理。

请求参数

无。

响应格式

json
{
  "success": true,
  "filters": [
    {
      "namePrefix": "DYJV1_",
      "productModelId": "uuid",
      "modelName": "点一机·一代",
      "requiresInventoryCheck": true,
      "generation": "gen1",
      "role": "full"
    },
    {
      "namePrefix": "DYJ-",
      "productModelId": "uuid",
      "modelName": "点一机·一代",
      "requiresInventoryCheck": true,
      "generation": "gen1",
      "role": "upgrade_only"
    }
  ]
}

响应字段说明

字段类型说明
filters[].namePrefixstring蓝牙设备名前缀
filters[].productModelIdstring产品型号 ID
filters[].modelNamestring产品型号名称
filters[].requiresInventoryCheckboolean是否需要库存校验
filters[].generationstring | null产品代次,gen1 / gen2 / null(第三方型号)
filters[].rolestring前缀角色:full(完整功能)/ upgrade_only(仅固件升级识别,不用于常规绑定)

错误码

HTTP 状态码说明
500获取蓝牙过滤规则失败

GET /public/payment/prices

获取产品价格列表。

请求参数

参数位置类型必填默认值说明
currencyQuerystringCNY货币类型

响应格式

json
{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "productType": "subscription",
      "productCode": "pro",
      "name": "专业版",
      "description": "描述文本",
      "amount": 9900,
      "currency": "CNY",
      "credits": 100000,
      "billingPeriod": "monthly",
      "isFeatured": true
    }
  ]
}

响应字段说明

字段类型说明
data[].idstring价格 ID
data[].productTypestring产品类型
data[].productCodestring产品代码
data[].namestring产品名称
data[].descriptionstring产品描述
data[].amountnumber价格金额(分)
data[].currencystring货币类型
data[].creditsnumber包含积分数
data[].billingPeriodstring计费周期
data[].isFeaturedboolean是否推荐

错误码

HTTP 状态码说明
500获取价格列表失败

GET /public/payment/methods

获取可用支付方式。

请求参数

参数位置类型必填默认值说明
currencyQuerystring按货币类型筛选支付方式

响应格式

json
{
  "success": true,
  "data": [
    {
      "id": "wechat_pay",
      "name": "微信支付",
      "currencies": ["CNY"]
    }
  ]
}

错误码

无特殊错误码。


GET /public/wechat/jssdk-signature

微信公众号 JS-SDK 签名(按 OAuth App 隔离,issue #854)。供第三方 landing 页在微信浏览器内调 wx.config()。靠 client_id 识别接入应用,用该应用配置的公众号凭据签名;主安全边界 = 待签名 URL host 必须在该应用绑定的 JS 安全域名内。仓库内功能说明见 docs/features/wechat-jssdk/README.md

请求参数

参数位置类型必填说明
client_idQuerystring接入应用的 OAuth App client_id
urlQuerystring当前页面 URL(encodeURIComponent;服务端取 # 之前签名)
apisQuerystring逗号分隔,白名单当前为 openAddress + chooseWXPay(默认 openAddress

响应格式

json
{
  "success": true,
  "data": {
    "appId": "wx公众号AppID",
    "timestamp": 1710000000,
    "nonceStr": "...",
    "signature": "...",
    "jsApiList": ["openAddress"]
  }
}

错误码(信封 { success:false, error:{ code, message } }

codeHTTP场景
NOT_CONFIGURED503未配置 / 配置禁用 / 应用不存在(前端走手填兜底)
INVALID_REQUEST400参数缺失 / 非白名单 api / url 非 https / 域名不在白名单 / Origin 不一致
RATE_LIMITED429超过 IP 限流
INTERNAL_ERROR500微信侧异常(不透传原始错误)

源码

  • 路由文件apps/backend/src/routes/public.ts
  • 微信 JS-SDK 签名apps/backend/src/routes/public/wechat-jssdk.tsapps/backend/src/services/wechat/jssdk*.ts

GET /public/features/graphiti

无需认证,返回 Graphiti 功能是否开放及客户端展示所需的公开状态;不暴露模型、Provider 或计费凭据。

AI Workflow Editor