TokenToSea开发者文档
控制台

用官方 SDK 接入

用 OpenAI SDK 调用 Chat Completions 与 Responses,用 Anthropic SDK 调用 Messages,并正确处理幂等键、流式输出和错误。

本页内容

对话类型号兼容三种主流协议,可以直接使用厂商官方 SDK,只需改 Base URL 和密钥。本页给出 Python 与 Node.js 的完整配置。

前提:已创建密钥并把它设置为环境变量 TOKENTOSEA_API_KEY。示例需要 Python 3.8+ 或 Node.js 18+,以及下文安装的 SDK。

协议端点SDKBase URL
OpenAI Chat CompletionsPOST /v1/chat/completionsopenai(Python / Node.js)https://api.tokentosea.com/v1
OpenAI Responses(无状态)POST /v1/responsesopenai(Python / Node.js)https://api.tokentosea.com/v1
Anthropic MessagesPOST /v1/messagesanthropic / @anthropic-ai/sdkhttps://api.tokentosea.com(不带 /v1)

我们用 OpenAI Python SDK 2.30、Anthropic Python SDK 1.16、openai Node.js 7.39 与 @anthropic-ai/sdk 0.136 核对过 SDK 发出的路径、请求头和请求体,与网关要求一致。图像、视频、语音、向量等其他接口没有对应的官方 SDK 方法,请直接用 HTTP 调用,示例见API 参考。

先确认型号支持这个协议

每个型号只开放逐项验收过的协议。例如 qwen3.8-flash 三种协议都支持,kimi-k2.6 只支持 Chat Completions 与 Messages。调用前在模型目录或 GET /v1/models 的 verified_endpoints 中确认,否则返回 422 endpoint_not_verified。

安装#

pip install openai anthropic

推荐的客户端配置#

三个设置对 TokenToSea 尤其重要:

  1. 显式传入 Idempotency-Key。不传时网关会自动生成一个,但如果连接在收到响应头前中断,你就拿不到这个键,也就无法取回结果。
  2. 关闭 SDK 自动重试(max_retries=0 / maxRetries: 0)。SDK 默认会在网络错误、超时以及 408、409、429、5xx 时自动重发。只有入口直接拒绝的错误带 x-should-retry: false,余额不足、并发已满、厂商 5xx 等经执行节点返回的错误都不带这个头,SDK 仍会重发;不传幂等键时,每次重发都会换一个新键,可能重复生成并计费。结果未知时应按幂等键查询结果,而不是重新生成。
  3. 足够长的超时。平台对单次上游调用最长等待 21 分钟;长输出或推理型号请把超时设到几分钟以上。

Chat Completions#

import os
import uuid

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["TOKENTOSEA_API_KEY"],
    base_url="https://api.tokentosea.com/v1",
    max_retries=0,
    timeout=600,
)

