Messages(Anthropic 格式)
POST /v1/messages 与 count_tokens 的接入、请求转发方式、流式事件、计费与错误格式。
更新于 2026-10-25·阅读约 15 分钟
httpPOST https://api.scirouter.cn/v1/messages
POST https://api.scirouter.cn/v1/messages/count_tokens请求与响应格式与 Anthropic Messages API 一致。Anthropic SDK、Claude Code 等按 Anthropic 格式发送请求的客户端,替换 base URL 与 Key 即可调用。平台上的所有对话模型均可通过此接口调用;模型的线路没有 Anthropic 入口时,网关转换请求并尽量保留内容,见请求的转发方式。
接入
#Anthropic SDK 与 Claude Code 会在 base URL 后拼接 /v1/messages,因此 base URL 为 https://api.scirouter.cn,不带 /v1。Key 为控制台创建的 API Key,携带方式见认证与 API Key。
Python:
pythonimport os
import anthropic
client = anthropic.Anthropic(
api_key=os.environ["SCIROUTER_API_KEY"],
base_url="https://api.scirouter.cn", # SDK 自己会拼 /v1/messages
)
msg = client.messages.create(
model="YOUR_MODEL_ID",
max_tokens=1024,
messages=[{"role": "user", "content": "这段序列的二级结构倾向?"}],
)
print(msg.content)TypeScript:
typescriptimport Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
apiKey: process.env.SCIROUTER_API_KEY,
baseURL: 'https://api.scirouter.cn',
})
const msg = await client.messages.create({
model: 'YOUR_MODEL_ID',
max_tokens: 1024,
messages: [{ role: 'user', content: '这段序列的二级结构倾向?' }],
})curl:
bashcurl https://api.scirouter.cn/v1/messages \
-H "x-api-key: $SCIROUTER_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_ID",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "这段序列的二级结构倾向?"}]
}'anthropic-version 可省略,默认值见请求头。
Claude Code
#Claude Code 的安装、settings.json 写法、环境变量与使用要点见 Claude Code。
请求
#| 字段 | 必填 | 说明 |
|---|---|---|
model | 是 | 平台的模型 id,也可填写平台为该模型配置的别名(如厂商官方的模型名)。名称末尾带 -YYYYMMDD 日期时,去掉日期后查找。响应中的 model 为解析后的平台模型 id |
max_tokens | 是 | 非负整数,处理方式见 max_tokens |
messages | 是 | 不能为空。role 可为 user、assistant,以及对话中途的 system(Claude Code 每个请求都带一条) |
stream | 否 | true 时为流式,见流式响应 |
tools | 否 | 见工具 |
metadata | 否 | 不转给上游 |
| 其他字段 | 否 | 按线路处理,见请求的转发方式;各参数无法带到线路上时的处理见参数如何被处理 |
请求体上限为 32 MB(对话补全为 4 MB),超过时返回 413 payload_too_large。
max_tokens
| 情况 | 平台的处理 |
|---|---|
| 超过模型或套餐的单次输出上限 | 按上限发出,在响应头 X-SciRouter-Max-Tokens-Clamped 与 scirouter.max_tokens_clamped 中写明请求值、实际发出的值与生效的上限,不静默截短。此时 thinking.budget_tokens 若不小于发出的值,一并降为该值减 1(厂商要求思考预算小于 max_tokens) |
| 输入估算本身超过套餐的每分钟 token 数 | 返回 400 invalid_request_error(error.code 为 validation_failed,details.reason 为 plan_tpm_exceeded)。message 以 prompt is too long: N tokens > M maximum 开头(N 为输入估算,M 为套餐每分钟上限),末尾带 capability_rejected: prompt_too_long,Claude Code 据此尝试自动压缩对话后重发(压缩请求本身也超过上限时压缩失败,需 /clear 或升级套餐),见错误码。max_tokens 写多大都不因每分钟 token 数被拒:它只按输出预留计入,结束后按实际用量结算 |
值为 0 | 只预热厂商的提示词缓存,不生成。只走 Anthropic 入口,模型的线路都没有 Anthropic 入口时返回 400,见无法转发的内容 |
输入加 max_tokens 超过模型的上下文窗口 | 400 context_window_exceeded,见参数如何被处理「上下文窗口」 |
对话补全接口的 max_tokens 超限返回 400,与本接口不同。
工具
#| 工具 | 处理 |
|---|---|
| 自定义工具 | 照常使用 |
advisor 工具(advisor_*) | 只走 Anthropic 入口。其 model 须为平台上有定价的模型(正式 id 或别名),否则返回 400 validation_failed,details.reason 为 sub_model_unpriced;调用方须有该模型的调用权限,否则与直接调用一样返回 403。子推理按该模型的价格另行计费,见计费 |
厂商的服务端工具(web_search_*、web_fetch_*、code_execution_*、tool_search_tool_*、mcp_toolset)与 mcp_servers、container | 不支持,返回 400 validation_failed,details.reason 为 server_tool_unsupported |
请求的转发方式
#模型背后的每条线路对应同一个上游账号,可接入多种协议,每种协议是线路的一个入口(见多厂商差异「字段生效规则」)。Anthropic 格式的调用在一条线路上按以下顺序处理,前一级无法处理时进入下一级:
| 级别 | 条件 | 处理 |
|---|---|---|
| 1. 原样转发 | 线路有 Anthropic 入口 | 请求原样转发,只修改少数几处 |
| 2. 转换 | 线路没有 Anthropic 入口 | 转为主入口的协议后调用,扩展字段能携带的内容均带上 |
| 3. 降级 | OpenAI 格式中没有对应概念的块 | 改写为等价的文字或普通工具,内容不丢失 |
| 4. 返回 400 | 无法用文字表达的内容 | 见无法转发的内容 |
每一级去掉或改写的内容记录在响应头 X-SciRouter-Param-Actions 与扩展块 param_actions 中(dropped / reshaped)。
原样转发
#线路有 Anthropic 入口时,请求原样转发,只修改以下几处:
model换成上游的模型名;- 去掉
metadata; max_tokens写入生效值;- 按平台的提示词缓存策略处理
cache_control断点; - 去掉签名为空的思考块。这类块来自其他模型的思考过程,厂商会因签名无效拒绝整个请求。
厂商自定义参数、思考块与签名、文档块、anthropic-beta 均到达上游,响应原样返回。「原样」指请求的格式与字段:鉴权、计费、限额与线路选择仍由平台完成,发给厂商的 x-api-key 是平台在该厂商的凭据,调用方的 SciRouter Key 不会到达厂商。
转换
#线路没有 Anthropic 入口时,网关将请求转为主入口的协议后调用,再将结果转回 Anthropic 格式。只保留能对应的字段:
| 内容 | 转换方式 |
|---|---|
| 内容块 | 可转换 text、image、document(PDF、纯文本)、tool_use、tool_result、thinking、redacted_thinking |
| 工具结果中的图片 | 移入紧随其后的用户消息,并标注来自哪个工具调用 |
对话中途的 system 消息 | 在原位置成为一条 system 消息 |
system 第一块为 Claude Code 的归因块(x-anthropic-billing-header: …) | 去掉(Anthropic 的接口同样去掉该块) |
cache_control 断点 | 上游支持内容块上的 cache_control 时带上断点 |
| 思考块的签名 | 按线路配置,以上游支持的扩展写法连同签名带上 |
anthropic-beta | 按线路配置转发 |
thinking | 按模型的思考控制翻译为该线路的写法;模型没有思考能力时去掉并留痕 |
top_k | 带给支持它的线路 |
speed 等计价参数 | 不带 |
context_management | clear_tool_uses_* 由平台在转换后的历史上补实现(保留最近几次工具调用,更早的工具结果换成占位);compact_* 等其余编辑去掉并留痕 |
document 块 | 转为该线路的文件内容段 |
output_format / output_config.format 的 JSON Schema | 转为 response_format;模型没有原生结构化输出时由平台模拟 |
| 输出上限 | 按该线路支持的字段名写入 |
cache_control 断点、思考块的签名与 anthropic-beta,线路未配置的不带并留痕。字段对照见多厂商差异与参数如何被处理。
转回的响应与原生响应的差异:
| 项 | 差异 |
|---|---|
流式的 message_start.usage | 为 0,真实用量在 message_delta.usage 中 |
| 工具调用 | 在流的末尾整块发出,参数完整 |
| 命中停止序列 | stop_reason 为 end_turn,stop_sequence 为 null(OpenAI 格式不报告命中的是哪一条) |
| 上游给出 Anthropic 没有的结束原因 | 原样写入 stop_reason(如 insufficient_system_resource),不视为正常结束 |
| 思考签名 | 上游经扩展字段返回的思考签名,还原为带签名的 thinking 块 |
多轮工具调用时,将上一轮的思考块原样带回。平台优先将请求发回签发该签名的线路;落到其他线路时签名可能无效,厂商返回 400,平台原样交回该错误。
降级
#OpenAI 格式中没有对应概念的块,改写为等价的文字或普通工具。内容完整保留,只缺少厂商对这些块的专门处理:
| 原内容 | 改写为 |
|---|---|
search_result | 带来源与标题的文本块 |
文档块的 citations / context | 文字说明 |
Anthropic 定义的客户端工具(bash_* / text_editor_* / computer_*) | 同名的普通函数工具 |
非文本的 system 块 | 并入第一条用户消息 |
历史中的服务端工具结果(web_search_tool_result / web_fetch_tool_result) | 带标题与来源的文本;server_tool_use 去掉 |
每条改写在 param_actions 中记为 reshaped。带这些内容的请求,模型有带 Anthropic 入口的线路时一定走该线路(优先于权重与粘性),没有时才降级。
无法转发的内容
#以下内容无法用文字表达:
- Files API 来源的文件与图片(文件在厂商侧,平台无法获取);
- 按需压缩
compaction; max_tokens: 0;- 非 JSON Schema 的输出格式;
- 没有可提取文字的块与工具(代码执行结果、
memory_*等)。
模型没有带 Anthropic 入口的线路时,返回 400 unsupported_param,details.reason 为 unsupported_content,details.unsupported_content 列出相应内容(如 ["document:file", "param:compaction"])。平台不会丢弃这些内容后作答。该错误由请求内容引起,重试无效。
响应
#非流式:
json{
"id": "msg_…",
"type": "message",
"role": "assistant",
"model": "YOUR_MODEL_ID",
"content": [{ "type": "text", "text": "…" }],
"stop_reason": "end_turn",
"usage": { "input_tokens": 42, "output_tokens": 318 },
"scirouter": { "request_id": "req_…", "attempts": 1, "cost_quota": 18240, "…": "…" }
}数值为示例。
顶层的 scirouter 是平台的扩展块,内容与对话补全相同,SDK 忽略该字段。单次调用扣除的配额见 scirouter.cost_quota。
流式响应
#请求带 "stream": true 时按 Anthropic 的事件格式发送:每条事件带 event: 行,事件类型与 Anthropic 相同(message_start、content_block_delta……message_stop)。与对话补全的流式响应的差异:
- 没有
data: [DONE],流以message_stop结束。平台在结算后才发送message_stop,其中多一个scirouter字段(含本次的cost_quota)。 - 开始输出后出错时,发送一个
event: error事件(内容为错误中的错误体),随后断开。未收到message_stop即结束的流按失败处理。 - 流中有以
:开头的心跳注释行,SDK 自动忽略。
非流式请求最长等待约 270 秒,超时返回 504 upstream_timeout(details.timeout 为 response),不计费;回答可能很长时使用流式,见 SDK 与框架「重试与超时」。
计费
#按厂商返回的 usage 结算,口径与厂商一致:input_tokens、cache_read_input_tokens、cache_creation_input_tokens(含 5 分钟与 1 小时两档写入)分别按各自的单价计费;思考 token 包含在 output_tokens 中,按输出单价计费。
厂商将一次请求中的多次采样拆分在 usage.iterations 中时(服务端压缩 context_management 的 compact_* 编辑、按需压缩 compaction、advisor 工具、fallbacks 回退),按 iterations 逐条计费:
| 迭代 | 计费 |
|---|---|
| 本模型的迭代(含压缩) | 并入本次用量 |
| advisor 子推理、回退模型的迭代 | 按该模型在平台上的价格另行计费 |
scirouter.cost_quota 为合计。fallbacks 写成模型列表时,每个模型都须在平台上有定价且调用方有权调用,否则返回 400 sub_model_unpriced;写 "default" 时由厂商选择模型,按其返回的模型结算。
错误
#/messages 与 /messages/count_tokens 的错误使用 Anthropic 的格式,鉴权失败与路径或方法错误(404 / 405)也是如此:
json{
"type": "error",
"error": {
"type": "rate_limit_error",
"message": "请求过于频繁,请稍后再试",
"code": "rate_limited",
"details": { "retry_after_seconds": 12 }
},
"request_id": "req_88a1"
}- 状态码与对话补全逐码相同,
error.code使用同一套小写错误码,按error.code分支处理,对照见错误码。 error.type按状态码给出;配额、权限、Key 状态等策略拒绝例外,见下表。
平台拒绝请求时的标记:
| 标记 | 出现条件 | Claude Code 的处理 |
|---|---|---|
message 末尾带 capability_rejected: <class> | 平台自身拒绝、关闭对应能力即可恢复的 400(结构化输出、思考强度、图片、文档、超长等) | 关闭该能力后重发 |
error.type 为 policy_blocked,带 x-should-retry: false | 配额、权限、Key 状态等策略拒绝 | 直接展示,不重试 |
message 为 prompt is too long: N tokens > M maximum 的格式 | 上下文超长 | 见 Claude Code「上下文窗口」 |
计价参数与模型变体
#部分参数会使厂商按另一档单价计费。计价参数由平台配置,当前为走 Anthropic 入口时的以下参数:
| 参数 | 按另一档计价的取值 |
|---|---|
speed | standard 以外的值 |
inference_geo | 任意取值 |
service_tier | auto、standard_only 以外的值 |
模型的线路都没有 Anthropic 入口时,这些参数无法带到线路上,不做检查。请求带有计价参数时:
| 情况 | 结果 |
|---|---|
平台已上架覆盖这些参数的模型变体(id 格式为 厂商/模型名:fast) | 自动改用变体,按变体的价格结算。响应中的 model 为变体的 id,响应头 X-SciRouter-Variant-Switch 列出触发的参数(逗号分隔) |
| 没有对应的变体 | 400 validation_failed,details.reason 为 price_param_unsupported,details.params 列出参数 |
也可直接将 model 设为变体的 id,或在别名后加后缀(别名:fast)。模型的变体、各变体强制的参数与自动改用的格式,见模型中心的详情页或 GET /models 扩展字段中的 variant_params 与 variant_switch_formats(见模型列表)。对话补全(OpenAI 格式)默认只记录,不改用变体。
统计 token 数
#bashcurl https://api.scirouter.cn/v1/messages/count_tokens \
-H "x-api-key: $SCIROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_ID",
"messages": [{"role": "user", "content": "这段序列的二级结构倾向?"}]
}'json{
"input_tokens": 1834,
"scirouter": { "model": "YOUR_MODEL_ID", "estimated": false, "request_id": "req_…" }
}数值为示例。
| 项 | 说明 |
|---|---|
| 请求体 | 与 /messages 相同,不需要 max_tokens。context_management 原样转给厂商,计数结果为裁剪后、实际计费的上下文。可携带 mcp_servers 中的平台托管工具声明,与 /messages 一样摘除后计数 |
| 授权与限频 | 模型解析与授权与正式调用相同,计入一次每分钟请求数 |
| 计费与日志 | 不计费,不进入请求日志 |
| 计数方 | 模型有带 Anthropic 入口的可用线路时由厂商计数;没有、厂商 5 秒内未响应或报错时由平台估算(同一条线路故障后约 1 分钟内直接估算),此时 scirouter.estimated 为 true |
模型列表
#GET /models 与 GET /models/{id} 带 anthropic-version 请求头时,按 Anthropic 的格式返回(Claude Code 与 Anthropic SDK 列出模型时会携带):
json{
"data": [{ "type": "model", "id": "YOUR_MODEL_ID", "display_name": "…", "created_at": "2026-09-01T00:00:00Z" }],
"has_more": false,
"first_id": "YOUR_MODEL_ID",
"last_id": "YOUR_MODEL_ID"
}一次返回全部模型,has_more 恒为 false;查询单个模型时也接受别名。不带该请求头时按 OpenAI 的格式返回,见模型列表。
请求头与响应头
#请求头
#| 请求头 | 取值 | 说明 |
|---|---|---|
x-api-key | API Key | 携带 Key 的另一种方式,见认证与 API Key |
anthropic-version | 如 2023-06-01 | 走 Anthropic 入口时透传给上游,不带时默认为 2023-06-01;线路可按配置改成别的值,改了请求里带的值时记在控制台调用记录的「请求参数」里(param 为 anthropic_version)。在 /models 上决定返回哪种格式 |
anthropic-beta | beta 名称 | 可写多个请求头或逗号分隔。走 Anthropic 入口时透传给上游;走其他入口转换时按线路配置转发,默认不转发。线路可按配置去掉其中几项,去掉时记在控制台调用记录的「请求参数」里(scirouter.param_actions 中 param 为 anthropic_beta、reason 为 header_rule) |
anthropic-dangerous-direct-browser-access | — | Anthropic SDK 在浏览器中直连时携带,网关的跨源预检放行该请求头。Key 不应放入浏览器,见认证与 API Key |
X-SciRouter-Unsupported-Params | strict / lenient | strict:提示类参数无法带到线路上时也返回 400;lenient:契约类参数也去掉。见参数如何被处理 |
X-SciRouter-Validate-Schema | 1 | 结构化输出由平台模拟时按 schema 校验结果,写入 scirouter.schema_valid |
响应头
#| 响应头 | 取值 | 说明 |
|---|---|---|
request-id | 与 X-Request-Id 相同 | Anthropic SDK 读取该名称。每个响应都带,包括鉴权与请求体校验失败的响应 |
X-SciRouter-Variant-Switch | 触发的参数 | 请求被自动改用模型变体时出现,见计价参数与模型变体 |
X-SciRouter-Max-Tokens-Clamped | 如 requested=32000; effective=8192; limit=model | max_tokens 超过模型或套餐的单次上限、按上限发出时出现;limit 为 model 或 plan |
X-SciRouter-Param-Actions | 如 dropped=top_k; translated=reasoning | 有参数被去掉、翻译、模拟、整形或自愈时出现,见参数如何被处理 |
x-should-retry | false | 本次错误重试无效(不带 Retry-After 的 503,以及 policy_blocked 的策略拒绝,见错误码)。Anthropic SDK 与 Claude Code 收到后不再自动重试 |
其余 X-SciRouter-*、x-ratelimit-* 响应头与对话补全相同,见可观测性。
缓存、幂等与重试
#Idempotency-Key 与平台响应缓存的规则与对话补全相同,见缓存与幂等。
Anthropic SDK 默认自动重试 429 与 5xx,不检查 error.code,但先检查 x-should-retry:平台判定重试无效的 503 与策略拒绝(policy_blocked)带 x-should-retry: false,SDK 与 Claude Code 收到后不再重试。可重试的错误见错误码。