Get an additional discount on premium plans after signing up

Chat 模型 API

Buble 通过多种公开 API 格式暴露当前激活的 Chat 模型,方便 code agent、后端服务和第三方集成在不依赖浏览器 UI 的情况下调用同一套 Chat 模型配置。

Chat API 与媒体生成 API 是分开的。Chat 模型列表使用 /api/v1/models;图片、视频、音频和音乐生成模型列表使用 /api/v1/media_models。

认证

所有 Chat API 端点都需要服务端 API Key。

Authorization: Bearer $BUBLE_API_KEY

也支持使用 X-API-Key: $BUBLE_API_KEY。

端点

Method Endpoint 格式 用途
GET /api/v1/models OpenAI 风格模型列表 列出当前激活的 Chat 模型。
POST /api/v1/chat/completions OpenAI Chat Completions 风格 创建 Chat 回复或流式 chunk。
POST /api/v1/messages Anthropic Messages 风格 创建 Message 回复或流式事件。
POST /api/v1beta/models/{model}:generateContent Gemini generateContent 风格 生成非流式模型内容。
POST /api/v1beta/models/{model}:streamGenerateContent Gemini streamGenerateContent 风格 流式生成模型内容。

OpenAI 兼容和 Anthropic 兼容端点使用 stream: true 开启流式输出。Gemini 兼容流式输出使用标准 :streamGenerateContent 方法,而不是在 :generateContent 中传 stream: true。

获取 Chat 模型列表

GET /api/v1/models

请求示例

curl https://buble.ai/api/v1/models \
  -H "Authorization: Bearer $BUBLE_API_KEY"

响应结构

{
  "object": "list",
  "data": [
    {
      "id": "openai/gpt-5.5",
      "object": "model",
      "created": 1778716800,
      "owned_by": "OpenAI",
      "name": "GPT-5.5",
      "description": "High-capability chat model.",
      "capabilities": {
        "reasoning": true,
        "attachments": true,
        "tools": true
      },
      "tags": ["chat"]
    }
  ]
}

模型字段

字段 说明
id 稳定模型 key,调用 Chat API 时作为 model 传入。
object 固定为 model。
created 模型创建时间,Unix 秒级时间戳。
owned_by Vendor 或 Provider 展示名称。
name 模型展示名称。
description 可选的模型描述。
capabilities 基于当前 Chat 模型配置生成的公开能力标记。
tags 模型配置中的可选标签。

OpenAI 兼容 Chat Completions

POST /api/v1/chat/completions
Content-Type: application/json

请求体

字段 类型 必填 说明
model string 是 来自 /api/v1/models 的 Chat 模型 key。
messages array 是 OpenAI 风格 Chat 消息。转换后至少需要一条非 system 消息。
stream boolean 否 为 true 时返回 OpenAI 兼容的 Server-Sent Events。
temperature number 否 仅当所选模型配置暴露该 option 时才会转发。
top_p number 否 仅当所选模型配置暴露该 option 时才会转发。
stop string 或 array 否 仅当所选模型配置暴露该 option 时才会转发。
presence_penalty number 否 仅当所选模型配置暴露该 option 时才会转发。
frequency_penalty number 否 仅当所选模型配置暴露该 option 时才会转发。
response_format object 否 仅当所选模型配置暴露该 option 时才会转发。
seed number 否 仅当所选模型配置暴露该 option 时才会转发。
options object 否 所选 Chat 模型配置中定义的模型专属 options。
extra_body object 否 会在校验前合并到模型 options 中。
tools array 否 OpenAI 兼容工具定义。需要模型支持 capabilities.tools。
tool_choice string 或 object 否 OpenAI 兼容工具选择。需要模型支持 capabilities.tools。
parallel_tool_calls boolean 否 OpenAI 兼容并行工具调用控制。需要模型支持 capabilities.tools。
reasoning boolean 否 仅当模型配置支持 reasoning 时启用推理能力。
reasoning_effort string 或 boolean 否 当前按 reasoning 开关处理;provider 专属 effort 值应通过已配置的 options 传递。
max_tokens number 否 请求输出上限,可能会被 Buble 计费预留上限进一步收紧。
max_completion_tokens number 否 OpenAI 风格的另一种输出上限字段。

