GEMINI-COMPATIBLE / NATIVE REST

用 Gemini 原生 REST 接入 JBB:原生格式与兼容限制

使用 Gemini 的 contents / parts 请求形状访问 JBB 的 v1beta 路由。路由、认证与字段接收边界已有证据;本轮没有使用有效 Key,也没有发起付费模型调用,因此逐模型端到端能力仍未验证。

CONTRACT

兼容的是 Gemini 原生请求形状,不是 Google 控制面的复制

JBB 接受 Gemini 原生 v1beta 路由与核心 JSON 字段。公开目录当前声明 11 个模型带有 Gemini endpoint 标记,但这不是每个模型对流式、工具、多模态、安全设置或缓存均可用的证明。

01原生 envelope

对话使用 contents[].parts[],系统指令、生成配置与安全设置保持 Gemini 字段名。

02证据到认证边界

生成、流式与 token 计数均到达 TokenAuth 并返回 401;没有有效 Key 或付费调用记录。

03逐模型验证

路由存在不等于响应形状、SSE、工具循环、usage 与计费已端到端通过。

品牌边界

Gemini-compatible 是协议兼容描述,不代表 JBB 与 Google 存在官方合作、授权、背书或完整功能等价关系。

ENDPOINT EVIDENCE

生成、流式与计数已到认证边界,成功响应仍未验证

2026-07-15 的源码、公开价格目录与生产探测确认了以下边界。本轮 未使用有效 Key、未发起付费调用,逐模型 E2E 未验证;401 只说明请求进入认证链。

端点证据级别当前边界
GET /v1beta/models路由已验证源码注册 Gemini 模型列表;无有效凭证返回 401。公开目录当前声明 11 个 Gemini endpoint 模型。
POST /v1beta/models/{model}:generateContent认证边界原生 relay 路由与字段 DTO 已确认;无凭证生产请求返回 401,未验证模型成功响应。
POST /v1beta/models/{model}:streamGenerateContent?alt=sse仅路由 / 认证请求返回 401;SSE Content-Type、事件增量与终止行为没有使用有效 Key 验证。
POST /v1beta/models/{model}:countTokens仅路由 / 认证请求返回 401;只证明 route/auth,不证明模型级 token 计数结果。
GET / POST /v1beta/cachedContents当前 404独立缓存资源的 list/create 均返回 404,不得宣传 standalone cachedContents 管理。
OPTIONS ...:generateContent当前 404不要假设浏览器 CORS 预检可用;生产调用应从服务端发起。

Base URL 固定为站点 origin:https://downstream.jbbtoken.cn。把 /v1beta/models/... 放在每个 REST route 中,不要把 /v1beta 全局追加到 Base URL。

AUTH & DIRECT REST

优先发布 direct REST;三种 JBB Key 传递方式均可用

原生 Google 文档通常使用 x-goog-api-key?key=;JBB 的 TokenAuth 还接受 Authorization: Bearer。Key 只放在服务端环境变量中,查询参数可能进入代理日志,优先使用 header。

shell · 环境变量
export JBB_API_KEY="<YOUR_API_KEY>"
export JBB_BASE_URL="https://downstream.jbbtoken.cn"
export JBB_MODEL="<E2E_TESTED_GEMINI_MODEL_ID>"
cURL · x-goog-api-key
curl "$JBB_BASE_URL/v1beta/models/$JBB_MODEL:generateContent" \
  -H "x-goog-api-key: $JBB_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "systemInstruction": {"parts": [{"text": "Answer concisely."}]},
    "contents": [{"role": "user", "parts": [{"text": "Reply with OK"}]}],
    "generationConfig": {"temperature": 0.2, "maxOutputTokens": 128}
  }'
Python · urllib (direct REST)
import json
import os
import urllib.parse
import urllib.request

base = os.getenv("JBB_BASE_URL", "https://downstream.jbbtoken.cn")
model = urllib.parse.quote(os.environ["JBB_MODEL"], safe="")
url = f"{base}/v1beta/models/{model}:generateContent"
body = {
    "contents": [{"role": "user", "parts": [{"text": "Reply with OK"}]}],
    "generationConfig": {"temperature": 0.2, "maxOutputTokens": 128},
}
request = urllib.request.Request(
    url,
    data=json.dumps(body).encode(),
    headers={
        "content-type": "application/json",
        "x-goog-api-key": os.environ["JBB_API_KEY"],
    },
)
with urllib.request.urlopen(request, timeout=60) as response:
    print(response.read().decode())
JavaScript · fetch (direct REST)
const base = process.env.JBB_BASE_URL ??
  "https://downstream.jbbtoken.cn";
const model = encodeURIComponent(process.env.JBB_MODEL);
const response = await fetch(
  `${base}/v1beta/models/${model}:generateContent`,
  {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-goog-api-key": process.env.JBB_API_KEY,
    },
    body: JSON.stringify({
      contents: [{ role: "user", parts: [{ text: "Reply with OK" }] }],
      generationConfig: { temperature: 0.2, maxOutputTokens: 128 },
    }),
  },
);
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());
  • ?key=$JBB_API_KEY 可作为查询参数认证,但要评估 URL 日志泄漏风险。
  • Authorization: Bearer $JBB_API_KEY 是 JBB 兼容选项,不是 Gemini 原生文档的默认 API-key 写法。
  • 不要把 Google Gen AI SDK custom base URL 示例发布成“已验证 JBB 集成”;本页只给 direct REST 路径。

NATIVE ENVELOPE