completion = client.chat.completions.create(
    model="qwen3.8-flash",
    messages=[
        {"role": "system", "content": "你是简洁的中文助手。"},
        {"role": "user", "content": "列出三种常见的排序算法及其时间复杂度。"},
    ],
    max_tokens=800,
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print(completion.choices[0].message.content)
print(completion.usage)

厂商专有参数#

部分型号支持厂商自己的参数,例如千问的 enable_thinking,DeepSeek、Kimi、豆包、MiniMax 的 thinking: {"type": "disabled"}。这些参数原样转发给厂商。OpenAI SDK 不认识的参数放在 extra_body(Python)或直接写进请求体(Node.js):

completion = client.chat.completions.create(
    model="qwen3.8-flash",
    messages=[{"role": "user", "content": "1+1 等于几?"}],
    max_tokens=64,
    extra_body={"enable_thinking": False},
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)

是否开启思考可能影响价格,某些型号对思考与非思考输出使用不同费率,见各型号页面的价格表。

Responses#

/v1/responses 是无状态的:平台始终以 store: false 转发。请求中出现 store: true、previous_response_id、conversation 或 background: true 都会返回 422 stateful_responses_not_supported。多轮对话请在 input 中自行携带历史消息。

response = client.responses.create(
    model="qwen3.8-flash",
    input=[
        {"role": "user", "content": "我叫小林。"},
        {"role": "assistant", "content": "你好,小林!"},
        {"role": "user", "content": "我叫什么名字?"},
    ],
    max_output_tokens=256,
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print(response.output_text)
print(response.usage)

Anthropic Messages#

Anthropic SDK 的 Base URL 是 https://api.tokentosea.com,SDK 会自行拼接 /v1/messages,并用 x-api-key 请求头携带密钥。max_tokens 为必填。

import os
import uuid

import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["TOKENTOSEA_API_KEY"],
    base_url="https://api.tokentosea.com",
    max_retries=0,
    timeout=600,
)

message = client.messages.create(
    model="qwen3.8-flash",
    max_tokens=800,
    system="你是简洁的中文助手。",
    messages=[{"role": "user", "content": "解释一下什么是幂等性。"}],
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print("".join(block.text for block in message.content if block.type == "text"))
print(message.usage)

自定义工具必须提供 name 与 input_schema。厂商托管的工具(如联网搜索)和 MCP 服务器没有单独定价,请求中出现时返回 422。

流式输出#

stream = client.chat.completions.create(
    model="qwen3.8-flash",
    messages=[{"role": "user", "content": "写一段 100 字左右的产品介绍。"}],
    max_tokens=400,
    stream=True,
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
usage = None
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        usage = chunk.usage
print("\n用量:", usage)

Chat Completions 流式请求会被平台自动加上 stream_options.include_usage = true,所以总能收到一个带 usage、choices 为空的分片。这个分片可能先于带 finish_reason 的分片到达,代码不要依赖两者的顺序。更多细节见流式输出。

读取请求编号#

响应头 X-Request-Id 回显本次的幂等键。需要读取响应头时:

raw = client.chat.completions.with_raw_response.create(
    model="qwen3.8-flash",
    messages=[{"role": "user", "content": "你好"}],
    max_tokens=64,
    extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print("X-Request-Id:", raw.headers.get("x-request-id"))
completion = raw.parse()

错误处理与 202#

平台错误体统一为 {"error": {"code": "…", "message": "…"}}(message 只在有经过脱敏的厂商说明时出现),SDK 会把它转成异常。处理时分三类:

情况SDK 中的表现做法
网络中断、超时APIConnectionError(含 APITimeoutError)结果未知:用原幂等键查询 /v1/results/{键}
5xx,或 409 request_already_accepted / request_already_dispatchedAPIStatusError / APIError结果未知:同上,不要换键重发
其他 4xxAPIStatusError / APIError平台明确拒绝、没有执行:修正请求后用新幂等键发起

另外,结果仍在结算或处理时,同步接口也会返回 202 和结果信封。SDK 把 202 当作成功响应解析:OpenAI Python SDK 得到的 completion.choices 为 None,Node.js SDK 得到的是信封本身。需要区分时,用 with_raw_response(Python)或 .withResponse()(Node.js)读取状态码:

import openai

ACCEPTED = {"request_already_accepted", "request_already_dispatched"}
request_key = str(uuid.uuid4())
try:
    raw = client.chat.completions.with_raw_response.create(
        model="qwen3.8-flash",
        messages=[{"role": "user", "content": "你好"}],
        max_tokens=64,
        extra_headers={"Idempotency-Key": request_key},
    )
except openai.APIConnectionError:
    print("网络中断或超时,结果未知:用原幂等键查询 /v1/results/" + request_key)
except openai.APIStatusError as error:
    if error.status_code >= 500 or error.code in ACCEPTED:
        print(f"HTTP {error.status_code} {error.code}:结果未知,用原幂等键查询 /v1/results/{request_key}")
    else:
        print(f"HTTP {error.status_code} {error.code}:未执行,修正后用新的幂等键发起")
else:
    if raw.status_code == 202:
        envelope = raw.http_response.json()  # 结果信封,不是 ChatCompletion
        print(f"处理中({envelope['status']}):用原幂等键查询 /v1/results/{request_key}")
    else:
        print(raw.parse().choices[0].message.content)

@anthropic-ai/sdk 的错误码在 error.error?.error?.code,用法与上面相同。查询与重发的完整实现见幂等与重试,状态码与错误码的完整含义见错误处理。

与官方服务的差异#

方面TokenToSea 的行为
响应体返回厂商原生响应,字段与各厂商实现一致,可能与 OpenAI / Anthropic 官方略有差异。
202 响应结果仍在结算或处理时,同步接口也可能返回 202 和结果信封;SDK 会把它当作成功响应解析,检测方法见上文。
自动重试经执行节点返回的错误不带 x-should-retry: false,SDK 默认会重发 409、429 与 5xx;请设置 max_retries=0 / maxRetries: 0。
费用响应中只有厂商 usage,没有费用字段;金额在控制台「账单」查看。
状态型功能Responses 不保存会话;不支持后台任务、文件检索等依赖服务端状态的功能。
托管工具联网搜索、代码执行、MCP 服务器等厂商托管工具未开放(422)。函数调用(function / custom 工具)可用。
缓存隐式缓存按厂商返回的命中量计费;显式缓存(cache_control)只在已单独定价的型号上开放。
输出上限未设置 max_tokens / max_completion_tokens / max_output_tokens 时,平台按型号默认值(通常为 4096)补上。
查询参数推理接口不接受 URL 查询参数(400 query_parameters_not_supported)。

下一步#

    输入关键词搜索全部文档与模型。