支持的消息内容

messages[].content 可以是字符串,也可以是内容 part 数组。

Part 类型 支持字段 在 Buble 内部的转换结果
text text 文本 part。
input_text text 文本 part。
image_url image_url 字符串,或 { "url": "..." } 图片类型文件附件。
file file.file_data、file.url 或 url 文件附件,可带 media type 和文件名。

附件是否真正可用取决于所选 Chat 模型配置中允许的附件类型。

请求示例

curl https://buble.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "messages": [
      {
        "role": "system",
        "content": "You are a concise product analyst."
      },
      {
        "role": "user",
        "content": "Summarize the main tradeoffs in this launch plan."
      }
    ],
    "temperature": 0.4,
    "reasoning": true,
    "max_completion_tokens": 800
  }'

响应结构

{
  "id": "chatcmpl-8c3d1f6b-5f04-4a8f-b75a-80f1c49e0a8d",
  "object": "chat.completion",
  "created": 1778716800,
  "model": "openai/gpt-5.5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Here are the main tradeoffs..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 120,
    "completion_tokens": 260,
    "total_tokens": 380
  }
}

如果 provider 返回 reasoning 文本且模型支持该能力,响应中可能包含 message.reasoning_content。如果 provider 返回 reasoning token 或 cached input token,响应中可能包含 usage.completion_tokens_details.reasoning_tokens 和 usage.prompt_tokens_details.cached_tokens。

流式响应

设置 stream: true 可以接收 OpenAI 兼容的 Server-Sent Events:

curl https://buble.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "Write a short launch summary."
      }
    ]
  }'

流式 chunk 使用 chat.completion.chunk 对象,并以 data: [DONE] 结束。

Anthropic 兼容 Messages

POST /api/v1/messages
Content-Type: application/json

请求体

字段 类型 必填 说明
model string 是 来自 /api/v1/models 的 Chat 模型 key。
system string 否 会转换为 system 消息。
messages array 是 Anthropic 风格消息。转换后至少需要一条非 system 消息。
stream boolean 否 为 true 时返回 Anthropic 兼容的 Server-Sent Events。
max_tokens number 否 请求输出上限,可能会被 Buble 计费预留上限进一步收紧。
temperature number 否 仅当所选模型配置暴露该 option 时才会转发。
top_p number 否 仅当所选模型配置暴露该 option 时才会转发。
top_k number 否 仅当所选模型配置暴露该 option 时才会转发。
stop_sequences array 否 当所选模型支持时,会映射为内部 stop option。
options object 否 所选 Chat 模型配置中定义的模型专属 options。
tools array 否 Anthropic 兼容工具定义。需要模型支持 capabilities.tools。
tool_choice object 否 Anthropic 兼容工具选择。需要模型支持 capabilities.tools。
thinking boolean/object 否 仅当模型配置支持 reasoning 时启用推理能力。
reasoning boolean 否 另一种 reasoning 开关。

支持的消息内容

messages[].content 可以是字符串,也可以是内容 block 数组。

Block 类型 支持字段 在 Buble 内部的转换结果
text text 文本 part。
image source.type: "url" 和 source.url 图片文件附件。
image source.type: "base64" 和 source.data Data URL 图片文件附件。
document source.type: "url" 和 source.url 文档文件附件。

请求示例

curl https://buble.ai/api/v1/messages \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "system": "You are a concise product analyst.",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "Summarize the main tradeoffs in this launch plan."
          }
        ]
      }
    ],
    "max_tokens": 800,
    "temperature": 0.4
  }'

响应结构

