接入文档
OpenAI 完全兼容 把 base_url 换成 你的域名/v1、api_key 换成我们发的密钥, 客户端代码几乎不用改。响应结构、错误结构、用量字段全部对齐。

快速开始

Python(OpenAI SDK)
pip install openai

from openai import OpenAI

client = OpenAI(
    api_key="sk-relay-你的密钥",
    base_url="https://你的域名/v1",
)

resp = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[
        {"role": "system", "content": "你是一个助手"},
        {"role": "user", "content": "用一句话介绍你自己"},
    ],
    max_tokens=500,
)
print(resp.choices[0].message.content)
print("本次消费:", resp.model_extra.get("relay_usage"))
Node.js
const OpenAI = require('openai');

const client = new OpenAI({
  apiKey: 'sk-relay-你的密钥',
  baseURL: 'https://你的域名/v1',
});

const resp = await client.chat.completions.create({
  model: 'gpt-5.6-terra',
  messages: [{ role: 'user', content: '你好' }],
});
console.log(resp.choices[0].message.content);
curl
curl -X POST https://你的域名/v1/chat/completions \
  -H "Authorization: Bearer sk-relay-你的密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.6-terra",
    "messages": [{"role": "user", "content": "你好"}]
  }'

鉴权

有两种传法,任选其一:

  • Authorization: Bearer sk-relay-xxx(OpenAI 标准,推荐)
  • Authorization: sk-relay-xxx 或 X-API-Key: sk-relay-xxx
密钥只在创建时显示一次 为保障安全,平台不保存密钥原文,关闭后无法再次查看。丢失请删除重建。

对话补全

POST /v1/chat/completions

请求参数

参数类型必填说明
modelstring是模型名,取自 /v1/models
messagesarray是标准 OpenAI 消息格式
max_tokensint否最大生成 token 数
temperaturenumber否0~2,部分模型不支持
streambool否流式输出

响应中的计费信息

响应体额外带一个 relay_usage 字段,让你能实时看到本次调用花了多少钱:

{
  "id": "chatcmpl-xxx",
  "model": "gpt-5.6-terra",
  "choices": [{ "message": { "role": "assistant", "content": "你好" }, "finish_reason": "stop" }],
  "usage": { "prompt_tokens": 8, "completion_tokens": 2, "total_tokens": 10 },

  // 平台追加字段
  "relay_usage": {
    "request_id": "req_a1b2c3",
    "sale": "0.00000100",   // 从你余额扣除的金额(= 你实际付的钱)
    "unit": "per_1m_token"
  }
}

模型列表

GET/v1/models

返回当前所有可调用模型及其售价,格式与 OpenAI 一致,额外携带计费信息:

{
  "object": "list",
  "data": [{
    "id": "gpt-5.6-terra",
    "object": "model",
    "owned_by": "tugou-ai",
    "relay": {
      "billing_unit": "per_1m_token",
      "sale_price": "0.00000840"
    }
  }]
}
售价以本接口返回为准 平台价格可能因供应方调价而调整。生产环境建议启动时拉一次本接口缓存模型与价格, 避免用户看到的价格与你本地硬编码的不一致。
同一模型名只会出现一次 平台会自动为每个模型选择最优线路,你看到的名称与价格就是最终计费口径, 不存在同一个名字两个价格的情况。

异步任务(视频 / 图片生成)

视频、音乐、数字人等生成任务耗时较长,走异步协议:提交拿任务号 → 轮询查状态 → 取结果。

POST/v1/async/submit
POST /v1/async/submit
{
  "model": "可灵文生视频",
  "params": {
    "prompt": "一只猫在草地上奔跑",
    "duration": 5
  }
}

