客户端 HTTP API
本规范描述客户端与 ScootGate API listener 的当前 HTTP 契约。
通用要求
- 传输:HTTP/1.1;生产环境使用 TLS 1.2+;
- 每个 API listener 请求都必须鉴权,包括
/v1/models; - POST 请求必须带唯一、有效的
Content-Length; - JSON 请求体大小受
api.max_request_body_bytes限制; - 每个响应使用
Connection: close; - 未声明的路径返回 404,不存在管理 API。
鉴权
支持两种请求头:
Authorization: Bearer <scootgate-client-key>
x-api-key: <scootgate-client-key>
两者同时出现时,有效 Bearer 值优先。key 缺失、未知或已吊销时:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Content-Type: application/json
{"status":"unauthorized"}
客户端 key 只用于 ScootGate 鉴权,不会转发给 Provider。
支持的端点
| 方法 | 路径 | 协议 |
|---|---|---|
POST | /v1/chat/completions | OpenAI-compatible |
POST | /v1/messages | Anthropic Messages |
GET | /v1/models | OpenAI-compatible 模型目录 |
路径存在但方法错误时返回:
{"status":"method_not_allowed"}
状态码为 405。
GET /v1/models
只列出已启用的 OpenAI-compatible 公共模型。Anthropic 模型、backend ID、 真实模型名和 Provider origin 不会出现。
响应示例:
{
"object": "list",
"data": [
{
"id": "chat-fast",
"object": "model",
"owned_by": "scootgate"
}
]
}
POST /v1/chat/completions
请求体必须是 JSON object,并包含字符串 model:
POST /v1/chat/completions HTTP/1.1
Authorization: Bearer demo-client-key
Content-Type: application/json
Content-Length: 67
{"model":"chat-fast","messages":[{"role":"user","content":"ping"}]}
ScootGate 选择 openai_compatible target,把公共 model 改写为真实模型名,
保留其他 JSON 字段,然后注入 backend credential。
当 stream: true 时要求 target 支持 stream,并透明转发 Provider SSE。
POST /v1/messages
请求体同样必须包含字符串 model:
POST /v1/messages HTTP/1.1
x-api-key: demo-client-key
anthropic-version: 2023-06-01
Content-Type: application/json
Content-Length: 85
{"model":"claude-fast","max_tokens":32,"messages":[{"role":"user","content":"ping"}]}
只选择 anthropic_messages target。anthropic-version 与 anthropic-beta
会转发给 Provider;客户端 x-api-key 会被 backend credential 替换。
能力过滤
ScootGate 从请求体推导所需能力:
| 请求字段 | 所需能力 |
|---|---|
"stream": true | supports_stream |
非空 tools(或非 array 值) | supports_tools |
response_format.type == "json_schema" | supports_json_schema |
模型存在但没有 target 同时满足能力时返回 400,不会出网。
请求头转发
客户端请求头采用 allowlist。只可能转发:
Content-TypeAcceptanthropic-versionanthropic-beta
ScootGate 重建 request line、Host、Provider 鉴权、Content-Length 与
Connection。客户端 Authorization、x-api-key、Host、代理头和其他
自定义头不会转发。
Provider 响应
除以下特殊处理外,ScootGate 转发 Provider 状态码、响应头和 body:
- 移除
Connection、Keep-Alive、Proxy-Connection,Proxy-Authenticate与TE; - 添加
Connection: close; - Provider 401/403 不原样返回:backend 被停用,客户端收到 502;
- Provider 429 原样返回,并让 backend 进入短暂冷却;
- SSE 按字节增量转发;客户端断开会关闭 Provider tunnel;
- Provider body 超过
stream_idle_timeout_ms无数据时结束 relay。
网关错误
通用错误 body
| 状态 | body | 场景 |
|---|---|---|
| 400 | {"status":"bad_request"} | HTTP 头或 framing 不合法 |
| 401 | {"status":"unauthorized"} | key 缺失/未知/吊销 |
| 404 | {"status":"not_found"} | 未知路径 |
| 405 | {"status":"method_not_allowed"} | 方法错误 |
| 411 | {"status":"length_required"} | POST 缺少 Content-Length |
| 413 | {"status":"payload_too_large"} | 请求体超过上限 |
| 502 | {"status":"bad_gateway"} | 出站、TLS、写入、响应头或 Provider 鉴权失败 |
| 503 | {"status":"not_ready"} | snapshot 路由尚未加载 |
| 504 | {"status":"gateway_timeout"} | 响应头预算耗尽 |
OpenAI-shaped 模型错误
无效 JSON、缺少 model、未知模型、能力不支持或无 backend 时使用:
{
"error": {
"message": "model `missing` does not exist",
"type": "not_found_error",
"param": "model",
"code": null
}
}
未知模型为 404;无效请求/能力不足为 400;无可用 backend 为 503。
Anthropic-shaped 模型错误
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "model `missing` does not exist"
}
}
重试语义
ScootGate 不自动重试可能已到达 Provider 的请求。只有在能证明尚未发送
Provider 请求字节时,才可能在 max_pre_send_attempts 范围内改选其他
backend。客户端和外层代理也不应对这些 POST 请求进行无条件自动重试。