{
  "id": "msg_8c3d1f6b5f044a8fb75a80f1c49e0a8d",
  "type": "message",
  "role": "assistant",
  "model": "openai/gpt-5.5",
  "content": [
    {
      "type": "text",
      "text": "Here are the main tradeoffs..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 120,
    "output_tokens": 260
  }
}

如果返回 reasoning 文本,响应中还会包含:

{
  "thinking": [
    {
      "type": "thinking",
      "thinking": "Reasoning text returned by the provider."
    }
  ]
}

流式响应

设置 stream: true 可以接收 Anthropic 兼容的 Server-Sent Events:

curl https://buble.ai/api/v1/messages \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "Write a short launch summary."
      }
    ]
  }'

流式事件包括 message_start、content_block_delta、message_delta 和 message_stop。

Gemini 兼容 generateContent

POST /api/v1beta/models/{model}:generateContent
Content-Type: application/json

路径中的 {model} 是 Buble Chat 模型 key。如果模型 key 中包含 /,可以作为路径层级传入,例如 /api/v1beta/models/openai/gpt-5.5:generateContent。

:generateContent 用于非流式 Gemini 兼容请求。流式请求使用 :streamGenerateContent。不要在 :generateContent 中使用 stream: true。

请求体

字段 类型 必填 说明
contents array 是 Gemini 风格内容列表。转换后至少需要一条非 system 消息。
systemInstruction object 否 其中的 parts 会转换为 system 消息。
generationConfig object 否 支持 temperature、topP、topK、stopSequences 和 maxOutputTokens。
generation_config object 否 generationConfig 的 snake-case 替代字段。
options object 否 所选 Chat 模型配置中定义的模型专属 options。
tools array 否 Gemini 兼容工具声明。需要模型支持 capabilities.tools。
toolConfig object 否 Gemini 兼容工具配置。需要模型支持 capabilities.tools。
reasoning boolean 否 仅当模型配置支持 reasoning 时启用推理能力。
thinkingConfig object 否 当前按 reasoning 开关处理;provider 专属字段需要通过已配置的 options 传递。

支持的 parts

Part 字段 在 Buble 内部的转换结果
text 文本 part。
fileData.fileUri 文件附件 URL。
file_data.file_uri 文件附件 URL。
inlineData.data Base64 Data URL 附件。
inline_data.data Base64 Data URL 附件。

contents[].role 为 model 时会转换为 assistant 消息,其他 role 会转换为 user 消息。

请求示例

curl https://buble.ai/api/v1beta/models/openai/gpt-5.5:generateContent \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemInstruction": {
      "parts": [
        {
          "text": "You are a concise product analyst."
        }
      ]
    },
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Summarize the main tradeoffs in this launch plan."
          }
        ]
      }
    ],
    "generationConfig": {
      "temperature": 0.4,
      "maxOutputTokens": 800
    }
  }'

响应结构

{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "text": "Here are the main tradeoffs..."
          }
        ]
      },
      "finishReason": "STOP",
      "index": 0
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 120,
    "candidatesTokenCount": 260,
    "totalTokenCount": 380
  },
  "modelVersion": "openai/gpt-5.5"
}

Gemini 兼容 streamGenerateContent

POST /api/v1beta/models/{model}:streamGenerateContent
Content-Type: application/json

请求体与 :generateContent 保持一致,但响应通过 Server-Sent Events 返回。

请求示例

curl https://buble.ai/api/v1beta/models/openai/gpt-5.5:streamGenerateContent \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Write a short launch summary."
          }
        ]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 800
    }
  }'

每个流式 chunk 都是一个 Gemini 兼容的 GenerateContentResponse JSON 对象。

SDK 示例

SDK 暴露与 HTTP API 相同的三类 Chat 协议。OpenAI 兼容和 Anthropic 兼容流式调用会由 SDK 自动设置 stream: true。Gemini 兼容流式调用使用专门的 streamGenerateContent / stream_generate_content 方法,并调用 /api/v1beta/models/{model}:streamGenerateContent。

下面的片段假设你已经按快速开始初始化了 SDK client,并引入了对应语言需要的 SDK 类型。

JavaScript / TypeScript

const completion = await buble.chat.completions.create({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'Write a short launch summary.' }],
  max_completion_tokens: 800,
});

