平台扩展与差异
平台层面与具体模型无关的行为:请求头、响应头、自动重试、限流、自定义字段,以及与官方 API 的已知差异
这一页只写平台层面、与具体模型无关的行为,按代码当前实际情况整理。各模型自己的参数和限制见对应的模型页面。标注「可能变化」的条目是已知的待改项,以实际返回为准。
支持的端点
| 能力 | 端点 |
|---|---|
| 对话 | POST /v1/chat/completions、POST /v1/messages、POST /v1/messages/count_tokens、POST /v1/responses(含 GET、DELETE、cancel、compact,其中 DELETE 和 cancel 不需要请求体) |
| 向量与重排 | POST /v1/embeddings、POST /v1/rerank |
| 图像 | POST /v1/images/generations、/v1/images/edits、/v1/images/variations,以及各模型的原生图像端点 |
| 语音与审核 | POST /v1/audio/speech、/v1/audio/transcriptions、/v1/audio/translations、POST /v1/moderations,GET /v1/realtime(WebSocket) |
| 视频 | 只在各模型的原生端点提供,/v1/videos* 已下线 |
| 模型 | GET /v1/models、GET /v1/models/{id} |
不提供:Files(/v1/files)、Batch(/v1/batches、/v1/messages/batches)、Fine-tuning、Uploads、Assistants / Threads、旧版 /v1/completions。这些路径没有对应的处理器,返回纯文本 404 page not found;如果是带 JSON 请求体的 POST 且体内没有 model,会先收到 400(missing model field)。各端点各自支持哪些参数,以对应页面为准。
请求头
鉴权
只认 Authorization: Bearer <Key>(Bearer 不区分大小写)。x-api-key 头和 URL 里的 ?key=、?api_key= 都不被接受,返回 401。唯一的例外是浏览器发起的 WebSocket 升级请求(Realtime),它不能自定义请求头,可以用 api_key 查询参数。
因此 Anthropic SDK 必须用 auth_token(发送 Authorization),不能用 api_key(发送 x-api-key)。
Key 的格式要求与失效规则见获取 API Key。
网关转发给上游的客户端头
网关只转发下面这些头,其余全部丢弃:
| 头 | 说明 |
|---|---|
Authorization | 用于平台鉴权,不会原样交给模型厂商 |
Content-Type、Accept、Accept-Encoding、Origin、User-Agent | 协议协商与日志 |
Anthropic-Beta、OpenAI-Beta | 显式的功能开关,转发后与平台内部的判断合并 |
不转发的头包括:anthropic-version(由平台按上游自己的配置设置,你传什么都不起作用)、Idempotency-Key、OpenAI-Organization、OpenAI-Project,以及你自定义的任何头。身份、计费、路由相关的头都是平台自己注入的,客户端传同名的头没有效果。
其他请求头行为
X-Request-ID:你传了就沿用并在响应里原样回显,没传则平台生成一个 UUID。- 路径里重复的
/v1/v1/会折叠成/v1/。有些客户端的base_url已经带了/v1,再拼接/v1/...也能用。 - 浏览器跨域:公网入口只对平台自有站点的域名返回 CORS 放行头,从其他网页直接用 Key 调用会被浏览器拦截。这也是不要把 Key 放进前端的原因之一。
响应头
X-Request-ID:每个响应都带。报问题时附上它。Retry-After(秒):平台自己只在两种响应上设置它,一是 Key 触发 RPM/TPM 限流的429(被 TPM 限流时,它可能比实际需要等待的时间短),二是网关并发已满的503(固定5)。其余错误都没有。- 平台不返回
x-ratelimit-*系列头,也没有余额类响应头。要知道自己的限额,看控制台或联系管理员。 - 流式响应:
Content-Type: text/event-stream,并带Cache-Control: no-cache和X-Accel-Buffering: no。
流式响应里的心跳
SSE 流每隔约 15 秒会插入一行 : heartbeat 注释帧(以冒号开头),用来在模型长时间思考、没有输出时保持连接。标准 SSE 客户端和官方 SDK 会忽略它;自己写解析器的话,请忽略以 : 开头的行。
自动行为
自动补 include_usage
请求体里 stream 为 true 且没有 stream_options 字段时,平台会补上 {"include_usage": true},使流的最后一个数据块带用量。你自己传了 stream_options,平台不会改它(包括你没写 include_usage 的情况)。
重试与切换上游
- 同一个模型有多个上游候选时,请求在收到第一个字节之前失败,平台会自动切换到下一个候选,直到候选用尽,再把最后一个上游的错误返回给你。
- 当前的默认策略下,除「上下文超长」外,几乎所有失败都会触发切换,包括连接、超时、
5xx、429,也包括上游返回的400、401、403(可能是该上游特有的问题)。可能变化。 - 只有一个上游的模型没有可切换的对象,上游失败就直接返回错误。
- 流式响应已经开始(已经有数据发给你)之后不再切换、不再重试,失败写进流里,见错误码。
- 失败的尝试不计费,你只会为最终成功的那一次付费。平台没有幂等键,你自己重试是一次新的请求。
- 平台不会自行把请求换成另一个模型。
上游限流(429)后的行为
- 上游对某个模型返回
429,只影响这个模型。同一厂商下的其他模型照常服务,不会因为一个模型被限流而一起不可用。 - 该模型还有别的上游候选时,被限流的上游会暂时不再接收请求,请求由其他候选服务,对你来说没有变化。
- 该模型只有一个上游(或所有上游同时被限流)时,平台不会让它整段时间都不可用:每隔几秒会放行一个请求去试探,上游恢复后立刻恢复服务。试探间隔内的其他请求直接得到
429,而不是503。 - 这种
429的含义是「稍后再试」。请自行退避重试(例如等待几秒并逐步加长),不要在收到后立即高频重发。 - 仅当上游明确表示整个账号的额度已用尽时,才会让该厂商下的模型一起暂停。
超时
- 流在默认 4 分钟没有任何数据后会被断开(部署可调)。
- 网关等不到响应头 120 秒会返回
502;生成时间可能超过两分钟的非流式请求请改用stream: true。 - 请求体要在 30 秒内传完。
任务 ID 与响应 ID
视频任务的 id(以 video_ 开头)和 Responses 的 id(通常以 resp_ 开头)是平台签发的不透明令牌,里面编码了处理该任务的上游和模型。请原样保存和使用,不要解析、截断或修改,也不要和上游厂商的原始 ID 混用。令牌可能很长,存储时不要限制过短的长度。
限流与余额
限流
- 默认档位是每个 Key 每分钟 60 次请求(RPM)、100 万 token(TPM)。实际生效的值取组织档位、团队限额和 Key 自己的覆盖值三者的最小值,档位由管理员配置,以你的账户为准。
- 超限返回
429,message固定为too many requests,不区分是 RPM 还是 TPM。 - TPM 限流只统计你在
messages里发送的文本,图片等附件和模型输出都不计入。不使用messages的请求(例如 Responses 和 Embeddings 的input)只受 RPM 约束。 GET /v1/models和 Realtime 会话不走 RPM/TPM 限流;Realtime 有单独的并发会话上限,超出返回429(没有Retry-After)。- 公网入口的 nginx 另有按来源 IP 的限速,触发时返回 HTML 的
429,见错误码。
余额与结算
- 如果你的余额不足以支撑所发送的请求,平台会直接返回
402,不会发给模型。余额接近用完时,把max_tokens设得很大,即使实际输出很短,也可能被402拒绝;调低它或先充值。 - 实际扣费在请求结束后按真实用量结算。失败且没有用量的请求不扣费;流式中途失败的,已经生成的部分按实际用量计费。
- 余额耗尽后,只有会产生费用的请求返回
402;GET /v1/models、视频任务与响应的查询、DELETE /v1/responses/{id}和cancel这类只读或免费请求仍然可用。 - 流式输出进行中余额耗尽,平台会切断流,并写入
data: {"error":{"type":"insufficient_quota","message":"balance exhausted"}}和data: [DONE]。 - 如果设置了预算额度(Key、成员或团队级别),用完同样返回
402,message里带(budget envelope: ...)。 - 账户有折扣时,
usage.cost是折后的实际扣费金额。折扣对所有计费端点生效(对话、图片、嵌入、重排、音频、视频等),不只是对话。
默认限制一览
下面是代码里的默认值,部署可能调整;以实际部署为准。
| 项 | 默认值 |
|---|---|
| 请求体上限(网关) | 50 MB,按 Content-Length 判断 |
| 请求体上限(公网入口 nginx) | 25 MB |
| 请求读取时限 | 30 秒 |
| 网关并发 | 500 路上游请求,排队最多 10 秒 |
| 等待响应头 | 120 秒 |
| 上游调用总时限 | 非流式 10 分钟,流式 5 分钟 |
| 流空闲断开 | 4 分钟没有数据 |
| 单 Key 限流 | 60 RPM,100 万 TPM(标准档) |
平台自定义字段
响应:usage.cost 与 usage.cost_details
usage 里可能出现两个官方 API 没有的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
usage.cost | 小数字符串,例如 "0.00002618" | 本次请求实际扣费的总额 |
usage.cost_details | 对象,值为小数字符串 | 按计价维度的明细,只含有费用的维度,加起来等于 cost |
规则:
- 没有请求参数可以打开它。是否出现取决于账户设置:默认都不返回;组织可以设为只返回
cost,或同时返回明细;成员的设置不能高于组织。 - 请求无法计价时两个字段都不出现(不是
0,也不是null)。 - 金额是字符串,token 数是数字。
- 平台不会返回上游成本、折扣率、牌价或命中的阶梯。
- 目前确认带这两个字段的位置:
/v1/chat/completions(非流式,以及流式里带用量的最后一个数据块)、/v1/responses(非流式),以及图片端点/v1/images/generations、/v1/images/edits、/v1/images/variations、/api/v3/images/generations,和返回图片时的 DashScope 风格端点/api/v1/services/aigc/multimodal-generation/generation。其他端点不带,Responses 流式是否带以实际返回为准。 - 图片:两个字段位于响应的
usage里。模型自己的响应没有usage对象时,会出现一个只含cost(账户设为返回明细时还有cost_details)的usage,且仅在有金额可返回时才出现;响应的其余内容不变。默认设置下,图片响应与模型返回的完全一致。图片的cost_details键名:output_image_cost(按生成的图片张数),输入图片收费时有input_image_cost。 - 视频:组织设为返回费用时,已完成任务的轮询(Seedance、MiniMax、HappyHorse/万相的任务查询端点)带
usage.cost,即实际扣费总额;视频没有明细。创建任务的响应不带费用;默认设置下轮询与原来完全一致:视频一生成好就报告已完成。设为返回费用时,已完成的任务在费用入账之前会继续显示为进行中、且不带结果链接,通常需要几分钟,最长约 5 分钟;超过后任务显示为已完成但不带cost,之后的轮询在费用就绪后会带上。已完成却没有cost,表示金额未给出,不表示免费。如果你的客户端对任务有固定的超时,设为返回费用时请多留最多 5 分钟。任务实际扣了多少,也可以看控制台里的用量记录。 cost_details的键名在 Chat Completions 里是prompt_cost、completion_cost、reasoning_cost、prompt_cache_read_cost等;Responses 里输入和输出分别叫input_cost、output_cost,其余同名。- 金额以美元计,与账户余额扣费所用的币种一致。
另外,上游在响应里给出的任何费用、价格、额度或余额类字段(无论在 usage 里还是响应顶层)都会被平台去掉,所有端点一致,流式也一样。响应里唯一的费用数字是平台自己的 usage.cost 和 usage.cost_details。
与官方 API 的已知差异
下面是当前的事实,其中带「可能变化」的是已知的待改项。
| 位置 | 差异 |
|---|---|
/v1/messages 的错误 | 网关层与路由层的错误都是 Anthropic 风格 {"type":"error","error":{...}},type 用 Anthropic 官方名称(余额不足为 billing_error) |
| Responses 的转换路径 | 上游不原生支持 Responses 时,平台把对话结果转换成 Responses 事件。转换后的事件带 sequence_number,id 以 resp_ 开头,响应对象回显请求参数,思考用官方的 summary 结构(流式与非流式一致),output 里思考在前、output_index 按出现顺序。仍有的差异:function_call 项的 id 与 call_id 相同(官方是 fc_… 与 call_…);拒答(refusal)内容块用 text 而不是官方的 refusal 字段;流式不发 response.output_text.annotation.added、不带 logprobs;回显的 store、truncation、previous_response_id 等只是请求回显,转换路径并不执行。上游原生支持时与官方一致。可能变化 |
Anthropic 流式 message_start | 其中的 usage 取自第一个数据块,上游较晚给用量时可能是 0;message_delta 里的用量是完整的。只读 message_start 的客户端会看到 0 |
GET /v1/models | created 是固定值,owned_by 固定为 modelsite,不含能力与价格 |
| Key 级别的模型限制 | 不支持,只能用团队白名单 |
anthropic-version 头 | 被忽略 |
如果你发现的行为和本页或官方文档都对不上,带上响应里的 X-Request-ID 联系支持。