土土金 Tutujin API › SDK 迁移

OpenAI API 国内怎么调用:只改一行 base_url

不重写业务逻辑、不装代理客户端、不需要海外信用卡。三段可直接复制的前后对照,外加一张能自证「路由是真的」的实测表。

实测时间 2026-08-20 · 网关地址 https://api.tutujin.com

先给结论

把 SDK 的 base_url 改成 https://api.tutujin.com/v1,把 key 换成控制台里生成的令牌,其余代码一行不动——这就是全部。

之所以能这么干,是因为服务端实现的是 OpenAI 协议本身,不是某个 SDK 的包装层:/v1/chat/completions/v1/images/generations/v1/embeddings/v1/messages 都是真实存在的路由(下面第五节有可复现的验证方法)。

一、一分钟版:三段前后对照

Python(openai SDK v1.x)

from openai import OpenAI

client = OpenAI(
-   api_key="sk-你的-openai-key",
-   # base_url 默认 https://api.openai.com/v1
+   api_key="你的土土金令牌",
+   base_url="https://api.tutujin.com/v1",
)

resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)

Node.js(openai v4/v5)

import OpenAI from "openai";

const client = new OpenAI({
- apiKey: process.env.OPENAI_API_KEY,
+ apiKey: process.env.TUTUJIN_KEY,
+ baseURL: "https://api.tutujin.com/v1",
});

const r = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "你好" }],
});
console.log(r.choices[0].message.content);

curl

curl https://api.tutujin.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TUTUJIN_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "你好"}]
  }'

二、base_url 到底该不该带 /v1(最高频踩坑)

这一条踩的人最多,因为不同工具的约定正好相反

场景正确写法说明
OpenAI 官方 SDK(Python / Node)https://api.tutujin.com/v1要带 /v1,SDK 会在其后拼 /chat/completions
curl / 自己写 HTTP 请求https://api.tutujin.com/v1/chat/completions写完整路径
多数第三方客户端(LobeChat 等)https://api.tutujin.com/v1同官方 SDK 约定
Claude Code 的 ANTHROPIC_BASE_URLhttps://api.tutujin.com不要带 /v1,它自己会拼 /v1/messages,详见 Claude Code 那页

三种典型错法:写成 https://api.tutujin.com(少了 /v1,SDK 会请求到 /chat/completions)→ 404;写成 https://api.tutujin.com/v1/chat/completions 却又用 SDK(SDK 再拼一次)→ 404;结尾多写一个斜杠 /v1/,部分 SDK 会拼出 //chat/completions → 404。凡是 404,先怀疑 base_url,不要怀疑 key。

三、openai SDK v0.x 与 v1.x 的写法差异

很多老项目还停在 v0.28 的写法,迁移方式不一样:

v0.x(≤0.28)v1.x(≥1.0)
配置方式模块级全局变量实例化 OpenAI() 客户端
地址字段openai.api_basebase_url
key 字段openai.api_keyapi_key
调用openai.ChatCompletion.create(...)client.chat.completions.create(...)
取结果resp["choices"][0]["message"]["content"]resp.choices[0].message.content
# v0.x 老项目的最小改法(不升级 SDK 也能切过来)
import openai
openai.api_key  = "你的土土金令牌"
openai.api_base = "https://api.tutujin.com/v1"

r = openai.ChatCompletion.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "你好"}],
)
print(r["choices"][0]["message"]["content"])

注意字段名是 api_base 不是 base_url——把 v1.x 的字段名抄进 v0.x 代码里,是另一个常见的「改了没生效」原因。

四、怎么拿到 key

  1. 注册:打开 https://api.tutujin.com/,用邮箱注册。当前只开放邮箱注册——微信、GitHub、Telegram、Discord、OIDC、Passkey 登录在服务端配置里全部为关闭状态,所以不必去找「微信一键登录」入口。
  2. 验证邮箱:站点开启了邮箱验证(email_verification: true),收验证码填入即可。
  3. 创建令牌:控制台 → 令牌 → 添加新令牌。可以给单个令牌设置额度上限,也可以设为无限;建议按项目分别建令牌,方便按项目看用量。
  4. 充值:按人民币充值额度,500000 quota = 1 美元额度。具体可用的支付渠道与当时单价,以控制台充值页显示为准。

