# TrafficAPI 调用文档 > **适用版本**: TrafficAPI v0.1.1+ > **文档日期**: 2026-04-09 --- ## 目录 1. [基本信息](#1-基本信息) 2. [认证方式](#2-认证方式) 3. [Claude / Anthropic API](#3-claude--anthropic-api) 4. [Gemini API](#4-gemini-api) 5. [OpenAI 兼容 API](#5-openai-兼容-api) 6. [Antigravity 路由(Claude + Gemini 混合)](#6-antigravity-路由claude--gemini-混合) 7. [公共接口](#7-公共接口) 8. [错误处理](#8-错误处理) --- ## 1. 基本信息 ### 1.1 Base URL ``` https:// ``` ### 1.2 支持的提供商与路由 | 提供商 | 平台标识 | 主要路由前缀 | |--------|----------|-------------| | Anthropic (Claude) | `anthropic` | `/v1` | | Google Gemini | `gemini` | `/v1beta` | | OpenAI | `openai` | `/v1` (兼容层) | | Antigravity (混合) | `antigravity` | `/antigravity` | ### 1.3 支持的模型 **Claude 系列** | 模型名 | 说明 | |--------|------| | `claude-opus-4-6` | Opus 最强版 | | `claude-opus-4-6-thinking` | Opus 扩展思考版 | | `claude-sonnet-4-6` | Sonnet 均衡版 | | `claude-sonnet-4-5` | Sonnet 上一代 | | `claude-sonnet-4-5-thinking` | Sonnet 扩展思考版 | | `claude-haiku-4-5` | Haiku 轻量版 | **Gemini 系列** | 模型名 | 说明 | |--------|------| | `gemini-2.5-flash` | Gemini 2.5 快速版 | | `gemini-2.5-pro` | Gemini 2.5 旗舰版 | | `gemini-2.5-flash-thinking` | Gemini 2.5 思考版 | | `gemini-3-flash` | Gemini 3 快速版 | | `gemini-3-pro-high` | Gemini 3 Pro 高性能 | | `gemini-3-pro-low` | Gemini 3 Pro 经济版 | | `gemini-3.1-pro-high` | Gemini 3.1 Pro 高性能 | --- ## 2. 认证方式 所有 AI 调用接口均通过 **API Key** 鉴权,支持以下三种方式(任选其一): | 方式 | Header/参数 | 示例 | |------|------------|------| | Bearer Token(推荐) | `Authorization` | `Authorization: Bearer sk-xxxxx` | | x-api-key | `x-api-key` | `x-api-key: sk-xxxxx` | | Gemini 兼容 | `x-goog-api-key` | `x-goog-api-key: sk-xxxxx` | > **注意**: API Key 在平台控制台创建,格式通常为 `sk-` 前缀的字符串。 --- ## 3. Claude / Anthropic API 完全兼容 Anthropic 官方 API 格式,可直接使用官方 SDK,只需替换 `base_url`。 ### 3.0 请求参数说明 #### 通用 Header 参数 | Header | 必填 | 说明 | |--------|------|------| | `Authorization` | 是¹ | Bearer 认证,格式:`Bearer sk-xxxxx` | | `x-api-key` | 是¹ | API Key 直接放入 header,与 `Authorization` 二选一 | | `Content-Type` | 是 | 固定为 `application/json` | | `anthropic-version` | 否 | Anthropic API 版本,推荐填写 `2023-06-01` | | `anthropic-beta` | 否 | 开启 Beta 特性,如 `interleaved-thinking-2025-05-14`(扩展思考)、`prompt-caching-2024-07-31`(提示缓存) | | `User-Agent` | 否 | 客户端标识,影响粘性会话(Sticky Session)亲和力 | > ¹ `Authorization`(Bearer)、`x-api-key`、`x-goog-api-key` 三者填一即可。 --- #### `POST /v1/messages` Body 参数 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `model` | string | **是** | — | 模型名称,如 `claude-sonnet-4-6` | | `messages` | array | **是** | — | 对话消息数组,至少一条 | | `messages[].role` | string | **是** | — | 消息角色,`user` 或 `assistant` | | `messages[].content` | string \| array | **是** | — | 消息内容;字符串或内容块数组(支持 `text`、`image`、`tool_use`、`tool_result` 等类型) | | `max_tokens` | integer | **是** | — | 最大输出 token 数,不同模型上限不同(Opus/Sonnet: 32000,Haiku: 8192) | | `system` | string \| array | 否 | — | 系统提示;字符串或内容块数组(支持缓存控制 `cache_control`) | | `stream` | boolean | 否 | `false` | 是否开启 SSE 流式输出 | | `temperature` | number | 否 | `1.0` | 随机性控制,范围 `0.0~1.0`;越低越确定性 | | `top_p` | number | 否 | — | Nucleus 采样概率阈值,范围 `0.0~1.0` | | `top_k` | integer | 否 | — | Top-K 采样,仅保留概率最高的 K 个 token | | `stop_sequences` | array\ | 否 | — | 遇到这些字符串时停止生成 | | `tools` | array | 否 | — | 工具定义列表(Function Calling);每项包含 `name`、`description`、`input_schema` | | `tool_choice` | object | 否 | — | 工具调用策略:`{"type": "auto"}` / `{"type": "any"}` / `{"type": "tool", "name": "..."}` / `{"type": "none"}` | | `thinking` | object | 否 | — | 扩展思考配置(需同时传 `anthropic-beta: interleaved-thinking-2025-05-14`) | | `thinking.type` | string | 否 | — | `enabled`(固定预算)或 `adaptive`(自适应预算) | | `thinking.budget_tokens` | integer | 否 | — | 思考 token 预算,最小 `1024`,推荐 `32000` | | `metadata` | object | 否 | — | 请求元数据 | | `metadata.user_id` | string | 否 | — | 用户标识,用于粘性会话(Sticky Session)路由亲和 | | `output_config` | object | 否 | — | 输出配置 | | `output_config.effort` | string | 否 | — | 推理强度:`low` / `medium` / `high` / `max` | | `context_management` | object | 否 | — | 上下文管理策略(扩展 Beta 功能) | **`tools` 单项结构** ```json { "name": "tool_name", "description": "工具描述", "input_schema": { "type": "object", "properties": { "param1": { "type": "string", "description": "参数说明" } }, "required": ["param1"] } } ``` **响应体结构(非流式)** ```json { "id": "msg_xxxxx", "type": "message", "role": "assistant", "model": "claude-sonnet-4-6", "content": [ { "type": "text", "text": "回复内容" } ], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 25, "output_tokens": 80, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0 } } ``` | `stop_reason` 取值 | 说明 | |-------------------|------| | `end_turn` | 模型正常结束 | | `max_tokens` | 达到 `max_tokens` 上限 | | `stop_sequence` | 命中 `stop_sequences` 中的字符串 | | `tool_use` | 模型请求调用工具 | **SSE 流式事件序列(`stream: true`)** ``` event: message_start # 消息开始,包含 usage 初始值 event: content_block_start # 内容块开始 event: content_block_delta # 内容增量(text_delta / thinking_delta) event: content_block_stop # 内容块结束 event: message_delta # 消息结束,包含最终 stop_reason 和 usage event: message_stop # 流结束标志 ``` --- #### `POST /v1/messages/count_tokens` Body 参数 与 `/v1/messages` 相同,但忽略 `stream` 字段,且不实际调用模型,不计费。 --- ### 3.1 发送消息 `POST /v1/messages` #### Curl ```bash BASE_URL="https://" API_KEY="sk-xxxxx" curl -X POST "$BASE_URL/v1/messages" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-6", "max_tokens": 1024, "messages": [ { "role": "user", "content": "你好,介绍一下自己。" } ] }' ``` **流式输出(SSE)** ```bash curl -X POST "$BASE_URL/v1/messages" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ --no-buffer \ -d '{ "model": "claude-sonnet-4-6", "max_tokens": 1024, "stream": true, "messages": [ {"role": "user", "content": "写一首七言绝句"} ] }' ``` **多轮对话** ```bash curl -X POST "$BASE_URL/v1/messages" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-6", "max_tokens": 2048, "system": "你是一位专业的代码审查员,回答简洁精准。", "messages": [ {"role": "user", "content": "如何优化 Python 列表推导式?"}, {"role": "assistant", "content": "列表推导式比等效的 for 循环快约 35%,因为..."}, {"role": "user", "content": "给我一个具体例子"} ] }' ``` #### Python(官方 SDK) ```python import anthropic client = anthropic.Anthropic( api_key="sk-xxxxx", base_url="https://", ) # 普通调用 message = client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, messages=[ {"role": "user", "content": "你好,介绍一下自己。"} ] ) print(message.content[0].text) # 系统提示 + 多轮对话 message = client.messages.create( model="claude-opus-4-6", max_tokens=2048, system="你是一位资深 Go 语言专家。", messages=[ {"role": "user", "content": "解释 goroutine 和 channel 的关系"}, ] ) print(message.content[0].text) ``` **流式输出** ```python import anthropic client = anthropic.Anthropic( api_key="sk-xxxxx", base_url="https://", ) with client.messages.stream( model="claude-sonnet-4-6", max_tokens=1024, messages=[{"role": "user", "content": "写一首关于春天的诗"}], ) as stream: for text in stream.text_stream: print(text, end="", flush=True) print() # 换行 ``` **工具调用(Function Calling)** ```python import anthropic import json client = anthropic.Anthropic( api_key="sk-xxxxx", base_url="https://", ) tools = [ { "name": "get_weather", "description": "获取指定城市的天气信息", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,例如:北京、上海" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位" } }, "required": ["city"] } } ] response = client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "北京今天天气怎么样?"}] ) # 处理工具调用结果 for block in response.content: if block.type == "tool_use": print(f"调用工具: {block.name}") print(f"参数: {json.dumps(block.input, ensure_ascii=False, indent=2)}") ``` #### Go(官方 SDK) ```go package main import ( "context" "fmt" "log" "github.com/anthropics/anthropic-sdk-go" "github.com/anthropics/anthropic-sdk-go/option" ) func main() { client := anthropic.NewClient( option.WithAPIKey("sk-xxxxx"), option.WithBaseURL("https://"), ) // 普通调用 message, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{ Model: anthropic.F(anthropic.ModelClaudeSonnet4_6), MaxTokens: anthropic.F(int64(1024)), Messages: anthropic.F([]anthropic.MessageParam{ anthropic.UserMessageParam([]anthropic.ContentBlockParamUnion{ anthropic.TextBlockParam{Text: anthropic.F("你好,介绍一下自己。")}, }), }), }) if err != nil { log.Fatal(err) } fmt.Println(message.Content[0].(anthropic.TextBlock).Text) } ``` **流式输出(Go)** ```go package main import ( "context" "fmt" "log" "github.com/anthropics/anthropic-sdk-go" "github.com/anthropics/anthropic-sdk-go/option" ) func main() { client := anthropic.NewClient( option.WithAPIKey("sk-xxxxx"), option.WithBaseURL("https://"), ) stream := client.Messages.NewStreaming(context.Background(), anthropic.MessageNewParams{ Model: anthropic.F(anthropic.ModelClaudeSonnet4_6), MaxTokens: anthropic.F(int64(1024)), Messages: anthropic.F([]anthropic.MessageParam{ anthropic.UserMessageParam([]anthropic.ContentBlockParamUnion{ anthropic.TextBlockParam{Text: anthropic.F("写一首关于春天的诗")}, }), }), }) for stream.Next() { event := stream.Current() switch delta := event.Delta.(type) { case anthropic.ContentBlockDeltaEventDelta: if textDelta, ok := delta.AsUnion().(anthropic.TextDelta); ok { fmt.Print(textDelta.Text) } } } fmt.Println() if err := stream.Err(); err != nil { log.Fatal(err) } } ``` **纯 HTTP 调用(Go,无 SDK)** ```go package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" ) type MessageRequest struct { Model string `json:"model"` MaxTokens int `json:"max_tokens"` Messages []Message `json:"messages"` Stream bool `json:"stream,omitempty"` } type Message struct { Role string `json:"role"` Content string `json:"content"` } func main() { const ( baseURL = "https://" apiKey = "sk-xxxxx" ) reqBody := MessageRequest{ Model: "claude-sonnet-4-6", MaxTokens: 1024, Messages: []Message{ {Role: "user", Content: "你好,介绍一下自己。"}, }, } data, _ := json.Marshal(reqBody) req, _ := http.NewRequest("POST", baseURL+"/v1/messages", bytes.NewReader(data)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json") req.Header.Set("anthropic-version", "2023-06-01") 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)) } ``` ### 3.2 Token 计数 `POST /v1/messages/count_tokens` #### Curl ```bash curl -X POST "$BASE_URL/v1/messages/count_tokens" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-6", "messages": [ {"role": "user", "content": "你好,介绍一下自己。"} ] }' ``` **响应** ```json { "input_tokens": 18 } ``` #### Python ```python response = client.messages.count_tokens( model="claude-sonnet-4-6", messages=[{"role": "user", "content": "你好,介绍一下自己。"}], ) print(f"Token 数: {response.input_tokens}") ``` #### Go ```go count, err := client.Messages.CountTokens(context.Background(), anthropic.MessageCountTokensParams{ Model: anthropic.F(anthropic.ModelClaudeSonnet4_6), Messages: anthropic.F([]anthropic.MessageParam{ anthropic.UserMessageParam([]anthropic.ContentBlockParamUnion{ anthropic.TextBlockParam{Text: anthropic.F("你好,介绍一下自己。")}, }), }), }) if err != nil { log.Fatal(err) } fmt.Printf("Token 数: %d\n", count.InputTokens) ``` ### 3.3 列出模型 `GET /v1/models` #### Curl ```bash curl "$BASE_URL/v1/models" \ -H "Authorization: Bearer $API_KEY" \ -H "anthropic-version: 2023-06-01" ``` --- ## 4. Gemini API 完全兼容 Google Gemini 原生 API 格式。 ### 4.0 请求参数说明 #### 通用 Header 参数 | Header | 必填 | 说明 | |--------|------|------| | `x-goog-api-key` | 是¹ | Gemini 兼容认证方式(推荐) | | `Authorization` | 是¹ | Bearer 认证,格式:`Bearer sk-xxxxx` | | `x-api-key` | 是¹ | 与 `Authorization` 等价 | | `Content-Type` | 是 | 固定为 `application/json` | > ¹ 三种认证方式选一即可。 --- #### `POST /v1beta/models/{model}:generateContent` 路径参数 | 参数 | 位置 | 必填 | 说明 | |------|------|------|------| | `{model}` | URL 路径 | **是** | 模型名,如 `gemini-2.5-flash`、`gemini-2.5-pro` | --- #### `POST /v1beta/models/{model}:generateContent` Body 参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `contents` | array | **是** | 对话消息数组 | | `contents[].role` | string | **是** | 消息角色:`user` 或 `model` | | `contents[].parts` | array | **是** | 内容块数组 | | `contents[].parts[].text` | string | 否 | 文本内容 | | `contents[].parts[].inlineData` | object | 否 | 内联媒体数据(图片等),含 `mimeType` 和 `data`(base64) | | `system_instruction` | object | 否 | 系统指令(等同于 system prompt) | | `system_instruction.parts` | array | 否 | 系统指令内容块,结构同 `contents[].parts` | | `generationConfig` | object | 否 | 生成配置 | | `generationConfig.temperature` | number | 否 | 随机性,范围 `0.0~2.0` | | `generationConfig.maxOutputTokens` | integer | 否 | 最大输出 token 数 | | `generationConfig.topP` | number | 否 | Nucleus 采样,范围 `0.0~1.0` | | `generationConfig.topK` | integer | 否 | Top-K 采样 | | `generationConfig.stopSequences` | array\ | 否 | 遇到这些字符串时停止生成 | | `generationConfig.candidateCount` | integer | 否 | 返回候选结果数量,默认 `1` | | `tools` | array | 否 | 工具定义(Function Calling) | | `tool_config` | object | 否 | 工具调用模式配置 | | `tool_config.function_calling_config.mode` | string | 否 | `AUTO` / `ANY` / `NONE` | | `safetySettings` | array | 否 | 安全过滤设置,每项含 `category` 和 `threshold` | **响应体结构(非流式)** ```json { "candidates": [ { "content": { "parts": [{ "text": "回复内容" }], "role": "model" }, "finishReason": "STOP", "index": 0 } ], "usageMetadata": { "promptTokenCount": 25, "candidatesTokenCount": 80, "totalTokenCount": 105 } } ``` | `finishReason` 取值 | 说明 | |--------------------|------| | `STOP` | 正常结束 | | `MAX_TOKENS` | 达到 `maxOutputTokens` 上限 | | `SAFETY` | 触发安全过滤 | | `RECITATION` | 内容引用检测 | > **流式端点**:将路径中的 `generateContent` 替换为 `streamGenerateContent`,响应为 SSE 流,每条数据为完整的 JSON 对象(非增量),客户端需自行拼接文本。 --- ### 4.1 生成内容 `POST /v1beta/models/{model}:generateContent` #### Curl ```bash BASE_URL="https://" API_KEY="sk-xxxxx" MODEL="gemini-2.5-flash" # x-api-key 方式(推荐用于 Gemini) curl -X POST "$BASE_URL/v1beta/models/$MODEL:generateContent" \ -H "x-goog-api-key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [{"text": "你好,介绍一下自己。"}] } ] }' ``` **含系统指令** ```bash curl -X POST "$BASE_URL/v1beta/models/$MODEL:generateContent" \ -H "x-goog-api-key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "system_instruction": { "parts": [{"text": "你是一位精通中文的写作助手,回答简洁优美。"}] }, "contents": [ { "role": "user", "parts": [{"text": "写一首关于秋天的五言绝句"}] } ], "generationConfig": { "temperature": 0.9, "maxOutputTokens": 512 } }' ``` **流式输出** ```bash curl -X POST "$BASE_URL/v1beta/models/$MODEL:streamGenerateContent" \ -H "x-goog-api-key: $API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "contents": [ {"role": "user", "parts": [{"text": "解释量子纠缠"}]} ] }' ``` #### Python(google-generativeai SDK) ```python import google.generativeai as genai genai.configure( api_key="sk-xxxxx", # 通过环境变量或直接设置 transport # 需要将请求路由到 TrafficAPI ) # 推荐:使用 google.generativeai 的 transport 覆盖 import google.ai.generativelanguage as glm from google.api_core import gapic_v1 from google.auth.credentials import AnonymousCredentials # 方式一:直接使用 HTTP 请求(最简单) import httpx BASE_URL = "https://" API_KEY = "sk-xxxxx" MODEL = "gemini-2.5-flash" response = httpx.post( f"{BASE_URL}/v1beta/models/{MODEL}:generateContent", headers={"x-goog-api-key": API_KEY}, json={ "contents": [ {"role": "user", "parts": [{"text": "你好,介绍一下自己。"}]} ] } ) data = response.json() print(data["candidates"][0]["content"]["parts"][0]["text"]) ``` **流式输出(Python HTTP)** ```python import httpx import json BASE_URL = "https://" API_KEY = "sk-xxxxx" MODEL = "gemini-2.5-flash" with httpx.stream( "POST", f"{BASE_URL}/v1beta/models/{MODEL}:streamGenerateContent", headers={"x-goog-api-key": API_KEY, "Content-Type": "application/json"}, json={ "contents": [ {"role": "user", "parts": [{"text": "解释量子纠缠,500字以内"}]} ] } ) as stream: for line in stream.iter_lines(): line = line.strip() if not line or line == "data: [DONE]": continue if line.startswith("data: "): line = line[6:] try: chunk = json.loads(line) for candidate in chunk.get("candidates", []): for part in candidate.get("content", {}).get("parts", []): if "text" in part: print(part["text"], end="", flush=True) except json.JSONDecodeError: pass print() ``` #### Go(纯 HTTP) ```go package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" ) type GeminiRequest struct { Contents []GeminiContent `json:"contents"` GenerationConfig *GeminiGenerationConfig `json:"generationConfig,omitempty"` } type GeminiContent struct { Role string `json:"role"` Parts []GeminiPart `json:"parts"` } type GeminiPart struct { Text string `json:"text"` } type GeminiGenerationConfig struct { Temperature float64 `json:"temperature,omitempty"` MaxOutputTokens int `json:"maxOutputTokens,omitempty"` } func main() { const ( baseURL = "https://" apiKey = "sk-xxxxx" model = "gemini-2.5-flash" ) reqBody := GeminiRequest{ Contents: []GeminiContent{ { Role: "user", Parts: []GeminiPart{{Text: "你好,介绍一下自己。"}}, }, }, GenerationConfig: &GeminiGenerationConfig{ Temperature: 0.7, MaxOutputTokens: 1024, }, } data, _ := json.Marshal(reqBody) url := fmt.Sprintf("%s/v1beta/models/%s:generateContent", baseURL, model) req, _ := http.NewRequest("POST", url, bytes.NewReader(data)) req.Header.Set("x-goog-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() var result map[string]any json.NewDecoder(resp.Body).Decode(&result) candidates := result["candidates"].([]any) content := candidates[0].(map[string]any)["content"].(map[string]any) parts := content["parts"].([]any) text := parts[0].(map[string]any)["text"].(string) fmt.Println(text) } ``` **流式输出(Go)** ```go package main import ( "bufio" "bytes" "encoding/json" "fmt" "log" "net/http" "strings" ) func main() { const ( baseURL = "https://" apiKey = "sk-xxxxx" model = "gemini-2.5-flash" ) body := map[string]any{ "contents": []map[string]any{ { "role": "user", "parts": []map[string]any{{"text": "解释量子纠缠,500字以内"}}, }, }, } data, _ := json.Marshal(body) url := fmt.Sprintf("%s/v1beta/models/%s:streamGenerateContent", baseURL, model) req, _ := http.NewRequest("POST", url, bytes.NewReader(data)) req.Header.Set("x-goog-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { line := scanner.Text() if !strings.HasPrefix(line, "data: ") { continue } raw := strings.TrimPrefix(line, "data: ") if raw == "[DONE]" { break } var chunk map[string]any if err := json.Unmarshal([]byte(raw), &chunk); err != nil { continue } candidates, _ := chunk["candidates"].([]any) for _, c := range candidates { cd := c.(map[string]any) content := cd["content"].(map[string]any) parts := content["parts"].([]any) for _, p := range parts { if text, ok := p.(map[string]any)["text"].(string); ok { fmt.Print(text) } } } } fmt.Println() } ``` ### 4.2 列出模型 `GET /v1beta/models` #### Curl ```bash curl "$BASE_URL/v1beta/models" \ -H "x-goog-api-key: $API_KEY" ``` --- ## 5. OpenAI 兼容 API 完全兼容 OpenAI Chat Completions 格式,可直接使用 OpenAI 官方 SDK,只需替换 `base_url`。 后端会自动将请求路由到相应平台(Claude/OpenAI),并将响应转换回 OpenAI 格式。 ### 5.0 请求参数说明 #### 通用 Header 参数 | Header | 必填 | 说明 | |--------|------|------| | `Authorization` | 是 | Bearer 认证,格式:`Bearer sk-xxxxx` | | `Content-Type` | 是 | 固定为 `application/json` | | `User-Agent` | 否 | 客户端标识,影响粘性会话亲和力 | --- #### `POST /v1/chat/completions` Body 参数 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `model` | string | **是** | — | 模型名,如 `claude-sonnet-4-6`、`gpt-oss-120b-medium` | | `messages` | array | **是** | — | 对话消息数组 | | `messages[].role` | string | **是** | — | 消息角色:`system` / `user` / `assistant` / `tool` | | `messages[].content` | string \| array | **是** | — | 消息内容;支持多模态内容块(`type: text` / `type: image_url`) | | `messages[].name` | string | 否 | — | 发送者名称(`tool` 角色时为工具名) | | `messages[].tool_call_id` | string | 否 | — | 工具调用 ID(`tool` 角色回复时使用) | | `max_tokens` | integer | 否 | 模型默认 | 最大输出 token 数 | | `stream` | boolean | 否 | `false` | 是否开启 SSE 流式输出 | | `temperature` | number | 否 | `1.0` | 随机性,范围 `0.0~2.0` | | `top_p` | number | 否 | `1.0` | Nucleus 采样概率阈值 | | `frequency_penalty` | number | 否 | `0.0` | 频率惩罚,范围 `-2.0~2.0`,减少重复词 | | `presence_penalty` | number | 否 | `0.0` | 存在惩罚,范围 `-2.0~2.0`,鼓励新话题 | | `stop` | string \| array | 否 | — | 遇到这些字符串时停止生成,最多 4 项 | | `n` | integer | 否 | `1` | 生成候选回复数量 | | `tools` | array | 否 | — | 工具定义列表(Function Calling) | | `tools[].type` | string | 否 | — | 固定为 `"function"` | | `tools[].function.name` | string | 否 | — | 工具名称 | | `tools[].function.description` | string | 否 | — | 工具描述 | | `tools[].function.parameters` | object | 否 | — | 工具参数 JSON Schema | | `tool_choice` | string \| object | 否 | `"auto"` | 工具调用策略:`"none"` / `"auto"` / `"required"` / `{"type": "function", "function": {"name": "..."}}` | | `response_format` | object | 否 | — | 响应格式,如 `{"type": "json_object"}` 强制 JSON 输出 | | `seed` | integer | 否 | — | 随机种子(尽力保证确定性输出) | | `user` | string | 否 | — | 终端用户标识,用于监控滥用行为 | | `stream_options` | object | 否 | — | 流式选项,如 `{"include_usage": true}` 在流末追加用量统计 | **响应体结构(非流式)** ```json { "id": "chatcmpl-xxxxx", "object": "chat.completion", "created": 1700000000, "model": "claude-sonnet-4-6", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "回复内容" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 25, "completion_tokens": 80, "total_tokens": 105 } } ``` | `finish_reason` 取值 | 说明 | |---------------------|------| | `stop` | 模型正常结束 | | `length` | 达到 `max_tokens` 上限 | | `tool_calls` | 模型请求调用工具 | | `content_filter` | 内容过滤触发 | **SSE 流式数据块格式(`stream: true`)** ``` data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]} data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]} data: [DONE] ``` --- ### 5.1 Chat Completions `POST /v1/chat/completions` #### Curl ```bash BASE_URL="https://" API_KEY="sk-xxxxx" curl -X POST "$BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-6", "messages": [ {"role": "system", "content": "你是一位资深软件工程师。"}, {"role": "user", "content": "解释 CAP 定理"} ], "max_tokens": 1024, "temperature": 0.7 }' ``` **流式输出(SSE)** ```bash curl -X POST "$BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "claude-sonnet-4-6", "messages": [ {"role": "user", "content": "写一段 Python 快速排序代码"} ], "stream": true }' ``` **函数调用** ```bash curl -X POST "$BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-6", "messages": [ {"role": "user", "content": "北京现在几点了?"} ], "tools": [ { "type": "function", "function": { "name": "get_current_time", "description": "获取指定时区的当前时间", "parameters": { "type": "object", "properties": { "timezone": { "type": "string", "description": "时区,如 Asia/Shanghai" } }, "required": ["timezone"] } } } ], "tool_choice": "auto" }' ``` #### Python(OpenAI SDK) ```python from openai import OpenAI client = OpenAI( api_key="sk-xxxxx", base_url="https:///v1", ) # 普通调用 response = client.chat.completions.create( model="claude-sonnet-4-6", messages=[ {"role": "system", "content": "你是一位资深软件工程师。"}, {"role": "user", "content": "解释 CAP 定理"}, ], max_tokens=1024, temperature=0.7, ) print(response.choices[0].message.content) # 流式输出 stream = client.chat.completions.create( model="claude-sonnet-4-6", messages=[{"role": "user", "content": "写一段 Python 快速排序代码"}], stream=True, ) for chunk in stream: delta = chunk.choices[0].delta if delta.content: print(delta.content, end="", flush=True) print() ``` **函数调用(Python OpenAI SDK)** ```python from openai import OpenAI import json client = OpenAI( api_key="sk-xxxxx", base_url="https:///v1", ) tools = [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名称"}, }, "required": ["city"], }, }, } ] response = client.chat.completions.create( model="claude-sonnet-4-6", messages=[{"role": "user", "content": "上海天气怎么样?"}], tools=tools, tool_choice="auto", ) message = response.choices[0].message if message.tool_calls: for call in message.tool_calls: print(f"工具: {call.function.name}") print(f"参数: {json.loads(call.function.arguments)}") ``` #### Go(OpenAI SDK) ```go package main import ( "context" "fmt" "log" "github.com/openai/openai-go" "github.com/openai/openai-go/option" ) func main() { client := openai.NewClient( option.WithAPIKey("sk-xxxxx"), option.WithBaseURL("https:///v1"), ) // 普通调用 completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: openai.F("claude-sonnet-4-6"), Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("你是一位资深软件工程师。"), openai.UserMessage("解释 CAP 定理"), }), MaxTokens: openai.F(int64(1024)), Temperature: openai.F(0.7), }) if err != nil { log.Fatal(err) } fmt.Println(completion.Choices[0].Message.Content) } ``` **流式输出(Go)** ```go package main import ( "context" "fmt" "log" "github.com/openai/openai-go" "github.com/openai/openai-go/option" ) func main() { client := openai.NewClient( option.WithAPIKey("sk-xxxxx"), option.WithBaseURL("https:///v1"), ) stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ Model: openai.F("claude-sonnet-4-6"), Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ openai.UserMessage("写一段 Go 实现的二叉树遍历"), }), }) for stream.Next() { chunk := stream.Current() if len(chunk.Choices) > 0 { fmt.Print(chunk.Choices[0].Delta.Content) } } fmt.Println() if err := stream.Err(); err != nil { log.Fatal(err) } } ``` **纯 HTTP 调用(Go,无 SDK)** ```go package main import ( "bufio" "bytes" "encoding/json" "fmt" "io" "log" "net/http" "strings" ) func main() { const ( baseURL = "https://" apiKey = "sk-xxxxx" ) body := map[string]any{ "model": "claude-sonnet-4-6", "messages": []map[string]string{ {"role": "user", "content": "解释 CAP 定理"}, }, "max_tokens": 1024, "stream": true, } data, _ := json.Marshal(body) req, _ := http.NewRequest("POST", baseURL+"/v1/chat/completions", bytes.NewReader(data)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { line := scanner.Text() if !strings.HasPrefix(line, "data: ") { continue } raw := strings.TrimPrefix(line, "data: ") if raw == "[DONE]" { break } var chunk map[string]any if err := json.Unmarshal([]byte(raw), &chunk); err != nil { continue } choices := chunk["choices"].([]any) delta := choices[0].(map[string]any)["delta"].(map[string]any) if content, ok := delta["content"].(string); ok { fmt.Print(content) } } fmt.Println() // 非流式调用 body2 := map[string]any{ "model": "claude-sonnet-4-6", "messages": []map[string]string{ {"role": "user", "content": "你好"}, }, } data2, _ := json.Marshal(body2) req2, _ := http.NewRequest("POST", baseURL+"/v1/chat/completions", bytes.NewReader(data2)) req2.Header.Set("Authorization", "Bearer "+apiKey) req2.Header.Set("Content-Type", "application/json") resp2, err := http.DefaultClient.Do(req2) if err != nil { log.Fatal(err) } defer resp2.Body.Close() body3, _ := io.ReadAll(resp2.Body) var result map[string]any json.Unmarshal(body3, &result) choices := result["choices"].([]any) message := choices[0].(map[string]any)["message"].(map[string]any) fmt.Println(message["content"]) } ``` ### 5.2 Responses API `POST /v1/responses` Responses API 兼容 OpenAI Responses 格式(含 WebSocket 流式支持)。 ```bash curl -X POST "$BASE_URL/v1/responses" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-6", "input": "你好,介绍一下自己。", "stream": false }' ``` --- ## 6. Antigravity 路由(Claude + Gemini 混合) Antigravity 平台同时支持 Claude 和 Gemini 模型,通过 `/antigravity` 前缀路由。 ### 6.1 Claude via Antigravity ```bash curl -X POST "$BASE_URL/antigravity/v1/messages" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-6", "max_tokens": 1024, "messages": [ {"role": "user", "content": "你好"} ] }' ``` ### 6.2 Gemini via Antigravity ```bash MODEL="gemini-2.5-flash" curl -X POST "$BASE_URL/antigravity/v1beta/models/$MODEL:generateContent" \ -H "x-goog-api-key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ {"role": "user", "parts": [{"text": "你好"}]} ] }' ``` ### 6.3 Antigravity 支持的模型(含别名映射) | 请求模型名 | 实际路由模型 | |-----------|-------------| | `claude-opus-4-6` | `claude-opus-4-6-thinking` | | `claude-sonnet-4-6` | `claude-sonnet-4-6` | | `claude-haiku-4-5` | `claude-sonnet-4-6`(升级) | | `gemini-2.5-flash` | `gemini-2.5-flash` | | `gemini-2.5-pro` | `gemini-2.5-pro` | | `gemini-3-flash-preview` | `gemini-3-flash` | | `gemini-3-pro-preview` | `gemini-3-pro-high` | | `gemini-3.1-pro-preview` | `gemini-3.1-pro-high` | --- ## 7. 公共接口 ### 7.1 健康检查 `GET /health` ```bash curl "$BASE_URL/health" ``` **响应** ```json {"status": "ok"} ``` ### 7.2 获取使用量 `GET /v1/usage` ```bash curl "$BASE_URL/v1/usage" \ -H "Authorization: Bearer $API_KEY" ``` --- ## 8. 错误处理 ### 8.1 错误格式 不同平台返回不同格式的错误,网关会根据调用端点自动适配: **Anthropic 格式**(`/v1/messages`) ```json { "type": "error", "error": { "type": "authentication_error", "message": "invalid x-api-key" } } ``` **OpenAI 格式**(`/v1/chat/completions`) ```json { "error": { "type": "authentication_error", "message": "invalid api key" } } ``` **Gemini 格式**(`/v1beta/...`) ```json { "error": { "code": 401, "message": "API key not valid.", "status": "UNAUTHENTICATED" } } ``` ### 8.2 常见 HTTP 状态码 | 状态码 | 含义 | 处理建议 | |--------|------|----------| | `200` | 成功 | - | | `400` | 请求格式错误 | 检查请求体参数 | | `401` | 认证失败 | 检查 API Key 是否正确 | | `403` | 权限不足 / IP 被限制 | 联系管理员 | | `429` | 请求过于频繁 / 并发超限 | 降低请求频率,等待后重试 | | `500` | 服务器内部错误 | 联系管理员 | | `529` | 上游服务过载 | 稍后重试 | ### 8.3 Python 错误处理示例 ```python import anthropic client = anthropic.Anthropic( api_key="sk-xxxxx", base_url="https://", ) try: message = client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, messages=[{"role": "user", "content": "你好"}], ) print(message.content[0].text) except anthropic.AuthenticationError as e: print(f"认证失败: {e}") except anthropic.RateLimitError as e: print(f"速率限制: {e}") except anthropic.APIStatusError as e: print(f"API 错误 {e.status_code}: {e.message}") ``` ### 8.4 Go 错误处理示例 ```go message, err := client.Messages.New(ctx, params) if err != nil { var apiErr *anthropic.Error if errors.As(err, &apiErr) { switch apiErr.StatusCode { case 401: log.Println("认证失败,请检查 API Key") case 429: log.Println("请求频率过高,请稍后重试") default: log.Printf("API 错误 %d: %s", apiErr.StatusCode, apiErr.Message) } } else { log.Printf("网络错误: %v", err) } return } ``` --- ## 附录:快速参考 ### A. SDK 安装 ```bash # Python - Anthropic 官方 SDK pip install anthropic # Python - OpenAI 官方 SDK pip install openai # Python - HTTP 客户端 pip install httpx # Go - Anthropic SDK go get github.com/anthropics/anthropic-sdk-go # Go - OpenAI SDK go get github.com/openai/openai-go ``` ### B. 环境变量配置(推荐) ```bash # .env 或 shell 配置 export TRAFFICAPI_BASE_URL="https://" export TRAFFICAPI_API_KEY="sk-xxxxx" ``` ```python import os import anthropic client = anthropic.Anthropic( api_key=os.environ["TRAFFICAPI_API_KEY"], base_url=os.environ["TRAFFICAPI_BASE_URL"], ) ``` ### C. 各 API 路由速查 | 操作 | 方法 | 路径 | |------|------|------| | Claude 发送消息 | `POST` | `/v1/messages` | | Claude 计算 Token | `POST` | `/v1/messages/count_tokens` | | Claude 模型列表 | `GET` | `/v1/models` | | Gemini 生成内容 | `POST` | `/v1beta/models/{model}:generateContent` | | Gemini 流式生成 | `POST` | `/v1beta/models/{model}:streamGenerateContent` | | Gemini 模型列表 | `GET` | `/v1beta/models` | | OpenAI Chat | `POST` | `/v1/chat/completions` | | OpenAI Responses | `POST` | `/v1/responses` | | Antigravity Claude | `POST` | `/antigravity/v1/messages` | | Antigravity Gemini | `POST` | `/antigravity/v1beta/models/{model}:generateContent` | | 健康检查 | `GET` | `/health` | | 使用量查询 | `GET` | `/v1/usage` |