核心结构是 contents / parts,系统指令与控制项位于顶层

原生 JSON 使用 camelCase systemInstruction。JBB DTO 同时接收 system_instruction,但 raw REST 示例应保持官方 camelCase。字段被 DTO 接收不代表每个上游模型都会执行这些能力。

JSON · 原生请求字段
{
  "systemInstruction": {
    "parts": [{"text": "Answer in Chinese."}]
  },
  "contents": [{
    "role": "user",
    "parts": [{"text": "Explain retry with jitter."}]
  }],
  "generationConfig": {
    "temperature": 0.2,
    "maxOutputTokens": 256
  },
  "safetySettings": []
}
  • contents[] 表示对话 turn;每个 turn 的有序 parts[] 可承载 text 等原生 Part。
  • systemInstruction 不放入 OpenAI messages[] 或 Claude system block。
  • generationConfigsafetySettings 已进入 DTO;具体参数、类别和模型行为逐项验证。
  • 多模态 Part 字段存在于协议并不证明 JBB 的每个 Gemini endpoint 模型均端到端支持。

STREAM · COUNT · TOOLS · CACHE

高级字段可以进入请求;执行、命中和返回形状仍需实测

cURL · SSE 路由
curl --no-buffer \
  "$JBB_BASE_URL/v1beta/models/$JBB_MODEL:streamGenerateContent?alt=sse" \
  -H "Authorization: Bearer $JBB_API_KEY" \
  -H "content-type: application/json" \
  -d '{"contents":[{"role":"user","parts":[{"text":"Count to three"}]}]}'
cURL · countTokens(仅 route/auth 已验证)
curl "$JBB_BASE_URL/v1beta/models/$JBB_MODEL:countTokens?key=$JBB_API_KEY" \
  -H "content-type: application/json" \
  -d '{"contents":[{"role":"user","parts":[{"text":"Count these tokens"}]}]}'
JSON · functionDeclarations
{
  "contents": [{"role": "user", "parts": [{"text": "上海现在几点?"}]}],
  "tools": [{
    "functionDeclarations": [{
      "name": "get_time",
      "description": "Return local time for an IANA timezone",
      "parameters": {
        "type": "object",
        "properties": {"timezone": {"type": "string"}},
        "required": ["timezone"]
      }
    }]
  }]
}
  • streamGenerateContent?alt=sse 只完成 route/auth 探测;上线前验证 SSE Content-Type、增量事件、终止与错误帧。
  • countTokens 目前只验证 route/auth;不得写成模型级计数已通过。
  • 模型可返回 functionCall;客户端负责校验参数、执行函数,再发送 functionResponse。JBB 或模型不会替应用执行声明的函数。
  • standalone cachedContents create/list 当前返回 404。请求字段 cachedContent 虽被 DTO 接收,但创建、命中、usage 与计费未端到端验证。

DIFFERENCES

Gemini 原生、OpenAI-compatible 与 Claude-compatible 是三套入口

  • Gemini 原生

    使用 /v1beta/models/{model}:actioncontents[].parts[];API Key 常用 x-goog-api-key?key=

  • OpenAI-compatible

    使用 /v1/chat/completions 等路由、Bearer 认证与 messages[]。迁移规则见OpenAI-compatible 页面

  • Claude-compatible

    使用 /v1/messagesx-api-key、Anthropic version 与 Claude content blocks。边界见Claude-compatible 页面

  • 模型与能力

    同一个模型名称出现在目录中,不代表三套协议的所有字段、stream、tools 与计费行为完全等价。

  • SDK 边界

    官方 SDK 暴露 custom base URL 配置,不等于 JBB 已验证其路径拼接、认证注入、SSE、缓存、文件和工具全流程。

ERRORS & RETRIES

先分清认证、路径、请求形状与上游错误,再决定重试

  • 401
    认证失败

    检查 JBB Key、header 名、查询参数、余额和权限。当前 401 证据不代表模型调用成功。

  • 404
    路径或资源不存在

    检查 Base URL 是否错误追加 /v1beta;standalone cachedContents 与 OPTIONS 当前明确返回 404。

  • 400
    请求形状或模型不接受

    核对 camelCase 字段、contents、Part 类型、工具 Schema、模型 ID 与参数范围。

  • 429
    额度或频率受限

    核对 Key 与分组限制;只对幂等或可安全重放的请求做有上限的指数退避与 jitter。

  • 5xx
    网关或上游失败

    保存请求 ID 和错误正文;设置连接与总超时,有限重试并避免重复产生副作用。

PRODUCTION GATE

上线前完成九项检查

  • JBB Key 只存于服务端环境变量或 Secret Manager,不放入浏览器 bundle。
  • Base URL 固定为 https://downstream.jbbtoken.cn,每条 route 自带 /v1beta
  • 优先使用 x-goog-api-key 或 Bearer header;使用 ?key= 时控制 URL 日志。
  • 目标模型已用最小额度完成 generateContent 端到端验证并保存响应。
  • 流式逐项验证 SSE Content-Type、增量、终止、取消和错误处理。
  • countTokens 的输入形状与返回值按目标模型实测,不依赖本轮 401。
  • 工具参数按不可信输入处理;设置 Schema、权限、超时、大小和循环上限。
  • 不依赖 standalone cachedContents;如使用 cachedContent 字段,先验证创建链、命中、usage 与计费。
  • 记录请求 ID、HTTP 状态、模型、关键参数、usage、延迟与实际计费;429/5xx 使用有限退避。