快速开始
-
注册并创建 API 密钥
进入控制台创建密钥(形如
sk-****),妥善保管勿泄露。 -
获取接入地址
平台接入地址为
https://api.cmrouter.com,下文示例已按真实地址书写,拷贝即可运行;控制台「工具接入」可按工具生成已填好地址与密钥的配置。 -
发起首次调用
任选下方语言示例,把
model字段换成目标模型 id。
curl https://api.cmrouter.com/v1/chat/completions \
-H "Authorization: Bearer sk-****" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"messages": [
{"role": "user", "content": "你好,介绍一下你自己"}
]
}'
编程工具快速接入
Cursor、Claude Code 等 AI 编程工具均通过自定义 OpenAI / Anthropic 端点接入平台:把工具里的 API 地址换成平台接入地址、密钥换成个人 Key 即可。控制台「工具接入」页可按工具逐项生成已填好地址与密钥的配置,推荐从那里开始。
| 工具 | 接入方式 | 要点 |
|---|---|---|
| Cursor | Settings → Models,覆盖 OpenAI Base URL |
|
| Claude Code | ~/.claude/settings.json 的 env 字段 |
|
| Codex CLI | ~/.codex/config.toml 自定义 model_provider |
|
| Codex App(桌面版) | 与 CLI 共用 ~/.codex/config.toml(或 App 内 Settings → Model Providers) |
|
| Aider | 环境变量 OPENAI_API_BASE |
|
| Cline / Roo Code | 扩展设置里 Provider 选 OpenAI Compatible 或 Anthropic |
|
| Continue | 配置的 models 列表 |
|
| OpenCode | opencode.json 配置自定义 provider |
|
代码示例
以下示例均以对话接口为例,替换 <模型名> 后即可直接运行。
平台同时提供三套协议入口(OpenAI Chat Completions、OpenAI Responses、Anthropic Messages),接入差异只在 base_url 与鉴权头:
| 协议 | base_url | 鉴权 |
|---|---|---|
| OpenAI Chat Completions / Responses | https://api.cmrouter.com/v1 | Authorization: Bearer |
| Anthropic Messages | https://api.cmrouter.com(不带 /v1,SDK 自行追加路径) |
x-api-key + anthropic-version 头 |
Anthropic Messages 与 OpenAI Responses 协议的完整请求样例见流式调用;请求体去掉 "stream": true、客户端把事件循环换成一次性读取响应,即为非流式调用(curl 仅需去掉该字段)。
curl https://api.cmrouter.com/v1/chat/completions \
-H "Authorization: Bearer sk-****" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"messages": [
{"role": "user", "content": "你好,介绍一下你自己"}
]
}'
from openai import OpenAI
client = OpenAI(
api_key="sk-****",
base_url="https://api.cmrouter.com/v1",
)
resp = client.chat.completions.create(
model="<模型名>",
messages=[
{"role": "user", "content": "你好,介绍一下你自己"}
],
)
print(resp.choices[0].message.content)
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-****",
baseURL: "https://api.cmrouter.com/v1",
});
const resp = await client.chat.completions.create({
model: "<模型名>",
messages: [
{ role: "user", content: "你好,介绍一下你自己" }
],
});
console.log(resp.choices[0].message.content);
OkHttpClient client = new OkHttpClient();
String payload = """
{
"model": "<模型名>",
"messages": [
{"role": "user", "content": "你好,介绍一下你自己"}
]
}
""";
Request request = new Request.Builder()
.url("https://api.cmrouter.com/v1/chat/completions")
.addHeader("Authorization", "Bearer sk-****")
.post(RequestBody.create(payload, MediaType.parse("application/json")))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
payload, _ := json.Marshal(map[string]any{
"model": "<模型名>",
"messages": []map[string]string{
{"role": "user", "content": "你好,介绍一下你自己"},
},
})
req, _ := http.NewRequest("POST", "https://api.cmrouter.com/v1/chat/completions", bytes.NewBuffer(payload))
req.Header.Set("Authorization", "Bearer sk-****")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
流式调用
三种对话协议均支持 SSE 流式返回:请求体加 "stream": true,服务端会逐段推送增量内容,客户端按分段读取即可。
OpenAI Chat Completions 协议(/v1/chat/completions)
curl -N https://api.cmrouter.com/v1/chat/completions \
-H "Authorization: Bearer sk-****" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"stream": true,
"messages": [
{"role": "user", "content": "用一句话介绍你自己"}
]
}'
from openai import OpenAI
client = OpenAI(api_key="sk-****", base_url="https://api.cmrouter.com/v1")
stream = client.chat.completions.create(
model="<模型名>",
messages=[{"role": "user", "content": "你好"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
OpenAI Responses 协议(/v1/responses)
Codex CLI 与 OpenAI Agents SDK 默认走此端点(OpenAI 新一代接口),把 base_url 指向平台即可,无需改代码。
curl -N https://api.cmrouter.com/v1/responses \
-H "Authorization: Bearer sk-****" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"stream": true,
"input": "用一句话介绍你自己"
}'
from openai import OpenAI
client = OpenAI(api_key="sk-****", base_url="https://api.cmrouter.com/v1")
stream = client.responses.create(
model="<模型名>",
input="你好",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
Anthropic Messages 协议(/v1/messages)
鉴权用 x-api-key 头,Claude 系 SDK / Claude Code 换 base_url 即用。
curl -N https://api.cmrouter.com/v1/messages \
-H "x-api-key: sk-****" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"max_tokens": 1024,
"stream": true,
"messages": [
{"role": "user", "content": "用一句话介绍你自己"}
]
}'
import anthropic
client = anthropic.Anthropic(
api_key="sk-****",
base_url="https://api.cmrouter.com",
)
stream = client.messages.create(
model="<模型名>",
max_tokens=1024,
stream=True,
messages=[{"role": "user", "content": "你好"}],
)
for event in stream:
if event.type == "content_block_delta" and event.delta.type == "text_delta":
print(event.delta.text, end="", flush=True)
工具调用
三种对话协议均支持工具调用(Function Calling):OpenAI 协议的 tools / tool_calls 与 Responses 协议的扁平 function 工具按官方结构原生透传;Anthropic 协议的 tools / tool_use / tool_result 由平台自动完成双向转换,Claude SDK 无需任何改造。
声明工具
以 Anthropic 协议为例,在请求中声明工具:
curl https://api.cmrouter.com/v1/messages \
-H "x-api-key: sk-****" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "查询指定城市当前天气",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
],
"tool_choice": {"type": "auto"},
"messages": [
{"role": "user", "content": "北京今天天气怎么样?"}
]
}'
响应中的 tool_use
模型决定调用工具时,响应中会包含 tool_use 内容块,且 stop_reason 为 tool_use:
{
"type": "message",
"role": "assistant",
"content": [
{"type": "text", "text": "我来查一下"},
{"type": "tool_use", "id": "toolu_01", "name": "get_weather",
"input": {"city": "北京"}}
],
"stop_reason": "tool_use"
}
回传 tool_result
执行工具后,把结果以 tool_result 块随下一轮请求回传,即可获得最终回答:
curl https://api.cmrouter.com/v1/messages \
-H "x-api-key: sk-****" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "<模型名>",
"max_tokens": 1024,
"tools": [ ... 同上 ... ],
"messages": [
{"role": "user", "content": "北京今天天气怎么样?"},
{"role": "assistant", "content": [
{"type": "text", "text": "我来查一下"},
{"type": "tool_use", "id": "toolu_01", "name": "get_weather",
"input": {"city": "北京"}}
]},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_01",
"content": "晴,25 度,西北风 3 级"}
]}
]
}'
使用要点
-
tool_choice 三种模式
{"type": "auto"}模型自行决定、{"type": "any"}必须调用某个工具、{"type": "tool", "name": "..."}指定工具,平台自动映射到对应上游协议。 -
流式工具参数增量推送
流式调用时工具参数以
input_json_delta事件推送,客户端按顺序拼接partial_json即可还原完整参数。 -
OpenAI 协议对应行为
finish_reason为tool_calls,工具调用位于message.tool_calls,结果以role: "tool"消息回传。 -
上游支持范围
部分上游模型暂不支持工具调用(如 Gemini 系),请求会返回明确的错误信息。
接口总览
端点列表
平台在同一接入地址下同时提供三套对话协议入口(OpenAI Chat Completions、OpenAI Responses、Anthropic Messages),请求与响应结构和官方保持一致;上游各家模型的协议差异由平台自动适配,对调用方透明。OpenAI 协议使用 Authorization: Bearer 鉴权,Anthropic 协议使用 x-api-key 头鉴权。
| 接口 | 方法与路径 | 说明 |
|---|---|---|
| OpenAI Chat Completions | POST /v1/chat/completions | 常规对话,绝大多数 OpenAI SDK 与工具默认走此入口,支持 SSE 流式 |
| OpenAI Responses | POST /v1/responses | OpenAI 新一代协议端点,Codex CLI / Agents SDK 默认走此入口,支持 SSE 流式与函数工具调用 |
| Anthropic Messages | POST /v1/messages | Claude 系模型原生协议,Anthropic SDK 直接可用,支持 SSE 流式 |
| Token 预估(Anthropic 协议) | POST /v1/messages/count_tokens | 按官方语义预估消息将消耗的 token 数(含 tools),不计费;Claude SDK 发消息前会自动调用 |
| 模型列表 | GET /v1/models | 列出当前可调用的全部模型 id |
| 模型检索 | GET /v1/models/{id} | 查询单个模型是否存在及其信息 |
| 文本向量 | POST /v1/embeddings | 文本嵌入(Embeddings),用于检索与语义匹配 |
| 图像生成 | POST /v1/images/generations | OpenAI 兼容的图像生成接口 |
| 视频生成 | POST /v1/videos | 创建视频生成任务,异步执行;GET /v1/videos/{id} 查询状态。分辨率传 size("1080p"、"1920x1080" 均可)或 resolution(480p/720p/1080p/4k 档位)皆可,平台统一归一适配各模型:尺寸写法自动换算分辨率档并推出画幅比(竖屏 1080x1920 即 9:16);特殊画幅可显式传 ratio,无需关心不同模型的参数写法差异 |
输出长度控制
两种写法等价可用:max_tokens 与 OpenAI 新参数 max_completion_tokens(计数含思维链),两者同时传会返回 400。各模型最大输出见模型广场。
-
超限自动规约
超过模型最大输出的请求会被平台自动规约至该模型上限(
max_tokens语义为「至多」,规约不损失请求意图;未配置上限的模型原样透传,由上游校验)。 -
生效值可对账
实际生效值通过响应头
X-Effective-Max-Tokens回显,便于对账;未指定上限时不设该头,上游将使用自身默认输出长度。
协议兼容与地址替换
Anthropic Messages 协议(/v1/messages)按官方语义支持常用参数(含 tools / tool_choice、stop_sequences 与图像输入)。
调用时把 OpenAI / Anthropic 官方 API 地址整体替换为 https://api.cmrouter.com,路径、参数与响应结构保持不变。
模型选择
请求中的 model 字段直接传模型 id 即可。完整模型列表与单价见模型广场(公开价目快照 GET /public/pricing 仅包含有活跃渠道的模型,与模型列表保持同步)。
也可通过 GET https://api.cmrouter.com/v1/models(携带密钥)编程获取列表。
-
route:auto 自动路由
route:auto是平台的自动路由入口:把model设为route:auto,网关按各候选渠道的实际定价自动选择成本最低的可用模型;按实际命中模型的原价计费(路由本身免费),响应头X-Route-Model回传本次命中的模型。
思考模型的两种形态:部分模型以名称后缀区分思考版(如 claude-opus-4-8-thinking),换用不带后缀的同款模型名即为非思考版;GLM 系列(glm-5.2 / glm-5.3 / glm-5.3-flash)默认开启思考、思考过程会消耗输出 token,请求体传 "thinking": {"type": "disabled"} 可关闭(该参数仅对 GLM 系生效,对名称带 -thinking 后缀的模型无效)。
计费说明
-
按 tokens 计费
输入与输出分别计价,按实际用量结算。
-
缓存命中更省
命中缓存前缀的输入部分按更低单价计。
-
图像按次计费
图像模型按生成张数计费,默认规格 1024×1024(1K),与 tokens 用量无关。
-
视频按用量计费
视频模型按实际用量计费(生成 token 数或时长),创建时预估冻结,完成后多退少补。
-
预扣与结算
请求与任务发起时按预估上限校验可用余额并预扣,完成后按实际用量结算、多退少补;门户余额展示为总额(含进行中任务的预扣),故余额数字在任务完成后才下降,失败任务自动全额退回。
具体单价以模型广场各模型价目为准。计费金额向上取整至最小计费粒度 ¥0.000001,单次不足此金额的按 ¥0.000001 计。
计费对账接口
除门户控制台外,平台提供三个只读端点供程序对账(余额告警、定时对账脚本等),响应中的金额一律为人民币元。
持任意有效密钥调用,返回密钥所属账户的余额;额度耗尽的密钥同样可查(只读自查放行,不会被额度拦截)。
curl https://api.cmrouter.com/v1/ledger/balance \
-H "Authorization: Bearer sk-****"
{
"tenant_id": "t_xxxx",
"balance": 128.50234, // 余额总额(元):含进行中请求/任务的预扣,结算完成后才下降
"reserved": 1.2, // 预扣占用中(元)
"available": 127.30234, // 可用额度(元):发起新请求/任务时校验的额度
"subsidy_balance": 0, // 补贴余额(元)
"prepay_balance": 128.50234, // 充值余额(元)
"currency": "CNY"
}
按维度聚合调用量与消费,仅统计成功请求。start / end(可选)按 UTC 理解,start 含端、end 不含端;group_by 可选 model / day / billing_group / scenario,默认 model。
curl "https://api.cmrouter.com/v1/metering/usage?group_by=model&start=2026-10-01&end=2026-11-01" \
-H "Authorization: Bearer sk-****"
{
"total_tokens": 123456, // tokens 为真实用量统计
"total_calls": 42, // 仅计成功请求
"total_charged_amount": 1.23, // 实扣金额(元)
"group_by": "model",
"by_model": [
{ "model": "glm-5.3", "total_tokens": 100000, "calls": 40, "charged_amount": 1.0 }
]
}
免鉴权、无需密钥。返回全部模型当前单价(元 / 百万 tokens),按模型名排序、结构稳定,可直接缓存复用;与模型广场同源同价。
curl https://api.cmrouter.com/public/pricing
{
"models": [
{
"model": "glm-5.3",
"billing_type": "per_token",
"pricing": {
"input": 8, // 输入单价(元/百万 tokens)
"output": 28, // 输出单价(元/百万 tokens)
"cache_read": 2, // 缓存命中单价
"cache_write": 0,
"per_request": 0, // 按次计费模型(图像)才非零,单位元/张
"per_second": 0 // 按秒计费模型(视频)才非零,单位元/秒
},
"tiers": [ ... ] // 仅分时档模型携带:空闲/高峰分档单价
}
]
}
状态码与重试
出错时返回体分两层:HTTP 状态码标明大类——4xx 表示请求本身有问题,需要修改后才能成功;5xx 表示平台或上游侧故障,等待片刻后重试通常即可恢复。error.code 标明具体原因,是程序里做分支处理的依据。排查思路:先看状态码定方向,再按 error.code 对照下表处理。
错误响应结构
{
"error": {
"message": "Invalid API key", // 错误原因说明,可直接阅读
"type": "cmrouter_error", // 固定为 cmrouter_error,表示错误来自本平台
"code": "invalid_api_key", // 错误码,程序按它判断,见下表
"param": null // 补充信息(如涉及的参数、审核明细),无则为 null
}
}
{
"type": "error",
"error": {
"type": "authentication_error", // 官方错误类型,由状态码映射(本例 401)
"message": "Invalid API key" // 具体原因,与 OpenAI 协议的 message 相同
}
}
两种协议的 HTTP 状态码与 message 完全一致,可按接入协议任选一种解析。Anthropic 协议没有 error.code 字段,error.type 由状态码映射为官方类型:400/422 → invalid_request_error、401 → authentication_error、403 → permission_error、404 → not_found_error、429 → rate_limit_error、503 → overloaded_error、504 → timeout_error,其余 5xx → api_error;使用日志中记录的错误码仍为下表的 error.code。
错误码对照表
| 状态码 | error.code | 原因 | 处理办法 |
|---|---|---|---|
| 400 | invalid_request | 请求参数不合法 | 按 message 提示修正参数后重发 |
| unsupported_content_type | 请求携带了该模型不支持的内容类型(如向纯文本模型发送图片) | 换用支持视觉的模型(模型广场标签含「视觉」的),或去掉请求中的图片内容 | |
| validation_failed | 请求体校验失败 | 按 message 指出的字段修正请求体 | |
| channel_model_mapped_error | 标准模型名在该渠道未配置上游映射 | 联系管理员补全映射,或先换其他可用模型 | |
| model_price_error | 模型缺少计费配置,无法计费 | 联系管理员补配价目后重试 | |
| context_length_exceeded | 估算输入 token 明显超过模型上下文窗口(网关预检,估算达上限 2 倍才拦截;边界情况由上游精确判定) | 精简 messages 长度或换更大上下文窗口的模型 | |
| 401 | invalid_api_key | API Key 缺失或无效 | 检查 Authorization 请求头与密钥是否完整正确 |
| 403 | key_revoked | API Key 已被吊销 | 换用其他 Key,或联系管理员恢复 |
| key_exhausted | API Key 日/月额度耗尽,已被自动停用 | 调高该 Key 的额度上限,或等额度周期重置 | |
| key_expired | API Key 已超过有效期 | 换新 Key,或延长有效期 | |
| permission_denied | 当前账号无权访问该资源 | 确认账号权限后重试 | |
| model_not_allowed | API Key 的模型白名单不含该模型 | 为 Key 添加模型授权,或改用已授权模型 | |
| ip_not_allowed | 请求来源 IP 不在该 Key 的 IP 白名单内 | 从 IP 白名单内的机器发起调用,白名单可在门户「API 密钥」编辑;经公网域名调用时填调用方公网出口 IP,本机调试可填 127.0.0.1 | |
| insufficient_user_quota | 可用余额不足,低于本次请求/任务的预估扣费(进行中的请求与任务会占用可用额度) | 错误信息中附有可用余额、结算中金额与本次预估的具体数字;等在途任务结算释放额度,或到门户充值后重试 | |
| 404 | model_not_found | 模型名不存在(平台未配置该模型) | 核对模型名,以模型广场列表为准 |
| not_found | 请求的资源不存在(账单、对象等) | 核对资源 ID 与请求路径 | |
| task_not_exist | 异步任务不存在或已被过期清理 | 检查任务 ID,必要时重新提交任务 | |
| 409 | conflict | 资源状态冲突 | 查询资源当前状态后再操作 |
| duplicate_request_id | 请求头 X-Request-Id 的值与之前某次请求重复 |
换一个新的值重发;不传该请求头时由平台自动生成,不会遇到此错误 | |
| 413 | request_too_large | 请求体超过大小上限(默认 32MB) | 精简请求内容;大文本改用文件/URL 引用,图片避免 base64 内联 |
| 415 | unsupported_media_type | Content-Type 不支持 | 请求头改用 application/json |
| 422 | no_routable_channel | 模型存在,但平台当前无法为它提供服务,短时间内不会自行恢复 | 若请求中带有供应商类限制参数(指定只用某些供应商、排除某些供应商、价格上限),请放宽后重试;否则联系管理员 |
| content_policy_violation | 内容未通过平台合规审核或上游安全系统拦截(平台合规审核的原因见 error.param;上游拦截请调整提示词措辞) |
修改提示词内容后重发 | |
| 429 | rate_limit_exceeded | 每秒请求数超过 Key 的 QPS 配额(令牌桶限速,允许 2×QPS 的瞬时突发) | 按 Retry-After 退避后重试;频繁出现说明速率超出配额,可降低调用频率 |
| concurrency_limit_exceeded | 同时进行中的请求数(含未结束的流式连接)超过 Key 的并发配额,请求完成后名额立即释放 | 等部分在途请求结束后再发新请求 | |
| upstream_rate_limit_exceeded | 上游服务限流(响应带 X-Upstream-Error-Category 头) |
按 Retry-After 给出的秒数等待后重试 |
|
| tenant_quota_exceeded | 账户的每日 / 每月 token 用量达到上限 | 按 Retry-After(距配额周期重置的剩余秒数)等待,或联系管理员调高上限 |
|
| global_rate_limit_exceeded | 平台整体过载,触发系统级保护 | 按 Retry-After 等待后重试;持续出现说明平台容量告急 |
|
| temporarily_unavailable | 该模型当前繁忙,通常几十秒内自动恢复 | 按 Retry-After 给出的秒数等待后重试;主流 SDK 会自动完成退避重试,无需人工干预 |
|
| 499 | client_disconnected | 调用方提前断开连接(超时/手动停止/链路断),上游调用被联动取消——上游本身正常 | 检查调用端超时设置(推理模型建议 ≥120s);手动停止属正常行为 |
| 500 | internal_error | 服务内部错误 | 等 2~5 秒重试;持续失败带 Request ID 反馈 |
| 502 | upstream_error | 上游服务返回错误 | 等几秒重试;持续失败联系管理员检查渠道 |
| 503 | all_channels_unavailable | 所有渠道不可用(熔断或维护中) | 等渠道恢复,通常几分钟内 |
| 504 | upstream_timeout | 上游响应超时 | 等几秒重试;长请求建议改用流式 |
重试建议
-
可重试:429 与 5xx
每次失败后把等待时间翻倍再试(如 1 秒 → 2 秒 → 4 秒…),不要反复硬撞;重试两三次仍失败就停止。若响应带
Retry-After头,按它指定的秒数等待,优先于自行估算。 -
不可重试:4xx 客户端错误
400 / 401 / 403 / 404 / 409 / 415 表示请求本身需要修正,反复重试只会持续失败;按
error.code对照上表处理后再发送。422 视错误码而定,见上表。 -
排查技巧
curl 命令加
-i查看完整响应头与原始返回;带上响应中的X-Request-Id头反馈问题,可精确定位到单次调用(使用日志详情中的 Request ID 与之一致)。
常见问题
加载中…