VisibleBase
参考

HTTP API

/v1/* 与 /api/admin/* 路由的鉴权边界、请求方式和返回形态。

如果你已经在用 SDK,通常不需要手写 HTTP 请求。
这页更适合:

  • 你在接别的运行时
  • 你在调试 Base 的真实请求
  • 你要确认某个路由到底返回什么

路由分组

产品侧路由

这些路由给 UserClient 或终端产品使用,统一要求 user_token

路由方法用途
/v1/modelsGET返回公开模型目录
/v1/servicesGET返回已注册的 service 列表
/v1/invokePOST通用 service 调用入口
/v1/textPOST文本 service
/v1/streamPOST流式文本 service
/v1/imagePOST图像 service
/v1/videoPOST视频 service
/v1/ttsPOSTTTS service
/v1/asrPOSTASR service

管理端路由

这些路由给 AdminClient 或可信环境使用,统一要求 admin_secret_key

路由方法用途
/api/admin/productsGET返回 product 列表
/api/admin/products/createPOST创建 product
/api/admin/products/pausePOST暂停 product
/api/admin/products/activatePOST启用 product
/api/admin/products/removePOST删除 product
/api/admin/tokens/applyPOST签发 user_token
/api/admin/envGET查看 Runtime env
/api/admin/env/upsertPOST写入 Runtime env
/api/admin/env/removePOST删除某个 env 变量
/api/admin/env/importPOST批量导入 .env 文本

产品侧请求格式

认证头

产品侧请求统一使用:

Authorization: Bearer <user_token>
Content-Type: application/json

GET /v1/models

[
  {
    "id": "gpt-5.4",
    "name": "GPT-5.4",
    "provider": "openai",
    "description": "Primary text model",
    "primary": true
  }
]

GET /v1/services

{
  "items": ["text", "stream", "image"]
}

POST /v1/text

请求:

{
  "product_id": "prod_xxx",
  "model": "gpt-5.4",
  "prompt": "写一段欢迎语"
}

返回:

{
  "id": "msg_xxx",
  "role": "assistant",
  "parts": [
    {
      "type": "text",
      "text": "欢迎使用 VisibleBase",
      "state": "done"
    }
  ]
}

具体返回体由你的 service handler 决定。用 UserClient.text() 时,建议 handler 返回 AI SDK UIMessage

POST /v1/invoke

请求:

{
  "service": "rewrite",
  "product_id": "prod_xxx",
  "model": "gpt-5.4",
  "prompt": "把这段话改得更专业"
}

这和 POST /v1/text 的区别只是:service 名称由请求体显式提供。

POST /v1/stream

请求体和 text 类似:

{
  "product_id": "prod_xxx",
  "model": "gpt-5.4",
  "prompt": "流式输出一段文案"
}

但返回值不是普通 JSON,而是流式响应体。用 UserClient.stream() 时,Base 侧应该返回 AI SDK UIMessage stream response,client 会把它解析成 UIMessageChunk 流。

管理端请求格式

认证头

管理端请求统一使用:

Authorization: Bearer <admin_secret_key>
Content-Type: application/json

POST /api/admin/products/create

请求:

{
  "name": "Chrome Extension"
}

返回:

{
  "product_id": "prod_xxx",
  "name": "Chrome Extension",
  "status": "active",
  "created_at": "2026-04-23T00:00:00.000Z",
  "updated_at": "2026-04-23T00:00:00.000Z"
}

POST /api/admin/tokens/apply

请求:

{
  "product_id": "prod_xxx",
  "user_id": "user_123",
  "metadata": {
    "plan": "pro"
  },
  "ttl": "7d"
}

返回:

{
  "user_token": "ub_xxx",
  "product_id": "prod_xxx",
  "user_id": "user_123",
  "expires_at": "2026-04-30T00:00:00.000Z"
}

POST /api/admin/env/upsert

请求:

{
  "key": "OPENAI_API_KEY",
  "value": "sk-xxx"
}

POST /api/admin/env/remove

请求:

{
  "key": "OPENAI_API_KEY"
}

POST /api/admin/env/import

请求:

{
  "raw": "OPENAI_API_KEY=sk-xxx\nOPENAI_BASE_URL=https://api.openai.com/v1"
}

常见状态码

Base 自己产生的错误统一返回 JSON:

{
  "error": "Invalid user token"
}

如果 service handler 直接返回 Response,Base 会原样透传这个 Response。如果 handler 抛错,Base 会先执行当前 service 和全局的 onError hook,然后把错误转成 HTTP 响应:带 statusCode 的错误使用该状态码,其他错误返回 500

状态码什么时候返回
200请求成功,或 service handler 正常返回 JSON。
400/v1/invoke 请求体缺少 service
401产品侧请求缺少 user_token;token 过期、签名无效、audience 无效、payload 无效;token 对应的 product 已不存在;管理端请求缺少或传错 admin_secret_key
403请求体里的 product_id 和 token 内的 product 不一致;token 对应 product 已暂停;给已暂停 product 签发 token。
404HTTP 路由不存在;调用了未注册的 service;给不存在的 product 签发 token。
422service 最终没有 query.model;请求的 model 不存在或不是 active;当前 service 的 match() 没有任何 handler 命中。
500Base 必要配置缺失,例如 VISIBLEBASE_TOKEN_SIGNING_KEYVISIBLEBASE_ADMIN_SECRET_KEY;service 已注册但没有 handler;handler、provider、数据库或 env 逻辑抛出了未显式指定 statusCode 的错误。

在自定义 handler 里,如果你想控制 HTTP 状态码,可以抛出带 statusCode 的错误:

import type { ErrorWithStatus } from "@visiblebase/base";

const error = new Error("quota exceeded") as ErrorWithStatus;
error.statusCode = 429;
throw error;

目录