// 响应
{
  "request_id": "req_xxx",
  "status": "submitted",
  "upstream_task_id": "task_abc123"
}
资金时点 提交时按最大可能用量预扣(如按秒计费的模型按 60 秒封顶预扣); 成功时按实际用量结算并退回差额;失败则全额退回,你不会为失败的任务付费。
GET/v1/async/{request_id}
{
  "request_id": "req_xxx",
  "status": "success",          // submitted / running / success / failed / timeout
  "progress": 100,
  "result_url": "https://.../output.mp4",
  "reserved_amount": "3.00",    // 预占
  "settled_amount": "0.60",     // 实际结算
  "refunded": "2.40"            // 已退回
}

轮询建议

  • 视频类任务建议每 5~10 秒轮询一次,不要秒级轮询
  • 轮询到 success / failed / timeout 即停止
  • 建议加指数退避:5s → 10s → 20s → 30s(上限 30s)

错误码

错误响应统一为 OpenAI 格式,客户端 SDK 能直接解析:

{
  "error": {
    "message": "余额不足,当前可用 ¥0.50,本次需要 ¥1.20",
    "type": "insufficient_balance",
    "code": "insufficient_balance",
    "request_id": "req_xxx"
  }
}
HTTPcode含义与处理
400invalid_request参数缺失或非法,检查请求体
401invalid_api_key密钥错误、已禁用或已过期
402insufficient_balance 余额不足。充值后重试 —— 这类请求不会产生任何调用,你不会为失败的调用付费
403model_not_allowed该密钥无权调用此模型(检查密钥的模型白名单)
404model_not_found模型不存在或未上架
429rate_limited触发限流,指数退避后重试
502upstream_error模型服务异常,费用已退回,请稍后重试
503upstream_unavailable模型服务暂不可用,费用已退回
429 / 502 / 503 都可以安全重试 这三类错误不会扣你的钱(预占已释放)。建议重试策略:最多 3 次,间隔 1s / 3s / 9s。

计费与余额

  • 先充值后调用:余额不足时会拒绝请求,不会产生调用与费用
  • 最低充值 ¥1,人民币现金计价,没有平台虚拟币
  • 扣费时机:调用前按预估量预扣,返回后按实际用量结算并退差额
  • 单次调用可低至万分之一分钱,控制台可查看每一笔明细

计费单位有三种:per_1m_token(每百万 token)、 per_call(每次)、per_second(每秒)。 具体每个模型的计费单位见 /v1/models 返回的 relay.billing_unit。

幂等与重试

网络超时后重试,最怕的是重复扣费。加一个 Idempotency-Key 头即可:

headers = {
  "Authorization": "Bearer sk-relay-xxx",
  "Idempotency-Key": "order-20240101-001",   # 你的业务唯一标识
}

# 带相同 Idempotency-Key 重试时:
#   - 不会重复调用(不会二次消耗算力额度)
#   - 不会重复扣费
#   - 直接返回首次的结果
务必使用业务维度的唯一标识 比如订单号 + 接口名。不要用随机 UUID —— 那样每次重试都会被当成新请求, 反而绕过了幂等保护。

常见问题

为什么余额明明够,却提示 402?

可动用金额 = 账户余额 − 在途占用(已提交但尚未返回的请求)。 如果有并发的长耗时请求(尤其视频生成),它们会占用一部分额度。 控制台「钱包」页会单独显示"在途占用",等任务完成就会释放。

调用失败了会扣钱吗?

不会。余额不足(402)不会产生调用;服务异常(502/503)会退回全部预扣。 唯一会扣钱的是成功返回了结果的调用。控制台的用量明细里, 失败记录的"消费"列都是 0。

支持哪些模型?

见首页模型广场或调用 GET /v1/models。 模型名沿用原始名称,没有做别名映射 —— 你在控制台看到的名字就是调用时该用的名字。

可以开发票吗?

充值后联系客服即可。请注意余额按实际消耗扣除,未消费部分可申请退回。

模型名怎么查?

curl https://你的域名/v1/models \
  -H "Authorization: Bearer sk-relay-你的密钥"
还有疑问? 带上你的 request_id(响应头 X-Request-Id 里也有)联系客服, 我们能精确定位到这一笔调用的完整链路。