const stream = await buble.chat.completions.stream({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'Write one sentence at a time.' }],
});

for await (const text of stream.toTextStream()) {
  process.stdout.write(text);
}

Python

completion = client.chat.completions.create(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "Write a short launch summary."}],
    max_completion_tokens=800,
)

for text in client.chat.completions.stream_text(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "Write one sentence at a time."}],
):
    print(text, end="")

Go

completion, err := client.Chat.Completions.Create(ctx, buble.ChatRequest{
	"model": "openai/gpt-5.5",
	"messages": []any{
		map[string]any{"role": "user", "content": "Write a short launch summary."},
	},
	"max_completion_tokens": 800,
})
if err != nil {
	return err
}

stream, err := client.Chat.Completions.Stream(ctx, buble.ChatRequest{
	"model": "openai/gpt-5.5",
	"messages": []any{
		map[string]any{"role": "user", "content": "Write one sentence at a time."},
	},
})
if err != nil {
	return err
}
defer stream.Close()

for stream.Next() {
	fmt.Print(stream.Text())
}

Rust

use futures_util::StreamExt;

let completion = client.chat().completions().create(serde_json::json!({
    "model": "openai/gpt-5.5",
    "messages": [
        { "role": "user", "content": "Write a short launch summary." }
    ],
    "max_completion_tokens": 800
})).await?;

let mut stream = client.chat().completions().stream_text(serde_json::json!({
    "model": "openai/gpt-5.5",
    "messages": [
        { "role": "user", "content": "Write one sentence at a time." }
    ]
})).await?;

while let Some(chunk) = stream.next().await {
    print!("{}", chunk?);
}

Swift

let completion = try await client.chat.completions.create([
    "model": "openai/gpt-5.5",
    "messages": [
        ["role": "user", "content": "Write a short launch summary."]
    ],
    "max_completion_tokens": 800
])

let stream = try await client.chat.completions.streamText([
    "model": "openai/gpt-5.5",
    "messages": [
        ["role": "user", "content": "Write one sentence at a time."]
    ]
])

for try await text in stream {
    print(text, terminator: "")
}

Dart / Flutter

final completion = await client.chat.completions.create({
  'model': 'openai/gpt-5.5',
  'messages': [
    {'role': 'user', 'content': 'Write a short launch summary.'},
  ],
  'max_completion_tokens': 800,
});

final stream = await client.chat.completions.streamText({
  'model': 'openai/gpt-5.5',
  'messages': [
    {'role': 'user', 'content': 'Write one sentence at a time.'},
  ],
});

await for (final text in stream) {
  print(text);
}

Elixir

{:ok, completion} =
  Buble.Chat.Completions.create(client, %{
    model: "openai/gpt-5.5",
    messages: [%{role: "user", content: "Write a short launch summary."}],
    max_completion_tokens: 800
  })

{:ok, stream} =
  Buble.Chat.Completions.stream_text(client, %{
    model: "openai/gpt-5.5",
    messages: [%{role: "user", content: "Write one sentence at a time."}]
  })

Enum.each(stream, &IO.write/1)

Java

var completion = client.chat().completions().create(Map.of(
        "model", "openai/gpt-5.5",
        "messages", List.of(Map.of("role", "user", "content", "Write a short launch summary.")),
        "max_completion_tokens", 800));

try (BubleStream stream = client.chat().completions().stream(Map.of(
        "model", "openai/gpt-5.5",
        "messages", List.of(Map.of("role", "user", "content", "Write one sentence at a time."))))) {
    while (stream.next()) {
        System.out.print(stream.text());
    }
}

.NET

var completion = await client.Chat.Completions.CreateAsync(new Dictionary<string, object?>
{
    ["model"] = "openai/gpt-5.5",
    ["messages"] = new[]
    {
        new Dictionary<string, object?>
        {
            ["role"] = "user",
            ["content"] = "Write a short launch summary."
        }
    },
    ["max_completion_tokens"] = 800
});

