BasicRouter 文档
快速入门
BasicRouter 为生产团队提供统一的稳定 API,用于模型访问、路由、兜底、用量跟踪和基于积分的计费。LLM token 供应来自可信的企业云原厂账号,网关内置隐私保护、高稳定性和请求可追溯能力。
https://api.basicrouter.ai/apihttps://api.basicrouter.ai/api/v1https://api.basicrouter.ai/api/v1Authorization: Bearer <key>创建 API 密钥
在控制台中创建 BasicRouter API 密钥。请将密钥保存在服务器端,切勿在浏览器或移动客户端代码中暴露。
推荐的密钥策略:
| 密钥类型 | 推荐用途 |
|---|---|
| 开发密钥 | 本地开发、预发布、测试和原型。 |
| 生产密钥 | 仅用于后端生产负载。 |
| 集成密钥 | 专用于 Cursor、Claude Code、Codex、Hermes 或 OpenClaw 等工具的密钥。 |
| 客户 / 租户密钥 | 面向企业客户、租户流量或业务单元的可选密钥隔离。 |
当团队访问权限变更时请轮换密钥。不再使用的密钥请及时吊销。
将 SDK 指向 BasicRouter
大多数 OpenAI 兼容客户端只需更换 base URL 和 API 密钥即可。
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.BASICROUTER_API_KEY,
baseURL: "https://api.basicrouter.ai/api/v1"
});
发送聊天补全请求
curl --request POST \
--url https://api.basicrouter.ai/api/v1/chat/completions \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "claude-sonnet-5",
"messages": [
{ "role": "user", "content": "Explain BasicRouter in one sentence." }
]
}'
查询用量和余额
curl --request GET \
--url https://api.basicrouter.ai/api/v1/billing/balance \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
模型发现
使用模型页面或模型 API 查看可用的文本模型。模型元数据包括厂商、服务提供商、模态、上下文长度、支持的 API 系列、支持的能力、可用性、账户级限制和积分定价。
端点: GET /v1/models
用途: 列出当前账户可用的模型。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/models \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
能力矩阵
| 能力 | 说明 | 常用场景 |
|---|---|---|
streaming | 支持服务器推送事件流。 | 聊天应用、编程智能体、实时交互体验。 |
tool_calling | 支持工具或函数调用。 | 智能体、工作流自动化、编程助手。 |
structured_outputs | 支持 schema 约束或 JSON 输出。 | 数据提取、工作流自动化、企业应用。 |
json_mode | 可返回 JSON 格式输出。 | 轻量级结构化响应。 |
vision | 接受图像输入。 | 多模态聊天、UI 分析、文档截图。 |
prompt_caching | 支持缓存输入或上下文复用。 | 长上下文智能体、重复的系统提示词。 |
reasoning | 支持可用时的显式推理控制。 | 复杂规划、编程、分析工作流。 |
logprobs | 支持 token 概率输出。 | 评估、排序、高级 NLP 工作流。 |
API 系列兼容性矩阵
| API 系列 | 文本 | 视觉输入 | 工具调用 | 结构化输出 | 流式 | 说明 |
|---|---|---|---|---|---|---|
| OpenAI Chat Completions | 是 | 取决于模型 | 取决于模型 | 取决于模型 | 是 | OpenAI 兼容智能体和 SDK 的最佳默认选择。 |
| OpenAI Responses | 是 | 取决于模型 | 取决于模型 | 取决于模型 | 是 | 推荐用于较新的 OpenAI 风格智能体工作流。 |
| Anthropic Messages | 是 | 取决于模型 | 取决于模型 | 取决于模型 | 是 | 最适合 Claude 兼容客户端和 Claude Code。 |
| BasicRouter image generation | 否 | 取决于模型 | 否 | 否 | 否 | 使用异步任务轮询或 webhook。 |
| BasicRouter video generation | 否 | 取决于模型 | 否 | 否 | 否 | 使用异步任务轮询或 webhook。 |
认证
每个 API 请求都使用 bearer token。请将密钥存储在服务器端环境变量中,团队访问变更时及时轮换,并记录请求 ID 以便调试。
| 请求头 | 值 | 说明 |
|---|---|---|
Authorization | Bearer YOUR_API_KEY | 每个请求必填。 |
Content-Type | application/json | JSON 请求体必填。 |
密钥安全建议
- 将 API 密钥保留在服务器端。切勿在浏览器或移动客户端代码中暴露密钥。
- 为开发、预发布、生产和第三方集成使用不同的密钥。
- 在可用时按环境、服务、客户或租户限定密钥范围。
- 在员工离职、供应商访问变更或疑似泄露后轮换密钥。
- 将密钥存储在密钥管理器或环境变量中,而非源代码中。
编程智能体
BasicRouter 兼容支持 OpenAI 兼容或 Anthropic 兼容 API 端点的编程智能体和 AI
开发工具。使用 mwf/coding-auto 等路由别名,BasicRouter
即可路由到最佳的可用编程模型,无需开发者更改工具配置。
通用 OpenAI 兼容配置
此配置适用于 Cursor、Codex、Hermes、OpenClaw、Continue、Aider、Cline、基于 LangChain 的智能体、基于 LlamaIndex 的智能体以及自定义 OpenAI 兼容智能体运行时。
export OPENAI_BASE_URL="https://api.basicrouter.ai/api/v1"
export OPENAI_API_KEY="$BASICROUTER_API_KEY"
export OPENAI_MODEL="mwf/coding-auto"
通用 Anthropic 兼容配置
此配置适用于 Claude 兼容客户端以及期望 Anthropic Messages 格式的工具。
export ANTHROPIC_BASE_URL="https://api.basicrouter.ai/api/anthropic"
export ANTHROPIC_API_KEY="$BASICROUTER_API_KEY"
export ANTHROPIC_MODEL="mwf/coding-auto"
推荐的智能体模型
| 使用场景 | 推荐别名 | 要求 |
|---|---|---|
| 通用编程 | mwf/coding-auto | 工具调用、流式输出、强编程能力。 |
| 快速编程对话 | mwf/coding-fast | 低延迟和流式输出。 |
| 大型仓库分析 | mwf/coding-long | 长上下文和稳定输出。 |
| 成本敏感的编程助手 | mwf/low-cost | 较低价格且可接受的编程质量。 |
| UI 截图 / 视觉编程 | mwf/vision-chat | 视觉输入和文本输出。 |
Cursor 快速指南
使用 OpenAI 兼容端点。
Base URL: https://api.basicrouter.ai/api/v1
API Key: BASICROUTER_API_KEY
Model: mwf/coding-auto
推荐步骤:
- 打开 Cursor 设置。
- 添加或启用 OpenAI 兼容 API 密钥配置。
- 将 OpenAI base URL 覆盖设置为
https://api.basicrouter.ai/api/v1。 - 添加自定义模型,例如
mwf/coding-auto、mwf/coding-fast或mwf/coding-long。 - 使用支持流式输出和工具调用的模型以获得最佳智能体表现。
故障排查:
| 问题 | 建议修复 |
|---|---|
| 模型未显示 | 手动将模型名称添加为自定义模型。 |
| 工具调用失败 | 在模型页面使用 tool_calling: true 的模型。 |
| 流式中断 | 使用退避重试或使用带兜底的路由别名。 |
| 401 错误 | 检查 API 密钥和 base URL。 |
| 404 模型错误 | 确认该模型已为账户启用。 |
Claude Code 快速指南
使用 Anthropic 兼容网关端点。
export ANTHROPIC_BASE_URL="https://api.basicrouter.ai/api/anthropic"
export ANTHROPIC_API_KEY="$BASICROUTER_API_KEY"
export ANTHROPIC_MODEL="mwf/coding-auto"
BasicRouter 为 Claude Code 和 Anthropic SDK 兼容性提供此 Anthropic 兼容路径:
POST /api/v1/messages
推荐要求:
| 要求 | 原因 |
|---|---|
| Anthropic Messages 兼容的请求结构 | Claude Code 期望 Anthropic 风格的消息。 |
| 流式支持 | Claude Code 依赖流式交互体验。 |
| 工具调用支持 | 编程智能体工作流所必需。 |
| 长上下文 | 对仓库级任务有用。 |
| 稳定兜底 | 对长时间运行的编程会话有用。 |
Codex 快速指南
将 BasicRouter 作为自定义 OpenAI 兼容模型提供商使用。
示例提供商配置:
[model_providers.basicrouter]
name = "BasicRouter"
base_url = "https://api.basicrouter.ai/api/v1"
env_key = "BASICROUTER_API_KEY"
wire_api = "responses"
model_provider = "basicrouter"
model = "mwf/coding-auto"
环境变量:
export BASICROUTER_API_KEY="br_xxx"
推荐模型:
| 模型 | 使用场景 |
|---|---|
mwf/coding-auto | 默认编程智能体模型。 |
mwf/coding-long | 大型仓库上下文。 |
mwf/coding-fast | 快速迭代和小改动。 |
故障排查:
| 问题 | 建议修复 |
|---|---|
| 认证错误 | 确认 env_key 指向 BASICROUTER_API_KEY。 |
| 未找到模型 | 在 BasicRouter 控制台添加别名或使用直接的模型 ID。 |
| Responses API 错误 | 仅对支持 Responses 的模型和端点使用
wire_api = "responses"。 |
| 仅支持 Chat Completions 的模型 | 如果客户端支持,切换为 chat 兼容的 wire API。 |
Hermes 快速指南
除非你的 Hermes 部署配置了其他协议,否则使用 OpenAI 兼容端点。
export OPENAI_BASE_URL="https://api.basicrouter.ai/api/v1"
export OPENAI_API_KEY="$BASICROUTER_API_KEY"
export OPENAI_MODEL="mwf/coding-auto"
推荐模型策略:
| Hermes 工作负载 | 模型 |
|---|---|
| 通用代码生成 | mwf/coding-auto |
| 低延迟任务执行 | mwf/coding-fast |
| 长上下文仓库扫描 | mwf/coding-long |
| 成本敏感的后台任务 | mwf/low-cost |
OpenClaw 快速指南
使用 OpenAI 兼容端点进行 OpenAI 风格智能体运行时配置。
export OPENAI_BASE_URL="https://api.basicrouter.ai/api/v1"
export OPENAI_API_KEY="$BASICROUTER_API_KEY"
export OPENAI_MODEL="mwf/coding-auto"
如果 OpenClaw 支持多提供商,请将 BasicRouter 配置为 OpenAI 兼容提供商,并使用 BasicRouter 路由别名进行模型选择。
{
"provider": "openai-compatible",
"base_url": "https://api.basicrouter.ai/api/v1",
"api_key_env": "BASICROUTER_API_KEY",
"model": "mwf/coding-auto"
}
智能体兼容性检查清单
| 能力 | 适用场景 |
|---|---|
| 流式输出 | 良好的终端/编辑器交互体验。 |
| 工具调用 | 编程智能体、文件编辑、命令执行。 |
| 长上下文 | 大型仓库和多文件改动。 |
| 结构化输出 | 规划、任务分解、自动化工作流。 |
| 视觉输入 | UI 截图分析和设计转代码工作流。 |
| 兜底 | 生产稳定性和长时间运行的任务。 |
控制台使用
BasicRouter 控制台是 API 访问、模型可用性、路由策略、用量可见性和计费管理的运维控制面板。它为账户管理员提供密钥、模型、请求、积分和生产模型流量账户级控制的集中视图。
管理 API 密钥
在控制台中创建、轮换、吊销和标记 API 密钥。为开发、预发布、生产和各个服务使用不同的密钥,以便按环境或应用审计和隔离用量。
| 实践 | 说明 |
|---|---|
| 分离环境 | 为开发、预发布和生产流量使用不同的 API 密钥。 |
| 使用描述性标签 | 按应用、服务、环境或集成为密钥打标签。 |
| 定期轮换 | 在访问变更或凭证可能已暴露时轮换密钥。 |
| 避免客户端暴露 | 仅将 API 密钥保留在服务器端系统。切勿在浏览器或移动客户端代码中暴露密钥。 |
| 监控密钥用量 | 按密钥审查请求量、积分消耗和错误模式。 |
模型列表
使用模型页面查看账户可用的模型。每个模型条目可能包括厂商、服务提供商、模态、支持的 API 系列、上下文长度、能力标志、可用性状态和定价信息。
| 筛选器 | 用途 |
|---|---|
| 厂商 | 按模型厂商筛选,如 OpenAI、Anthropic、Google、Qwen、DeepSeek 或其他提供商。 |
| 提供商 | 按服务提供商或云提供商筛选。 |
| 模态 | 按文本、图像、视频、嵌入、音频或多模态支持筛选。 |
| 能力 | 按流式输出、工具调用、结构化输出、视觉、提示词缓存或推理支持筛选。 |
| 可用性 | 识别当前对账户可用的模型。 |
对于生产应用,启用流量前请验证模型能力。部分参数和功能取决于模型,可能并非在所有 API 系列中都受支持。
用量与日志
用量与日志视图提供 API 流量的运维可见性。团队可以检查请求量、所选模型、解析的路由目标、积分消耗、延迟、错误码和请求 ID。
- 排查失败的请求。
- 识别高成本工作负载。
- 比较不同应用和环境之间的模型用量。
- 验证路由和兜底行为。
- 调查延迟或提供商可用性问题。
- 联系支持时提供请求 ID。
每个 API 响应包含或暴露一个 BasicRouter 请求 ID。请将此 ID 存储在应用日志中,以提高生产调试和支持升级的效率。
兜底
兜底是 BasicRouter 的弹性机制。当主模型或路由策略失败时,系统自动切换到备用模型以继续处理请求。这使你的应用保持响应能力,并最大限度地降低服务中断的风险。
兜底就像一张安全网,即使在模型故障、配额限制或网络波动时也能保持应用平稳运行。
为什么兜底很重要
在生产环境中,模型服务可能会遇到许多不可预测的问题:
- 模型服务故障:上游 API 暂时不可用或超时。
- 性能波动:模型高负载导致响应缓慢或失败。
- 路由失败:智能路由选择的所有候选模型均不可用。
兜底通过提供可靠的备用路径来保持应用的可用性。
核心优势
| 优势 | 说明 |
|---|---|
| 高可用性 | 自动故障转移保持服务运行,减少停机影响。 |
| 透明切换 | 系统自动切换模型,无需修改应用代码。 |
| 灵活配置 | 支持请求级和账户级配置,适用于不同场景。 |
| 成本优化 | 选择更具成本效益的模型作为兜底,控制紧急成本。 |
| 集中管理 | 在账户级配置一次,即自动应用于每个请求。 |
全局兜底模型配置
BasicRouter 支持从控制台后端设置全局兜底模型。所有请求在失败时自动使用此模型作为备用。
配置方法:
- 前往 BasicRouter 策略设置页面。
- 找到 默认兜底模型 设置。
- 从下拉列表中选择你的全局兜底模型。
- 保存设置以立即生效。
全局配置的优势:
- 无需修改代码:配置一次即全局生效,无需在每个请求上重复设置。
- 集中管理:在一个位置管理兜底策略,便于调整和监控。
- 简化维护:降低代码复杂度和配置出错的可能性。
- 灵活覆盖:请求级兜底配置优先级更高,可为特定场景覆盖全局设置。
请求级兜底配置
对于特定业务场景,可在单个请求上指定兜底模型以覆盖全局配置。
使用 router.fallBackModels 参数指定兜底模型:
{
"model": "claude-sonnet-4",
"messages": [
{
"role": "user",
"content": "Explain what quantum computing is"
}
],
"router": {
"fallBackModels": ["glm-5.2"]
}
}
优先级规则
当存在多个兜底配置时,优先级从高到低为:
- 请求级
router.fallBackModels:在单个请求上指定的兜底模型。 - 全局默认兜底模型:在控制台配置的全局兜底模型。
- 无兜底:如果两者都未配置,请求失败时返回错误。
- 如果所有兜底模型均失败,系统返回最后尝试模型的失败原因。
- 当发生兜底时,响应会指明实际使用的模型,便于监控和分析。
账户管理
根据账户类型,控制台可能包括账户级模型启用、经销商或分销商控制、计费配置和访问设置。管理员可使用这些控制项,使模型访问、用量可见性和计费责任与应用、客户账户或业务单元保持一致。
生产运维检查清单
| 项目 | 建议 |
|---|---|
| API 密钥 | 使用带清晰标签的专用生产密钥。 |
| 模型 | 确认模型可用性、定价、上下文长度和所需能力。 |
| 路由 | 为关键工作负载配置路由别名或兜底策略。 |
| 日志 | 确保应用日志中捕获请求 ID。 |
| 计费 | 确认钱包余额、套餐状态和积分扣减规则。 |
| 速率限制 | 审查账户级 RPM、TPM、并发和媒体任务限制。 |
| 告警 | 监控用量增长、积分余额、错误和提供商可用性。 |
计费与积分
BasicRouter 在文本、图像、视频和其他支持的模型工作负载中采用基于积分的计费模型。积分为多模型和多提供商用量提供统一单位,使团队能够跨模态和 API 系列一致地管理消耗。
详细的模型定价可在模型页面或通过模型元数据 API 获取。定价可能因模型、提供商、模态、分辨率、token 类型、输出长度、任务时长、账户类型和商业协议而异。
充值与钱包
账户可添加按量付费钱包积分以获得灵活用量。除非账户适用自定义计费规则,否则钱包积分在月度套餐积分和资源包消耗完毕后使用。
除非适用商业条款另有规定,钱包积分不会过期。充值按量付费钱包时会收取服务费。
月度套餐和资源包
每个用户或账户可选择一个有效的月度套餐。月度套餐在计费周期内提供约定数量的用量容量、商业条款和账户级访问配置。
用户还可购买多个资源包以获得额外用量容量。资源包可将承诺用量与按量付费钱包余额分开,适用于大批量文本、图像、视频或专用工作负载用量。
扣费顺序
除非配置了自定义计费规则,否则积分按以下顺序扣减:
| 优先级 | 积分来源 | 说明 |
|---|---|---|
| 1 | 月度套餐 | 优先消耗包含的月度用量容量。 |
| 2 | 资源包 | 月度套餐积分消耗后消耗额外购买的资源包。 |
| 3 | 按量付费钱包 | 套餐和资源包积分消耗后消耗钱包余额。 |
对于有自定义商业条款的账户,扣费顺序、过期规则、包含用量和定价可能不同。账户特定规则会显示在控制台或通过商业协议提供。
自定义定价
可为每个用户或账户自定义定价。企业客户、经销商账户、分销商账户和大批量客户可能符合自定义定价条件。请联系销售获取报价。
自定义定价可按账户、模型、提供商、模态、区域、用量或商业协议配置。启用自定义定价后,控制台和计费 API 会在可用时反映账户特定的定价和扣减规则。
计价单位
不同模型模态使用不同的计量单位。BasicRouter 根据模型定价规则将这些单位转换为积分。
| 模态 | 常见计价基础 |
|---|---|
| 文本 | 输入 token、输出 token、缓存读 token、缓存写 token、推理 token 或模型特定的 token 类别。 |
| 图像 | 模型、分辨率、生成图片数量、输入图片用量、编辑模式或质量设置。 |
| 视频 | 模型、输出分辨率、生成秒数、宽高比、输入图片或视频用量和任务类型。 |
| 嵌入 | 输入 token 或嵌入记录数量。 |
| 音频 | 输入时长、输出时长、转录长度或模型特定的音频单位。 |
计价单位可能因模型而异。在生产环境中启用模型前,请务必参考模型详情页面或定价元数据。
用量归因
BasicRouter 用量可按账户、API 密钥、模型、模态或时间范围查看。这使团队能够将成本归因到应用、环境、客户或内部业务单元。
| 维度 | 说明 |
|---|---|
| API 密钥 | 按应用、服务或环境分组用量。 |
| 模型 | 按所选模型比较成本和用量。 |
| 解析后模型 | 查看路由或兜底后实际使用的模型。 |
| 模态 | 分离文本、图像、视频、嵌入和音频用量。 |
| 时间范围 | 查看每日、每月或自定义报告周期。 |
| 元数据 | 按自定义请求元数据(如客户 ID、租户 ID、用户 ID 或环境)分组用量。 |
积分余额
查看账户可用的积分数量。余额分为三个按顺序扣减的钱包:月度套餐积分、购买的资源包和按量付费钱包。还提供一个合并资源总量(月度套餐 + 资源包,不含按量付费),用于将包含用量与充值消费分开跟踪。
以编程方式获取此信息,请参见 API 参考中的
GET /v1/billing/balance。
用量详情
查看分页的、按时间顺序排列的用量记录列表,用于报告、监控和内部成本分摊。每条记录显示模型、模型类型(文本、图像或视频)、扣减的积分,以及每次扣减来自哪个钱包的明细。结果可筛选到特定时间范围。
以编程方式获取此信息,请参见 API 参考中的
GET /v1/usage。
交易记录
使用交易记录查看积分变动,包括充值、套餐分配、资源包发放、用量扣减、调整和管理修正。
以编程方式获取此信息,请参见 API 参考中的
GET /v1/billing/transactions。
失败请求与退款
校验错误、认证错误和权限错误通常不计费,因为未发生模型执行。到达上游模型或生成部分输出的请求可能会消耗积分,具体取决于模型、提供商和响应状态。
对于异步图像和视频任务,计费行为取决于任务是已接受、已开始、已完成、已失败还是已取消。任务详情响应在消耗积分时会包含用量信息。
充值、月度套餐、资源包和已消耗的积分不可退款,除非适用商业协议另有规定或法律要求。
API 参考
通用约定
Base URL
所有端点均提供在 /v1 前缀下。
认证
对 /v1/* 端点的调用使用 API Key 认证(非 JWT)。API Key
通过以下请求头传递:
| 请求头 | 格式 | 说明 |
|---|---|---|
Authorization | Bearer <api_key> | OpenAI 风格。Anthropic 兼容端点也接受 x-api-key 加
anthropic-version: 2023-06-01。 |
缺少或无效的密钥返回 401。
余额预检
所有调用模型的端点在执行前都会进行余额预检:
- 余额不足返回
Insufficient credit,映射为:- OpenAI 协议:HTTP
400,code = insufficient_quota - Anthropic 协议:HTTP
402,type = billing_error
- OpenAI 协议:HTTP
- 部分端点还会按模型估算最低成本以进行第二次预检。
POST https://api.basicrouter.ai/api/v1/chat/completions
OpenAI Chat Completions 兼容端点。支持流式和非流式、工具调用、JSON 模式和多模态输入。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | String | 是 | 模型名称。 |
messages | Message[] | 是 | 对话消息。 |
stream | Boolean | 否 | 流式模式,默认 false。 |
temperature | Double | 否 | 采样温度。 |
max_tokens | Integer | 否 | 最大输出 token 数。 |
top_p | Double | 否 | 核采样。 |
presence_penalty | Double | 否 | — |
frequency_penalty | Double | 否 | — |
tools | Tool[] | 否 | 工具定义。 |
tool_choice | String|Object | 否 | auto / none / required / 指定 函数。 |
response_format | Object | 否 | {type, json_schema:{name,schema,strict}};
text/json_object/json_schema。 |
parallel_tool_calls | Boolean | 否 | — |
metadata | Map | 否 | 透传元数据。 |
Message 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
role | String | system / user / assistant /
tool。 |
content | String|Array | 纯文本或多模态内容块数组
([{type:"text",text},{type:"image_url",image_url:{url}}])。 |
tool_call_id | String | 当 role=tool 时关联到 tool_calls。 |
tool_calls | ToolCall[] | 当 role=assistant 发起工具调用时出现。 |
| 字段 | 类型 | 说明 |
|---|---|---|
type | String | 固定值 function。 |
function | Object | 函数定义。 |
function.name | String | 函数名称。 |
function.description | String | 函数描述。 |
function.parameters | Object | 输入的 JSON Schema。 |
curl --request POST \
--url https://api.basicrouter.ai/api/v1/chat/completions \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "glm-5.2",
"messages": [{"role": "user", "content": "Describe Hangzhou in one sentence."}],
"stream": false,
"temperature": 0.7
}'
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1721380000,
"model": "glm-5.2",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "Hangzhou is ..."},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 12, "completion_tokens": 18, "total_tokens": 30}
}
响应字段(非流式):
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 补全 ID。 |
object | String | 固定值 chat.completion。 |
created | Long | 创建时间戳(秒)。 |
model | String | 模型名称。 |
choices | Choice[] | {index, message:{role, content, tool_calls?}, finish_reason}。 |
usage | Object | {prompt_tokens, completion_tokens, total_tokens}。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 工具调用 ID。 |
type | String | 固定值 function。 |
function | Object | 函数调用详情。 |
function.name | String | 函数名称。 |
function.arguments | Object | 函数参数。 |
流式响应示例:
data: {"object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":"..."}}]}
data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"..."}}]}
data: [DONE]
POST https://api.basicrouter.ai/api/v1/responses
OpenAI Responses 兼容端点。使用 input 代替 messages,使用
instructions 代替系统消息,使用 text 块代替
response_format。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | String | 是 | 模型名称。 |
input | String|Array | 是 | 纯字符串(用户消息)或消息对象数组。 |
instructions | String | 否 | 系统提示词。 |
stream | Boolean | 否 | 默认 false。 |
max_output_tokens | Integer | 否 | 最大输出 token 数。 |
temperature | Double | 否 | 默认 1。 |
top_p | Double | 否 | — |
tools | Tool[] | 否 | 顶层 {type, name, description, parameters}。 |
tool_choice | String|Object | 否 | auto
>/none/required/{type,name}。 |
text | Object | 否 | {format:{type, name, schema, strict}};
text/json_object/json_schema。 |
metadata | Map | 否 | — |
previous_response_id | String | 否 | 多轮对话的前一个响应 ID。 |
parallel_tool_calls | Boolean | 否 | — |
curl --request POST \
--url https://api.basicrouter.ai/api/v1/responses \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "glm-5.2",
"input": "Describe Hangzhou in one sentence.",
"instructions": "Be concise.",
"stream": false
}'
{
"id": "resp_xxx",
"object": "response",
"model": "glm-5.2",
"status": "completed",
"created_at": 1721380000,
"output": [
{
"id": "msg_xxx",
"type": "message",
"role": "assistant",
"content": [{"type": "output_text", "text": "Hangzhou is ..."}],
"status": "completed"
}
],
"usage": {"input_tokens": 12, "output_tokens": 18, "total_tokens": 30}
}
响应字段(非流式):
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 响应 ID。 |
object | String | 固定值 response。 |
model | String | 模型名称。 |
status | String | 如 completed。 |
created_at | Long | 创建时间戳(秒)。 |
output | Array | 输出项。消息项:
{id, type:"message", role, content:[{type:"output_text",
text}], status}。工具调用项:
{type:"function_call", id, name, call_id, arguments, status}。 |
usage | Object | {input_tokens, output_tokens, total_tokens}。对于 Claude 模型,
input_tokens 包含 cache_read,
output_tokens 包含 cache_write。 |
流式遵循 Responses API 事件:
| 事件 | 说明 |
|---|---|
response.created | 响应流开始。 |
response.output_text.delta | 文本增量输出更新。 |
response.completed | 响应流结束。 |
POST https://api.basicrouter.ai/api/v1/messages
Anthropic Messages 兼容端点。接受 x-api-key 和
anthropic-version: 2023-06-01 请求头。内容块支持
text、image、tool_use、tool_result、
thinking 和 redacted_thinking。
| 字段 | 类型 | 必填 | JSON 字段 | 说明 |
|---|---|---|---|---|
model | String | 是 | model | 模型名称。 |
messages | Message[] | 是 | messages | 对话消息。 |
system | String|Array | 否 | system | 系统提示词,字符串或 [{type,text}]。 |
maxTokens | Integer | 是 | max_tokens | 最大输出 token 数。 |
stream | Boolean | 否 | stream | 流式。 |
temperature | Double | 否 | temperature | — |
topP | Double | 否 | top_p | — |
topK | Integer | 否 | top_k | — |
tools | Tool[] | 否 | tools | 工具定义(input_schema)。 |
toolChoice | Object | 否 | tool_choice | — |
metadata | Map | 否 | metadata | — |
thinking | Object | 否 | thinking | 扩展思考配置。 |
stopSequences | Object | 否 | stop_sequences | — |
anthropicBeta | Object | 否 | anthropic_beta | Beta 功能请求头。 |
| 字段 | 类型 | 说明 |
|---|---|---|
role | String | 消息角色,如 user / assistant。 |
content | String|ContentBlock[] | 纯文本或内容块数组。 |
| 字段 | 类型 | 说明 |
|---|---|---|
type | String | text、image、tool_use、
tool_result、thinking、
redacted_thinking 之一。 |
text | String | 当 type 为 text 时出现。 |
source | Object | 当 type 为 image 时出现。 |
图片块示例:
{ "type": "image", "source": { "type": "base64", "media_type": "...", "data": "..." } }
{ "type": "image", "source": { "type": "url", "url": "..." } }
| 字段 | 类型 | 说明 |
|---|---|---|
name | String | 函数名称。 |
description | String | 函数描述。 |
input_schema | Object | 输入的 JSON Schema。 |
cache_control | Object | 可选缓存控制。 |
curl --request POST \
--url https://api.basicrouter.ai/api/v1/messages \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "Content-Type: application/json" \
--data '{
"model": "claude-sonnet-4.6",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Describe Hangzhou in one sentence."}]
}'
{
"id": "msg_xxx",
"type": "message",
"role": "assistant",
"model": "claude-sonnet-4.6",
"content": [{"type": "text", "text": "Hangzhou is ..."}],
"stop_reason": "end_turn",
"usage": {"input_tokens": 12, "output_tokens": 18}
}
响应字段(非流式):
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 消息 ID。 |
type | String | 固定值 message。 |
role | String | 固定值 assistant。 |
model | String | 模型名称。 |
content | ContentBlock[] | 响应内容块(如 {type:"text", text}、
{type:"tool_use", ...})。 |
stop_reason | String | 如 end_turn、tool_use、max_tokens。 |
usage | Object | {input_tokens, output_tokens}。 |
| 事件 | 说明 |
|---|---|
message_start | 消息流开始。 |
content_block_start | 新内容块开始。 |
content_block_delta | 内容块增量更新。 |
content_block_stop | 内容块结束。 |
message_delta | 消息增量更新。 |
message_stop | 消息流结束。 |
GET https://api.basicrouter.ai/api/v1/models
返回所有已上线、已启用的 API 模型。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/models \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"object": "list",
"data": [
{
"id": "glm-5.2",
"object": "model",
"display_name": "glm-5.2",
"created": 1721380000,
"owned_by": "Zai",
"input_modalities": ["text", "image"],
"output_modalities": ["text"],
"context_length": 128000
}
]
}
每个模型条目(data[])字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 模型 ID。 |
object | String | 固定值 model。 |
display_name | String | 显示名称。 |
created | Long | 创建时间戳(秒)。 |
owned_by | String | 所有者 / 厂商。 |
input_modalities | String[] | 如 ["text","image"]。 |
output_modalities | String[] | 如 ["text"]。 |
context_length | Integer | 最大上下文长度。 |
GET https://api.basicrouter.ai/api/v1/models/{model}
返回单个模型,结构与列表条目相同。模型不存在时返回 HTTP 404。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/models/gpt-5.5 \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
成功响应:单个模型对象,字段与
/v1/models 列表条目相同。
当模型不存在时,返回 HTTP 404:
{"error": {"message": "The model 'xxx' does not exist", "type": "invalid_request_error", "code": "invalid_model_error"}}
GET https://api.basicrouter.ai/api/v1/image-models
在调用
/v1/image-generations
之前,查询图像模型支持的分辨率、比例和最大数量。无需认证。
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 模型 ID。 |
object | String | 固定值 image_model。 |
displayName | String | 显示名称。 |
description | String | 模型描述。 |
icon | String | 图标 URL。 |
created | Long | 创建时间戳(秒)。 |
maxCount | Integer | 每次请求最大图片数。 |
fileMax | Integer | 最大参考图片数。 |
resolutions | String[] | 支持的分辨率,如 ["720p","1080p"]。 |
ratios | String[] | 支持的宽高比,如 ["1:1","3:2"]。 |
curl --request GET \
--url https://api.basicrouter.ai/api/v1/image-models \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"object": "list",
"data": [
{
"id": "gpt-image-2",
"object": "image_model",
"displayName": "GPT Image 1",
"description": "...",
"icon": "...",
"created": 1721380000,
"maxCount": 4,
"fileMax": 10,
"resolutions": ["720p", "1080p"],
"ratios": ["1:1", "3:2"]
}
]
}
GET https://api.basicrouter.ai/api/v1/video-models
在调用 /v1/video-generations 之前,查询视频模型支持的
videoType 值、时长范围、分辨率和比例。无需认证。
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 模型 ID。 |
object | String | 固定值 video_model。 |
displayName | String | 显示名称。 |
description | String | 模型描述。 |
icon | String | 图标 URL。 |
created | Long | 创建时间戳(秒)。 |
allowedVideoTypes | VideoTypeOption[] | 支持的 videoType 列表。 |
videoDurationMin | Integer | 每个片段最小秒数。 |
videoDurationMax | Integer | 每个片段最大秒数。 |
videoDurationSuggest | Integer[] | 推荐时长步长,如 [5,8,10]。 |
resolutions | String[] | 支持的分辨率。 |
ratios | String[] | 支持的宽高比。 |
resolutionOptions | ResolutionOption[] | 结构化的分辨率+比例+尺寸组合。 |
fileMax | Integer | 最大参考素材数。 |
VideoTypeOption 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
code | Integer | 传递给 /v1/video-generations 的 videoType 值。 |
name | String | 本地化类型名称(文生视频 / 图生视频 / ...)。 |
curl --request GET \
--url https://api.basicrouter.ai/api/v1/video-models \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"object": "list",
"data": [
{
"id": "sora-2",
"object": "video_model",
"displayName": "Sora 2",
"description": "...",
"icon": "...",
"created": 1721380000,
"allowedVideoTypes": [
{"code": 1, "name": "text-to-video"},
{"code": 2, "name": "image-to-video"},
{"code": 3, "name": "image-to-video (first/last frame)"}
],
"videoDurationMin": 5,
"videoDurationMax": 10,
"videoDurationSuggest": [5, 8, 10],
"resolutions": ["1080p", "720p"],
"ratios": ["16:9", "9:16"],
"fileMax": 5
}
]
}
POST https://api.basicrouter.ai/api/v1/image-generations
异步提交图像生成任务。立即返回 taskId;通过轮询
GET /v1/image-generations/{taskId} 或通过 callbackUrl webhook
获取结果。
model、支持的 resolution / ratio 值、
count 上限和参考图片上传限制(fileMax)必须先从
GET /v1/image-models
获取。仅接受该模型规格中公布的值。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | String | 是 | 提示词。 |
model | String | 是 | 模型名称。 |
imageUrls | String[] | 否 | 参考图片 URL(图生图)。 |
count | Integer | 否 | 图片数量(≥0)。 |
resolution | String | 否 | 分辨率(见 /v1/image-models)。 |
ratio | String | 否 | 宽高比。 |
callbackUrl | String | 否 | 任务级 webhook URL。 |
curl --request POST \
--url https://api.basicrouter.ai/api/v1/image-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "seedream-4.5",
"text": "A cat drinking water by the river",
"count": 1,
"resolution": "2k",
"ratio": "1:1",
"imageUrls": []
}'
{
"code": 200,
"message": "image task is commit",
"data": {"taskId": "img_xxx"}
}
错误响应:
// Insufficient credit
{ "code": 500, "message": "Insufficient credit" }
// Model not found
{ "code": 404, "message": "Model not found: xxx" }
GET https://api.basicrouter.ai/api/v1/image-generations/{taskId}
轮询图像生成任务。status 为 pending / success /
failed。images 是图片 URL 数组的 JSON 字符串;text
携带模型附加的文本描述(如 Gemini 多模态输出),否则为 null。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/image-generations/img_xxx \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"code": 200,
"message": "success",
"data": {
"taskId": "img_xxx",
"status": "success",
"errorMessage": null,
"images": "[\"https://.../1.png\"]",
"text": null
}
}
响应 data 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
taskId | String | 任务 ID。 |
status | String | pending / success / failed。 |
errorMessage | String | 失败原因,成功时为 null。 |
images | String | 图片 URL 数组的 JSON 字符串,如
"[\"https://.../1.png\"]"。 |
text | String | 模型附加的文本描述(如 Gemini 多模态输出);否则为 null。 |
任务未找到:
{ "code": 500, "message": "task not found" }
如果提交时提供了 callbackUrl,服务器会通过 webhook 推送最终的
success / failed 结果,数据结构相同。
完整示例(提交 + 轮询)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class ImageGenerationExample {
private static final String BASE = "https://api.basicrouter.ai/api/v1";
private static final String API_KEY = System.getenv("BASICROUTER_API_KEY");
public static void main(String[] args) throws Exception {
HttpClient http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)).build();
// 1. Submit the task.
String body = "{"
+ "\"model\":\"seedream-4.5\","
+ "\"text\":\"A cat drinking water by the river\","
+ "\"count\":1,"
+ "\"resolution\":\"2k\","
+ "\"ratio\":\"1:1\","
+ "\"imageUrls\":[]"
+ "}";
HttpResponse<String> submit = http.send(
HttpRequest.newBuilder(URI.create(BASE + "/image-generations"))
.header("Authorization", "Bearer " + API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body)).build(),
HttpResponse.BodyHandlers.ofString());
String taskId = extract(submit.body(), "taskId");
System.out.println("taskId = " + taskId);
// 2. Poll until terminal status.
String status = "pending";
while ("pending".equals(status)) {
Thread.sleep(15_000L);
HttpResponse<String> poll = http.send(
HttpRequest.newBuilder(URI.create(BASE + "/image-generations/" + taskId))
.header("Authorization", "Bearer " + API_KEY).GET().build(),
HttpResponse.BodyHandlers.ofString());
status = extract(poll.body(), "status");
System.out.println("status = " + status);
}
if (!"success".equals(status)) {
throw new RuntimeException("image generation failed: " + status);
}
// images is a JSON-stringified array of URLs.
String images = extract(pollResult(http, taskId), "images");
System.out.println("images = " + images);
}
// Minimal JSON field extractor — use Jackson/Gson in production.
private static String extract(String json, String field) {
int i = json.indexOf("\"" + field + "\":");
if (i < 0) return null;
i += field.length() + 3;
if (json.charAt(i) == '\"') {
int end = json.indexOf('\"', i + 1);
return json.substring(i + 1, end);
}
int end = i;
while (end < json.length() && "0123456789.".indexOf(json.charAt(end)) >= 0) end++;
return json.substring(i, end);
}
private static String pollResult(HttpClient http, String taskId) throws Exception {
return http.send(HttpRequest.newBuilder(URI.create(BASE + "/image-generations/" + taskId))
.header("Authorization", "Bearer " + API_KEY).GET().build(),
HttpResponse.BodyHandlers.ofString()).body();
}
}
import os
import time
import requests
BASE = "https://api.basicrouter.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BASICROUTER_API_KEY']}"}
# 1. Submit the task.
resp = requests.post(
f"{BASE}/image-generations",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "seedream-4.5",
"text": "A cat drinking water by the river",
"count": 1,
"resolution": "2k",
"ratio": "1:1",
"imageUrls": [],
},
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
print(f"taskId = {task_id}")
# 2. Poll until terminal status.
while True:
time.sleep(15)
poll = requests.get(f"{BASE}/image-generations/{task_id}", headers=HEADERS)
poll.raise_for_status()
data = poll.json()["data"]
status = data["status"]
print(f"status = {status}")
if status != "pending":
break
if status != "success":
raise RuntimeError(f"image generation failed: {data.get('errorMessage')}")
# images is a JSON-stringified array of URLs.
import json
images = json.loads(data["images"])
print(f"images = {images}")
POST https://api.basicrouter.ai/api/v1/video-generations
异步提交视频生成任务。立即返回 taskId;通过轮询
GET /v1/video-generations/{taskId} 或通过 callbackUrl webhook
获取结果。
model、允许的 videoType 值、时长范围
(videoDurationMin/Max)、支持的 resolution /
ratio 和参考素材上传限制(fileMax)必须先从
GET /v1/video-models 获取。仅接受该模型
allowedVideoTypes 中列出的 videoType 代码。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | String | 是 | 提示词。 |
model | String | 是 | 模型名称。 |
videoType | Integer | 是 | 1 文生视频 / 2 图生视频(首帧)/ 3 图生视频(首尾帧)/ 4 图生视频(参考)/ 5 全部参考。 |
imageUrls | String[] | 否 | 图片素材 URL。 |
videoUrls | VideoUrl[]|String[] | 否 | 视频素材 URL。 |
audioUrls | String[] | 否 | 音频素材 URL。 |
resolution | String | 否 | 分辨率。 |
ratio | String | 否 | 宽高比。 |
duration | Long | 否 | 秒数(>0)。 |
callbackUrl | String | 否 | 任务级 webhook URL。 |
各 videoType 示例:
1. 文生视频(videoType=1)
仅从文本提示词生成视频;无需参考素材。
curl --request POST \
--url https://api.basicrouter.ai/api/v1/video-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"videoType": 1,
"text": "A cat jumping on a bed",
"resolution": "480p",
"ratio": "16:9",
"duration": 4,
"model": "seedance-2.0"
}'
2. 图生视频 - 首帧(videoType=2)
在 imageUrls 中提供单张起始帧;模型从该帧开始生成视频。
curl --request POST \
--url https://api.basicrouter.ai/api/v1/video-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"videoType": 2,
"text": "Happily shaking head",
"resolution": "480p",
"ratio": "16:9",
"duration": 4,
"model": "seedance-2.0",
"imageUrls": ["https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/first-frame.png"]
}'
3. 图生视频 - 首尾帧(videoType=3)
在 imageUrls 中提供首帧和尾帧(顺序:
[首帧, 尾帧]);模型在两帧之间生成过渡视频。
curl --request POST \
--url https://api.basicrouter.ai/api/v1/video-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"videoType": 3,
"text": "Put on the hat",
"resolution": "480p",
"ratio": "16:9",
"duration": 4,
"model": "seedance-2.0",
"imageUrls": [
"https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/first-frame.png",
"https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/last-frame.png"
]
}'
4. 图生视频 - 参考(videoType=4)
在
imageUrls
中提供一张或多张参考图;模型使用其风格/内容作为参考(而非强制首/尾帧)来生成视频。
curl --request POST \
--url https://api.basicrouter.ai/api/v1/video-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"videoType": 4,
"text": "Two cats playing together",
"resolution": "480p",
"ratio": "16:9",
"duration": 4,
"model": "kling-v3-omni-video",
"imageUrls": [
"https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/ref-1.png",
"https://basicrouter-flie.oss-accelerate.aliyuncs.com/test/ref-2.png"
]
}'
5. 全部参考(videoType=5)
混合图片 / 视频 / 音频参考。在提示词中按位置引用素材:imageUrls 中第 1
项为 @图片 1,videoUrls 中第 1 项为
@视频 1,audioUrls 中第 1 项为 @音频 1。videoUrls
也接受纯 URL 字符串。
curl --request POST \
--url https://api.basicrouter.ai/api/v1/video-generations \
--header "Authorization: Bearer $BASICROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"videoType": 5,
"text": "Use the first-person framing of @视频 1 and @音频 1 as background music. First-person tea ad; start frame is @图片 1 ... end frame is @图片 2.",
"model": "seedance-2.0",
"imageUrls": [
"https://ark-project.tos-cn-beijing.volces.com/doc_image/r2v_tea_pic1.jpg",
"https://ark-project.tos-cn-beijing.volces.com/doc_image/r2v_tea_pic2.jpg"
],
"videoUrls": ["https://ark-project.tos-cn-beijing.volces.com/doc_video/r2v_tea_video1.mp4"],
"audioUrls": ["https://ark-project.tos-cn-beijing.volces.com/doc_audio/r2v_tea_audio1.mp3"],
"resolution": "1080p",
"ratio": "16:9",
"duration": 11
}'
提交响应(五种类型通用):
{
"code": 200,
"message": "success",
"data": {"taskId": "vid_xxx"}
}
GET https://api.basicrouter.ai/api/v1/video-generations/{taskId}
轮询视频生成任务。status 为 pending / success /
failed;videoUrl 是生成的视频 URL,lastFrameUrl
是尾帧 URL(图生视频场景)。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/video-generations/vid_xxx \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"code": 200,
"message": "success",
"data": {
"status": "success",
"videoUrl": "https://.../out.mp4",
"lastFrameUrl": null,
"message": null
}
}
响应 data 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
status | String | pending / success / failed。 |
videoUrl | String | 生成的视频 URL。 |
lastFrameUrl | String | 尾帧 URL(图生视频场景);否则为 null。 |
message | String | 失败原因,成功时为 null。 |
如果提交时提供了 callbackUrl,服务器会通过 webhook
推送最终结果,数据结构相同。
完整示例(提交 + 轮询)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class VideoGenerationExample {
private static final String BASE = "https://api.basicrouter.ai/api/v1";
private static final String API_KEY = System.getenv("BASICROUTER_API_KEY");
public static void main(String[] args) throws Exception {
HttpClient http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)).build();
// 1. Submit the task (videoType=1: text-to-video).
String body = "{"
+ "\"videoType\":1,"
+ "\"text\":\"A cat jumping on a bed\","
+ "\"resolution\":\"480p\","
+ "\"ratio\":\"16:9\","
+ "\"duration\":4,"
+ "\"model\":\"seedance-2.0\""
+ "}";
HttpResponse<String> submit = http.send(
HttpRequest.newBuilder(URI.create(BASE + "/video-generations"))
.header("Authorization", "Bearer " + API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body)).build(),
HttpResponse.BodyHandlers.ofString());
String taskId = extract(submit.body(), "taskId");
System.out.println("taskId = " + taskId);
// 2. Poll until terminal status. Video tasks take longer — poll every 20s.
String status = "pending";
String lastBody = null;
while ("pending".equals(status)) {
Thread.sleep(20_000L);
HttpResponse<String> poll = http.send(
HttpRequest.newBuilder(URI.create(BASE + "/video-generations/" + taskId))
.header("Authorization", "Bearer " + API_KEY).GET().build(),
HttpResponse.BodyHandlers.ofString());
lastBody = poll.body();
status = extract(lastBody, "status");
System.out.println("status = " + status);
}
if (!"success".equals(status)) {
throw new RuntimeException("video generation failed: " + status);
}
String videoUrl = extract(lastBody, "videoUrl");
System.out.println("videoUrl = " + videoUrl);
}
// Minimal JSON field extractor — use Jackson/Gson in production.
private static String extract(String json, String field) {
int i = json.indexOf("\"" + field + "\":");
if (i < 0) return null;
i += field.length() + 3;
if (json.charAt(i) == '\"') {
int end = json.indexOf('\"', i + 1);
return json.substring(i + 1, end);
}
int end = i;
while (end < json.length() && "0123456789.".indexOf(json.charAt(end)) >= 0) end++;
return json.substring(i, end);
}
}
import os
import time
import requests
BASE = "https://api.basicrouter.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BASICROUTER_API_KEY']}"}
# 1. Submit the task (videoType=1: text-to-video).
resp = requests.post(
f"{BASE}/video-generations",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"videoType": 1,
"text": "A cat jumping on a bed",
"resolution": "480p",
"ratio": "16:9",
"duration": 4,
"model": "seedance-2.0",
},
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
print(f"taskId = {task_id}")
# 2. Poll until terminal status. Video tasks take longer — poll every 20s.
while True:
time.sleep(20)
poll = requests.get(f"{BASE}/video-generations/{task_id}", headers=HEADERS)
poll.raise_for_status()
data = poll.json()["data"]
status = data["status"]
print(f"status = {status}")
if status != "pending":
break
if status != "success":
raise RuntimeError(f"video generation failed: {data.get('message')}")
print(f"videoUrl = {data['videoUrl']}")
if data.get("lastFrameUrl"):
print(f"lastFrameUrl = {data['lastFrameUrl']}")
GET https://api.basicrouter.ai/api/v1/billing/balance
返回账户余额,分为三个钱包:月度套餐、资源包和按量付费积分。
curl --request GET \
--url https://api.basicrouter.ai/api/v1/billing/balance \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
{
"totalCredit": 128.50,
"totalResourceCredit": 30.00,
"wallets": {
"monthlyPlan": {"id": "pkg_xxx", "credit": 50.00, "name": "Monthly plan"},
"resourcePacks": [
{"id": "rp_xxx", "credit": 30.00, "name": "Video resource pack"}
],
"payAsYouGo": 48.50
}
}
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
totalCredit | BigDecimal | 总余额。 |
totalResourceCredit | BigDecimal | 资源包余额合计。 |
wallets.monthlyPlan | WalletDetail | 月度套餐(无则为 null)。 |
wallets.resourcePacks | WalletDetail[] | 资源包列表。 |
wallets.payAsYouGo | BigDecimal | 按量付费余额。 |
WalletDetailVO 字段::
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | 钱包 ID。 |
credit | BigDecimal | 余额积分。 |
name | String | 钱包名称。 |
GET https://api.basicrouter.ai/api/v1/usage
分页的模型调用计费详情,按价格
(priceSnapshotId)快照,按订单创建时间倒序排列。仅返回正常扣费记录 (reason = model usage)。
查询参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
page | Integer | 否 | 1 | 页码,从 1 开始。 |
size | Integer | 否 | 20 | 每页条数(按 priceSnapshotId 分页)。 |
startTime | LocalDateTime | 否 | — | 开始时间,格式 yyyy-MM-ddTHH:mm:ss,按快照
orderCreatedAt 筛选。 |
endTime | LocalDateTime | 否 | — | 结束时间,格式 yyyy-MM-ddTHH:mm:ss。 |
curl --request GET \
--url "https://api.basicrouter.ai/api/v1/usage?page=1&size=20&startTime=2026-07-01T00:00:00&endTime=2026-07-31T23:59:59" \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
响应包装:
{
"code": 0,
"message": "success",
"data": { ... }
}
| 字段 | 类型 | 说明 |
|---|---|---|
records | UsageDetailVO[] | 当前页记录。 |
total | Long | 总条数。 |
current | Long | 当前页码。 |
size | Long | 每页条数。 |
pages | Long | 总页数。 |
UsageDetailVO 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
priceSnapshotId | String | 价格快照 ID。 |
taskId | String | 任务 ID。 |
credit | BigDecimal | 扣费金额。 |
model | String | 模型名称。 |
modelType | String | text / image / video。 |
inputTokens | Long | 输入 token 数;图像/视频为 null。 |
outputTokens | Long | 输出 token 数。 |
totalTokens | Long | 总 token 数。 |
cacheReadTokens | Long | 缓存读取 token 数。 |
cacheWriteTokens | Long | 缓存写入 token 数。 |
imageCount | Integer | 图像数量;图像模型时设置。 |
imageResolution | String | 图像分辨率,例如 720P。 |
imageRatio | String | 图像宽高比,例如 1:1。 |
videoResolution | String | 视频分辨率,例如 1080p。 |
videoRatio | String | 视频宽高比,例如 16:9。 |
videoDurationSec | Long | 视频时长(秒)。 |
orderCreatedAt | LocalDateTime | 订单创建时间(快照 orderCreatedAt)。 |
creditDetails | CreditDetailItem[] | 该快照下的订单明细(来自 credit_order_t)。 |
CreditDetailItem 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
credit | BigDecimal | 该订单的扣费金额。 |
deductionSource | String | 扣费来源(Balance / Monthly Package /
Resource Package)。 |
packageName | String | 套餐名称;无套餐时为 null。 |
空值约定:仅填充与各 modelType 相关的字段,其余为 null。text
填充 token 字段; image 填充
imageCount/imageResolution/imageRatio; video 填充
videoResolution/videoRatio/videoDurationSec。
响应示例:
{
"code": 200,
"message": "success",
"data": {
"records": [
{
"priceSnapshotId": "snap_9f3c1a2b",
"taskId": "task_5e8a1c33",
"credit": 0.0342,
"model": "glm-5.2",
"modelType": "text",
"inputTokens": 1280,
"outputTokens": 642,
"totalTokens": 1922,
"cacheReadTokens": 0,
"cacheWriteTokens": 0,
"imageCount": null,
"imageResolution": null,
"imageRatio": null,
"videoResolution": null,
"videoRatio": null,
"videoDurationSec": null,
"orderCreatedAt": "2026-07-18T14:23:11",
"creditDetails": [
{
"credit": 0.0342,
"deductionSource": "balance",
"packageName": ""
}
]
},
{
"priceSnapshotId": "snap_a12f77c0",
"taskId": "task_c71e44a2",
"credit": 1.8000,
"model": "seedance-2.0",
"modelType": "video",
"inputTokens": null,
"outputTokens": null,
"totalTokens": null,
"cacheReadTokens": null,
"cacheWriteTokens": null,
"imageCount": null,
"imageResolution": null,
"imageRatio": null,
"videoResolution": "1080p",
"videoRatio": "16:9",
"videoDurationSec": 8,
"orderCreatedAt": "2026-07-17T22:41:09",
"creditDetails": [
{
"credit": 1.5000,
"deductionSource": "Monthly Package",
"packageName": "基础月度套餐"
},
{
"credit": 0.3000,
"deductionSource": "Resource Package",
"packageName": "byteplus视频资源包"
}
]
}
],
"total": 128,
"current": 1,
"size": 20,
"pages": 7
}
}
GET https://api.basicrouter.ai/api/v1/billing/transactions
分页返回当前用户已支付(status=2)的充值交易,按
created_at 倒序排列。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
page | Integer | 否 | 1 | 页码。 |
size | Integer | 否 | 20 | 每页条数。 |
startTime | String | 否 | — | 开始时间,yyyy-MM-dd HH:mm:ss,包含边界。 |
endTime | String | 否 | — | 结束时间,yyyy-MM-dd HH:mm:ss,包含边界。 |
curl --request GET \
--url "https://api.basicrouter.ai/api/v1/billing/transactions?page=1&size=20&startTime=2026-07-01%2000:00:00&endTime=2026-07-31%2023:59:59" \
--header "Authorization: Bearer $BASICROUTER_API_KEY"
响应包装:
{
"code": 0,
"message": "success",
"data": { ... }
}
| 字段 | 类型 | 说明 |
|---|---|---|
records | TransactionVO[] | 当前页交易记录。 |
total | Long | 总条数。 |
current | Long | 当前页码。 |
size | Long | 每页条数。 |
pages | Long | 总页数。 |
TransactionVO 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
orderNo | String | 订单号。 |
thirdPartyOrderNo | String | 第三方订单号。 |
amount | BigDecimal | 订单金额。 |
actualAmount | BigDecimal | 实付金额。 |
discount | BigDecimal | 优惠金额。 |
paymentMethod | String | 支付方式(wechat / alipay / ustd /
stripe / wallyt 等)。 |
TransactionVO 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
serviceFeeAmount | BigDecimal | 服务费金额。 |
paymentChannel | String | 支付渠道。 |
source | String | 订单来源(recharge / package_purchase 等)。 |
packageName | String | 套餐名称(套餐购买时设置;普通充值为 null)。 |
createdAt | LocalDateTime | 创建时间。 |
{
"code": 200,
"message": "success",
"data": {
"records": [
{
"orderNo": "R20260718abc123",
"thirdPartyOrderNo": "wx_pay_xxx",
"amount": 50.00,
"actualAmount": 48.50,
"discount": 1.50,
"paymentMethod": "wechat",
"serviceFeeAmount": 0.00,
"paymentChannel": "wechat",
"source": "recharge",
"packageName": null,
"createdAt": "2026-07-18T14:23:11"
}
],
"total": 28,
"current": 1,
"size": 20,
"pages": 2
}
}
运维
错误处理
BasicRouter 返回稳定的错误码,便于应用统一处理重试、兜底、计费问题和调试。
兼容上游的端点会尽量保留原始 API 系列的错误结构。BasicRouter 原生端点使用 BasicRouter 错误对象。
HTTP 状态码与错误码映射
| HTTP 状态码 | 错误类型 | 示例错误码 | 是否重试 |
|---|---|---|---|
| 400 | invalid_request_error | invalid_request, unsupported_parameter,
invalid_messages, invalid_image_url | 否 |
| 401 | authentication_error | missing_api_key, invalid_api_key | 否 |
| 402 | billing_error | insufficient_credits, payment_required,
quota_exceeded | 否 |
| 403 | permission_error | model_access_denied, endpoint_access_denied,
key_scope_denied | 否 |
| 404 | not_found_error | model_not_found, response_not_found,
task_not_found | 否 |
| 408 | timeout_error | gateway_timeout, provider_timeout | 是 |
| 409 | conflict_error | idempotency_conflict, task_already_cancelled | 视情况 |
| 422 | validation_error | schema_validation_failed, unsupported_modality | 否 |
| 429 | rate_limit_error | account_rpm_exceeded, account_tpm_exceeded,
provider_rate_limited | 是 |
| 500 | internal_error | internal_error | 是 |
| 502 | provider_error | provider_bad_gateway, provider_invalid_response | 是 |
| 503 | service_unavailable | model_unavailable, provider_unavailable,
insufficient_capacity | 是 |
| 504 | timeout_error | provider_timeout, gateway_timeout | 是 |
常见错误码
| 错误码 | 含义 | 建议操作 |
|---|---|---|
missing_api_key | 未提供 API 密钥。 | 添加 Authorization 请求头。 |
invalid_api_key | API 密钥无效或已吊销。 | 创建或轮换 API 密钥。 |
model_not_found | 模型 ID 不存在或未对该账户启用。 | 查看模型页面或调用 GET /v1/models。 |
model_access_denied | API 密钥或账户无权访问该模型。 | 启用模型或联系管理员。 |
unsupported_parameter | 请求包含所选端点或模型不支持的参数。 | 移除该参数或选择兼容的模型。 |
unsupported_modality | 所选模型不支持该输入或输出模态。 | 选择支持该模态的模型。 |
account_rpm_exceeded | 账户每分钟请求数超限。 | 带退避重试或申请更高限额。 |
account_tpm_exceeded | 账户每分钟 token 数超限。 | 带退避重试、减少 token 数或申请更高限额。 |
provider_rate_limited | 上游服务商对该请求限流。 | 重试或启用兜底。 |
insufficient_credits | 账户积分不足。 | 充值钱包、购买资源包或升级套餐。 |
provider_timeout | 上游服务商未及时响应。 | 重试或启用兜底。 |
model_unavailable | 模型暂时不可用。 | 重试或使用路由别名。 |
content_policy_error | 请求或输出被安全策略拦截。 | 修改输入或选择合适的工作流。 |
支持
获取 BasicRouter 帮助
查找常见 API、计费、路由和集成问题的答案。如遇生产问题,请提供请求 ID、API 密钥标签、端点、模型和时间戳,以便团队快速定位请求。
常见问题
点击问题展开答案。
联系我们
为请求选择最合适的联系方式。
适用于故障事件、限流、计费问题、生产路由问题、SDK 迁移、服务商兼容性、端点设计问题、企业套餐、承诺用量或自定义服务商路由需求。