额度换算与倍率的完整算法,见计费拆解那一页

五、路由实证:怎么确认「协议兼容」不是嘴上说说

这一点你可以自己验,不需要有效 key。用一个故意写错的 key 去打各个路径,看返回码:

curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  https://api.tutujin.com/v1/chat/completions \
  -H "Authorization: Bearer sk-invalid-probe-000" \
  -H "Content-Type: application/json" -d '{}'

2026-08-20 实测结果:

路径无效 key 的返回说明
/v1/chat/completions401 new_api_error真实路由(对话)
/v1/images/generations401 new_api_error真实路由(生图)
/v1/embeddings401 new_api_error真实路由(向量)
/v1/messages401 new_api_error真实路由(Anthropic 原生协议)
/v1beta/models404 Invalid URL对照组:不存在的路由长这样

差别在于:真实路由会先做鉴权再拒绝你(401),不存在的路由直接告诉你 URL 无效(404)。这是判断「一个网关到底实现了哪些接口」最省事的办法,对任何中转站都适用。

六、流式、函数调用与其它字段

网关按 OpenAI 协议转发请求体,streamtoolstool_choiceresponse_formattemperature 等字段照常传递,SSE 流式响应结构不变:

r = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "写一首俳句"}],
    stream=True,
)
for chunk in r:
    print(chunk.choices[0].delta.content or "", end="")

但要说清楚边界:某个字段最终是否生效,取决于该模型自身与其上游通道,不是网关能替所有模型打包票的事。尤其是按次计费(quota_type=1)的聚合型条目,行为可能与官方直连不同。接入生产前,请用你的真实请求先跑一次。

七、报错速查表

现象最可能的原因怎么修
401 Invalid token令牌错、被删、额度耗尽,或请求头格式不对确认 Authorization: Bearer <令牌>;到控制台确认令牌状态与余额
404 Invalid URLbase_url 路径拼错(多写 / 少写 /v1对照上面第二节的写法表
提示模型不存在 / 无权限模型名拼错,或该模型不在你的分组模型与分组对照表;模型名要写全(含日期后缀)
429触发限流降低并发、加退避重试;并发上限相关问题请联系客服确认
响应是 HTML 而不是 JSON请求打到了网页而不是 API(通常还是 base_url 问题)确认路径以 /v1 开头

八、不想写代码:现成客户端一键接入

服务端配置里内置了几个客户端的一键导入模板,把 {key} 换成你的令牌、{address} 换成 https://api.tutujin.com 即可:

客户端接入方式
ChatGPT Next WebURL 参数导入 settings={"key":"...","url":"..."}
LobeChatkeyVaults.openai.apiKey + baseURL(记得带 /v1
AI as Workspaceprovider=openaicompatibility: strict
AMA 问天ama://set-api-key?server=...&key=...
OpenCatopencat://team/join?domain=...&token=...

编辑器场景另有两条路:Cursor 自定义 Base URL(注意它有覆盖不到的功能)与 Claude Code 走 ANTHROPIC_BASE_URL

常见问题

base_url 要不要带 /v1?

OpenAI SDK 要带(https://api.tutujin.com/v1);curl 写完整路径;Claude Code 的 ANTHROPIC_BASE_URL 相反,不要带 /v1。这是两类工具最容易互相串味的地方。

业务代码要改吗?

不用改。请求体与响应体结构不变,只替换 base_urlapi_key 两个值。模型名建议同时确认一遍——部分模型名带日期后缀,写短了会报模型不存在。

支持流式输出和 function calling 吗?

协议层按 OpenAI 规范透传。是否真正生效取决于你选的那个模型与其通道,建议接入后用真实请求自测一次,我们不替所有模型做统一承诺。

没有海外账号和信用卡能注册吗?

可以。注册只需要能收验证码的邮箱,国内可直连访问,按人民币充值额度。具体支付渠道以充值页显示为准。

报 401 先查什么?

先看响应体的 type 字段:出现 new_api_error 说明请求已经到达网关、是鉴权被拒(key 的问题),而不是网络或域名的问题。然后依次查:请求头格式 → 令牌是否有效 → 余额 → 模型是否在你的分组。