---
title: "Gemini"
description: "用 Google GenAI SDK 或 REST 调用 pirouter 上接受 Gemini 协议的模型。本页说明 generateContent 与 streamGenerateContent 怎么调、SDK 要加哪个请求头、为什么只带 x-goog-api-key 会返回 401，以及和 Google 官方行为的差异。"
canonical: "https://pirouter.ai/zh/docs/protocols/gemini"
last-updated: "2026-10-17"
lang: "zh"
source: "content/docs/zh/(start)/protocols/gemini.mdx"
---

# Gemini

用 Google GenAI SDK 或 REST 调用 pirouter 上接受 Gemini 协议的模型。本页说明 generateContent 与 streamGenerateContent 怎么调、SDK 要加哪个请求头、为什么只带 x-goog-api-key 会返回 401，以及和 Google 官方行为的差异。

用 Google GenAI SDK 或 REST 调用 pirouter 上接受 Gemini 协议的模型。和直接调 Google 有一处必须改：key 要放在 `Authorization` 请求头里。

## 用 REST 调用

Gemini 协议有两个动作，是同一个端点：

| 动作                                                  | 用途       |
| --------------------------------------------------- | -------- |
| `POST /v1beta/models/{model}:generateContent`       | 一次返回整个回答 |
| `POST /v1beta/models/{model}:streamGenerateContent` | 流式返回     |

模型 ID 写在路径里，写完整的 `vendor/model`，中间的斜杠原样保留，例如 `/v1beta/models/google/gemini-3.5-flash:generateContent`。pirouter 不会替你补厂商前缀。

cURL:

```bash
curl "https://api.pirouter.ai/v1beta/models/google/gemini-3.5-flash:generateContent" \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{ "parts": [{ "text": "Hello!" }] }]
  }'
```

Python:

```python
import os
from google import genai
from google.genai import types

client = genai.Client(
    api_key=os.environ["PIROUTER_API_KEY"],
    http_options=types.HttpOptions(
        base_url="https://api.pirouter.ai",
        headers={"Authorization": f"Bearer {os.environ['PIROUTER_API_KEY']}"},
    ),
)

response = client.models.generate_content(
    model="google/gemini-3.5-flash",
    contents="Hello!",
)
print(response.text)
```

TypeScript:

```ts
import { GoogleGenAI } from '@google/genai'

const ai = new GoogleGenAI({
  apiKey: process.env.PIROUTER_API_KEY,
  httpOptions: {
    baseUrl: 'https://api.pirouter.ai',
    headers: { Authorization: `Bearer ${process.env.PIROUTER_API_KEY}` },
  },
})

const response = await ai.models.generateContent({
  model: 'google/gemini-3.5-flash',
  contents: 'Hello!',
})
console.log(response.text)
```

你应该看到一个 JSON 响应，回答在 `candidates[0].content.parts[0].text` 里。在控制台的 **日志** 里能找到这次请求。

要流式输出，把 `generateContent` 换成 `streamGenerateContent`。请求体不变，不需要 `stream` 字段：

```bash
curl -N "https://api.pirouter.ai/v1beta/models/google/gemini-3.5-flash:streamGenerateContent" \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{ "parts": [{ "text": "Hello!" }] }]
  }'
```

你应该看到一行行 `data: ` 事件，每个事件在 `candidates` 里带一段回答。最后一个事件带 `finishReason` 和 `usageMetadata`，之后没有单独的结束标记。带不带 `?alt=sse`，返回的都是这样的事件流。

pirouter 只把路径里的模型换成 provider 的模型名，请求体除了去掉 `provider` 这类路由字段，其余原样转发。

## 用 Google GenAI SDK

创建客户端时改两处：

1. base URL 填 `https://api.pirouter.ai`。不要设 API 版本，SDK 默认会拼上 `/v1beta`。
2. 在 `http_options`（TypeScript 是 `httpOptions`）的 `headers` 里加 `Authorization: Bearer` 请求头。SDK 的 `api_key` 参数照常传。

上面 Python 和 TypeScript 两个 Tab 就是这样写的。

## 为什么只带 x-goog-api-key 会返回 401

pirouter 只从 `Authorization` 和 `X-Api-Key` 里读 key，不读 `x-goog-api-key`，也不读查询参数 `?key=`。这两处的值在转发前会被删掉。所以只靠 SDK 默认的请求头，或者照 Google 的 REST 示例写：

```bash
curl "https://api.pirouter.ai/v1beta/models/google/gemini-3.5-flash:generateContent" \
  -H "x-goog-api-key: $PIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{ "parts": [{ "text": "Hello!" }] }]
  }'
```

会得到 `401`：

```json
{
  "error": {
    "message": "You didn't provide an API key. Provide it in an Authorization header using Bearer auth (Authorization: Bearer YOUR_KEY).",
    "type": "invalid_request_error",
    "code": "invalid_api_key"
  }
}
```

把 key 放进 `Authorization: Bearer` 就能通过。`Authorization` 和 `x-goog-api-key` 同时带时以 `Authorization` 为准，所以 SDK 默认带上的 `x-goog-api-key` 不用去掉。读取规则见[在请求里带上 key](https://pirouter.ai/zh/docs/authentication.md#在请求里带上-key)。

## 哪些模型能用

接受 Gemini 协议的有 Google 的 Gemini 系列，包括几个图像生成模型。一个模型接不接受，看 `GET /v1/models/{vendor}/{model}/endpoints` 返回的 `protocols` 里有没有 `gemini`，或者在[模型列表](https://pirouter.ai/zh/models)里看每个模型的协议。图像模型怎么调见[生成与编辑图片](https://pirouter.ai/zh/docs/images.md)。

## 与 Google 官方行为的差异

| 方面                  | pirouter 的行为                                                                                                                                |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 鉴权                  | 不读 `x-goog-api-key` 和 `?key=`，见上文                                                                                                           |
| 响应里的 `modelVersion` | 改写为 pirouter 的模型 ID（`vendor/model`）。provider 自己报的名字在响应头 `X-Pi-Upstream-Model` 里                                                             |
| 上游请求 ID             | 部分 provider 不返回请求 ID，这时响应没有 `X-Pi-Upstream-Request-Id`                                                                                      |
| 错误体                 | pirouter 自己的错误是 `{"error": {"message", "type", "code"}}`，`code` 是字符串错误码，见[错误码](https://pirouter.ai/zh/docs/errors.md)。provider 自己返回的错误照原样转交 |
| 失败重试                | provider 在返回第一个字节之前失败时，pirouter 自动换下一家，见[失败时自动换一家](https://pirouter.ai/zh/docs/routing.md#失败时自动换一家)                                         |

## 目前没有的能力

下面这些 Gemini 接口 pirouter 目前没有：

- `countTokens`。调用 `POST /v1beta/models/{model}:countTokens` 返回 `400`，错误码 `invalid_request`，`message` 是 `model is required`。这个错误说的不是你的请求缺字段，而是 pirouter 不提供这个动作。
- `embedContent` 等其它动作。

## 下一步

- [OpenAI 兼容接口](https://pirouter.ai/zh/docs/protocols/openai.md): 用官方 OpenAI SDK 调用 OpenAI 协议的模型。
- [鉴权与 API key](https://pirouter.ai/zh/docs/authentication.md): key 放在哪个请求头，怎么创建和吊销。