await foreach (var text in client.Chat.Completions.StreamTextAsync(new Dictionary<string, object?>
{
    ["model"] = "openai/gpt-5.5",
    ["messages"] = new[]
    {
        new Dictionary<string, object?>
        {
            ["role"] = "user",
            ["content"] = "Write one sentence at a time."
        }
    }
}))
{
    Console.Write(text);
}

PHP

$completion = $client->chat()->completions()->create([
    'model' => 'openai/gpt-5.5',
    'messages' => [
        ['role' => 'user', 'content' => 'Write a short launch summary.'],
    ],
    'max_completion_tokens' => 800,
]);

foreach ($client->chat()->completions()->streamText([
    'model' => 'openai/gpt-5.5',
    'messages' => [
        ['role' => 'user', 'content' => 'Write one sentence at a time.'],
    ],
]) as $text) {
    echo $text;
}

Ruby

completion = client.chat.completions.create(
  model: "openai/gpt-5.5",
  messages: [
    { role: "user", content: "Write a short launch summary." }
  ],
  max_completion_tokens: 800
)

client.chat.completions.stream_text(
  model: "openai/gpt-5.5",
  messages: [
    { role: "user", content: "Write one sentence at a time." }
  ]
).each do |text|
  print text
end

Gemini 方法名

语言 非流式 流式
JavaScript / TypeScript buble.chat.gemini.generateContent(model, body) buble.chat.gemini.streamGenerateContent(model, body)
Python client.chat.gemini.generate_content(model, **body) client.chat.gemini.stream_generate_content(model, **body)
Go client.Chat.Gemini.GenerateContent(ctx, model, body) client.Chat.Gemini.StreamGenerateContent(ctx, model, body)
Rust client.chat().gemini().generate_content(model, body) client.chat().gemini().stream_generate_content(model, body)
Swift client.chat.gemini.generateContent(model, body) client.chat.gemini.streamGenerateContent(model, body)
Dart / Flutter client.chat.gemini.generateContent(model, body) client.chat.gemini.streamGenerateContent(model, body)
Elixir Buble.Chat.Gemini.generate_content(client, model, body) Buble.Chat.Gemini.stream_generate_content(client, model, body)
Java client.chat().gemini().generateContent(model, body) client.chat().gemini().streamGenerateContent(model, body)
.NET client.Chat.Gemini.GenerateContentAsync(model, body) client.Chat.Gemini.StreamGenerateContentAsync(model, body)
PHP $client->chat()->gemini()->generateContent($model, $body) $client->chat()->gemini()->streamGenerateContent($model, $body)
Ruby client.chat.gemini.generate_content(model, body) client.chat.gemini.stream_generate_content(model, body)

Options 与能力开关

Chat 模型 options 会根据所选模型的 UI options 配置进行校验。temperature、top_p、top_k、stop 等标准字段只有在所选模型暴露对应 option 时才会被转发。模型专属参数应放在 options 中传递。

reasoning 是请求级能力开关。它只有在所选模型的 capabilities 标记支持时才会生效。

Tool calling 使用各公开协议的标准字段。如果请求包含标准 tool 字段,但所选模型没有暴露 capabilities.tools,API 会返回 tools_not_supported。

错误格式

Chat API 使用与媒体 API 相同的公开错误结构。

{
  "error": {
    "code": "missing_model",
    "message": "model is required."
  }
}

常见 Chat API 错误:

Code HTTP 含义
missing_api_key 401 未提供 API Key。
invalid_api_key 401 API Key 无效、未激活或已删除。
invalid_request_body 400 请求体不是 JSON object。
missing_model 400 缺少必填模型 key。
invalid_messages 400 没有提供有效消息。
invalid_message_role 400 消息 role 不是 system、user、assistant 或 tool。
unsupported_method 404 Gemini 兼容路由不是 :generateContent 或 :streamGenerateContent。
model_not_found 404 模型未激活、不存在,或不可作为 Chat 模型调用。
tools_not_supported 400 请求向不支持 tool calling 的模型传入了工具字段。
internal_error 500 服务端非预期错误。