BazaarLinkBazaarLink
登入
文件API 参考SDK 参考Agent 应用AI Skills

BazaarLink 开发文档

BazaarLink 是台湾的统一 AI API 闸道器 — 透过单一、与 OpenAI 相容的 API 端点,提供对 OpenAI、Anthropic、Google、Meta 等数百个模型的存取。

AI Agent Skill 档案
将我们的 skill 档案载入您的 AI 助理(Claude、Cursor、Copilot…),让它完整了解 BazaarLink API:
Read https://bazaarlink.ai/skill.md and follow the instructions to integrate BazaarLink into your app.
免费模型与速率限制
想了解免费模型、每分钟请求上限与免费额度?请见 速率限制 · 常见问题

收费标准

BazaarLink 的模型用量采零加成计价(与上游供应商官方牌价相同);平台费用于「充值(入金)」时收取:10% 交易费,台币渠道另计 5% 营业税。以美元记账、提供台币报价与电子统一发票。支持自助式 pay as you go 储值,企业亦可洽谈月结账务(Net-30,可议)。

运作方式

  • 消耗(扣款):每一次 API 呼叫按实际 token 用量,以上游供应商的官方美元牌价从您的帐户余额扣款;模型零加成、消耗端不再加收任何费用。
  • 充值(入金):以当下「台币兑美元即时卖出汇率」将新台币换算成美元存入余额;入金时收取 10% 交易费。
  • • 信用卡充值:另收 US$0.60 固定手续费,并开立收据。
  • • 台币渠道:另依法计 5% 营业税,并开立台湾电子统一发票。
  • • 银行电汇:大额或企业充值请联系我们安排电汇与定制发票。
  • 发票:支持电子统一发票,符合台湾企业报账流程;需要采购流程或月结账务的公司可洽谈企业账务条件(Net-30,可议)。
举例
以充值 US$10.00 为例:台币渠道 = $10.00 + 10% 交易费 US$1.00 + 5% 营业税 US$0.55 = US$11.55(开立统一发票);信用卡 = $10.00 + 交易费 US$1.00 + 固定手续费 US$0.60 = US$11.60。入金后您的 US$10.00 余额按官方牌价扣用、消耗端不再加价。

关于汇率

外币换算采即时汇率;月结以报账(结算)时汇率为准,储值入金则以入金当下汇率换算为账户余额。汇率与时间随账务留存以供查核。

失败请求不收费(Zero Completion Insurance)

如果上游请求失败,并且没有可结算的用量数据,BazaarLink 会自动退回全部预扣款。即使串流已经开始、途中才中断,该次扣款仍为 0 美元。

哪些情况不收费
无需开启任何设置,所有公开推理与媒体 API 都会自动应用。即使上游供应商已向 BazaarLink 收费,BazaarLink 也可能自行承担这笔失败成本,不会转嫁给你。
  • 上游无法连接、拒绝请求,或没有返回可用结果
  • 串流在收到最终用量数据前中断,即使此前已返回部分内容
  • 响应没有 usage,或 usage 是所有数值都为 0 的空数据

output tokens 为 0,不代表一定免费

如果请求正常完成,并且供应商返回有效的 usage,BazaarLink 仍会按该用量结算。不要只看 output tokens 判断是否免费:即使 output tokens 为 0,只要仍有 input tokens 或有效的上游报告成本,就可能产生费用。请以响应中的 usage.cost 或“活动”记录显示的最终扣款为准。

快速入门

三种接入方式

方式
适用场景
起点
直接调用 API任何语言、零依赖、完全掌控 request
OpenAI / Anthropic SDK已用官方 SDK — 只换 base URL 与密钥
Agent 框架LangChain、Vercel AI SDK、CrewAI 等 agent 应用

五分钟内开始使用。BazaarLink 与 OpenAI SDK 完全相容 — 只需更改

基础 URL

https://bazaarlink.ai/api/v1

使用 OpenAI SDK

BazaarLink 与 OpenAI SDK 完全相容。只需更改 base URL 和 API 密钥 — 所有其他程式码保持不变。

from openai import OpenAI

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_API_KEY",
)

completion = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[
        {"role": "user", "content": "What is the meaning of life?"}
    ],
)

print(completion.choices[0].message.content)
需要 API 密钥?
API 密钥页面取得您的密钥。所有密钥都以 sk-bl-.
Model ID 格式 — 建议用 provider/model 完整格式
建议一律使用 provider/model 完整格式(例如 openai/gpt-4.1)。常见家族(gpt-*、claude-*)在所有端点都会自动补上前缀,chat/completions 另外会把无歧义的裸模型名从目录解析成完整 ID — 但无法解析的名称会返回 400,完整格式才是唯一保证可用的写法。
✓ openai/gpt-4o   anthropic/claude-sonnet-4.6   google/gemini-2.5-flash
✗ gpt-4.1   claude-sonnet-4.6   gemini-2.5-flash

自带上游密钥(BYOK)

将你自己的上游供应商 API 密钥(OpenAI 或 Anthropic 兼容接口)绑定到个人账户或组织,符合条件的请求会改用你的密钥直连上游,并可选择无缝回退(seamless)或严格(strict)两种模式。个人在密钥页的 BYOK 分页设置,组织则在组织设置中集中管理。 前往 BYOK 设置 →

内容过滤

为你的 API 流量启用双向内容防护:检测到提示注入的请求会被拦截(400),请求与响应中的敏感数据(API 密钥、信用卡号、身份证号等)会被自动遮蔽。规则与豁免清单可自定义,并提供使用统计。 前往内容过滤设置 →

从 OpenRouter 迁移

BazaarLink 的 API 与 OpenRouter 兼容 — 大多数集成只需改两个值即可切换:base URL 换成 https://bazaarlink.ai/api/v1、API 密钥换成 sk-bl- 开头的 BazaarLink 密钥。

  1. base URL:https://openrouter.ai/api/v1 → https://bazaarlink.ai/api/v1
  2. API 密钥:sk-or-... → sk-bl-...(在 /keys 创建)
  3. 模型 ID:同样使用 provider/model 格式(例如 anthropic/claude-sonnet-4.6);完整列表见 GET /api/v1/models
  4. models 数组故障转移、provider 路由偏好、流式输出、工具调用、结构化输出的 request 形状相同
  from openai import OpenAI

  client = OpenAI(
-     base_url="https://openrouter.ai/api/v1",
-     api_key="sk-or-...",
+     base_url="https://bazaarlink.ai/api/v1",
+     api_key="sk-bl-...",
  )
Note
账单以美元计费、可开立台湾电子统一发票。OpenRouter 专属的功能(如 :nitro 供应商排序)的对应行为请见 API 参考页的「模型变体」与「供应商选择」章节。

身份验证

所有 API 请求都需要在 Authorization 标头中提供您的 API 密钥。

Authorization: Bearer sk-bl-YOUR_API_KEY

仪表板取得您的 API 密钥。请妥善保管密钥 — 请勿在用户端程式码中暴露它。

安全提示
请勿在用户端 JavaScript 中暴露 API 密钥。务必透过后端伺服器代理请求。

选填标头

HTTP-Referer
string
您的网站 URL,用于用量追踪和分析(选填)
X-Title
string
您的应用程式名称,显示在仪表板中(选填)

设计原则

BazaarLink 围绕三个核心原则设计:

1. 统一介面

一个 API、一个 SDK、数百个模型。只需更改模型 ID,无需修改程式码,即可在 OpenAI、Anthropic、Google Gemini、Meta Llama 等之间切换。

2. 价格优化

BazaarLink 自动路由到您所选模型最具成本效益的供应商。您只需为实际使用量付费,以美元计费并提供完整发票支援。

3. 高可用性

自动故障转移意味著若供应商服务中断,您的请求会无缝重新路由。无需修改程式码,无需停机。

多模态

BazaarLink 支援多模态输入 — 将图片、音讯和档案与文字一起传送至支援的模型。内容会直接传送至上游供应商。

支援的模态

输入
说明
范例模型
文字标准文字讯息所有模型
图片URL 或 base64 资料 URI — PNG、JPEG、WebP、GIFopenai/gpt-5.2-codexanthropic/claude-sonnet-4google/gemini-embedding-2-preview另有 145 个
档案 / PDFbase64 资料 URI(`data:application/pdf;base64,...`)openai/gpt-5.4-nanoanthropic/claude-sonnet-4google/gemini-embedding-2-preview另有 73 个
音讯纯 base64 — 不支援 URL,需提供 `format` 栏位google/gemini-embedding-2-previewxiaomi/mimo-v2.5google/gemini-3.1-pro-preview另有 14 个
影片URL(CDN)或 base64 资料 URIgoogle/gemini-embedding-2-previewqwen/qwen3.6-35b-a3bbytedance-seed/seed-2.0-mini另有 37 个

示例:

# Image — URL or base64 data URI
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"What is in this?"},
        {"type":"image_url","image_url":{"url":"https://example.com/photo.jpg"}}
      ]}]}'

# File / PDF — base64 data URI only, no URL
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":[
        {"type":"file","file":{"filename":"doc.pdf","file_data":"data:application/pdf;base64,JVBER..."}},
        {"type":"text","text":"Summarize this."}
      ]}]}'

# Audio — raw base64, no URL. "format" is required
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"Transcribe this."},
        {"type":"input_audio","input_audio":{"data":"UklGRi...","format":"wav"}}
      ]}]}'

# Video — URL (CDN) or base64 data URI
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"Describe this video."},
        {"type":"video_url","video_url":{"url":"https://example.com/clip.mp4"}}
      ]}]}'

传送图片

使用 content 阵列格式搭配 image_url 部分。支援格式:PNG、JPEG、WebP 及 GIF(包含动态 GIF)。单一讯息可包含多张图片,每张为独立的 image_url 部分:

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer sk-bl-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role":"user","content":[
      {"type":"text","text":"What is in this image?"},
      {"type":"image_url","image_url":{"url":"https://example.com/photo.jpg","detail":"auto"}}
    ]}]
  }'
传送图片
建议在讯息中一律包含文字部分,并将文字放在图片前面,以确保与所有供应商的最佳相容性。
传送图片
请查看模型页面,了解每个模型支援的输入模态。模态栏位显示每个模型接受的输入类型。

限制

BazaarLink 有两种独立限制:按请求频率计算的速率限制,以及按账户花费计算的点数限制。超过速率限制会收到 HTTP 429;点数用尽则会收到 HTTP 402。

速率限制

速率限制以使用者为单位(非密钥),以每分钟请求数(RPM)计算。无每日上限。等级由帐户点数余额自动决定。

等级
RPM
每日用量
备注
免费(点数 < $5)20 RPM无限制开发与测试
付费(点数 ≥ $5)200 RPM无限制生产环境

超过速率限制时,您会收到附有 Retry-After 标头的 429 回应。重试时请使用指数退避策略。

响应标头

每个成功的响应都包含速率限制标头,便于客户端追踪:

X-RateLimit-Limit: 200        # Max requests per minute for your tier
X-RateLimit-Remaining: 198    # Remaining requests in current window
X-RateLimit-Reset: 1740000060 # Unix timestamp when the window resets
X-Request-Id: chatcmpl-abc123 # Unique request ID for debugging

点数限制

收到 402 代表账户余额或密钥花费上限已归零,而非请求过于频繁。此类响应不会带速率限制标头;若在流式传输过程中触发,会以 SSE 错误事件回传,而非直接改变 HTTP 状态码。

402 余额不足
当余额降至 $0 时,API 会回传 HTTP 402,讯息为 "Insufficient credits. Please top up to continue." — 请监控响应中的 usage.cost 以即时掌握花费。

个人紧急熔断

针对您所有 API 密钥的固定 1 分钟 / 1 小时 USD 支出上限。当时间窗口阈值触发后,新请求将收到 HTTP 429;窗口于整点边界自动重置。

cbEnabled
boolean
启用
cbMinuteUsd
number | null
每分钟 USD 上限 · 使用默认值
cbHourlyUsd
number | null
每小时 USD 上限 · 使用默认值
(继承默认值)
数值至少为 0.01(或留空使用默认值)
个人紧急熔断 · 调整

图片生成

透过 /v1/chat/completions 带 modalities:["image"],或 OpenAI DALL·E 相容的 /v1/images/generations 生成图片。

curl -N https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-5.4-image-2","messages":[{"role":"user","content":"a red cat on a sofa"}],"modalities":["image","text"],"stream":true}'

完整流程(流式、图片编辑、SSE 协议、模型清单)请见 API 参考 →

视频生成

非同步三步骤流程(submit → poll → content)。视频生成需要 30 秒到 5 分钟。

curl https://bazaarlink.ai/api/v1/videos \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"alibaba/wan2.7-t2v","prompt":"a bird flying over mountains","duration":3}'
# → 202 { "id": "vjob_xxx", "status": "pending" }

完整流程(轮询、下载、任务类型、注意事项)请见 API 参考 →

PDF 输入

直接在讯息中传送 PDF 文件,给原生支援 PDF 输入的模型(例如 Claude、Gemini)分析、摘要或回答问题。BazaarLink 会把档案直接转送给模型 — 算一般 input tokens,不额外收费、不额外处理。

支援的格式

  • PDF 文件(含文字、图片、表格、扫描件)
  • Base64 资料 URL(`data:application/pdf;base64,...`)
  • 多页文件
  • 仅限无密码保护的 PDF
import base64

with open("document.pdf", "rb") as f:
    pdf_data = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "file",
                "file": {
                    "filename": "document.pdf",
                    "file_data": f"data:application/pdf;base64,{pdf_data}",
                },
            },
            {"type": "text", "text": "Summarize this document."},
        ],
    }],
)

影片输入

传送视频档案给支援视频输入的模型,用来分析内容、生成说明或回答场景与事件相关问题。可用直接 URL 或 base64 数据 URI — URL 适合公开可存取的视频;base64 用于本机档案或私有视频。

支援的格式

MP4(H.264)MPEGMOVWebM
response = client.chat.completions.create(
    model="google/gemini-2.5-flash",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "video_url",
                "video_url": {"url": "https://example.com/video.mp4"},
            },
            {"type": "text", "text": "What is happening in this video?"},
        ],
    }],
)

完整 API 参考 →

管理 API 密钥

管理密钥(Management Key)专用于程式化管理 API 密钥:可建立、列出、更新、停用与删除标准密钥,但无法呼叫 AI 模型。

注意
管理密钥无法进行模型呼叫(chat、completions、messages、embeddings)。如需呼叫模型,请使用标准 API 密钥。

建立管理密钥

前往「Management API Keys」页面,点击「Create」即可 — 这是独立页面,不是在普通 API 密钥页面里选类型。

列出密钥

GET https://bazaarlink.ai/api/v1/keys
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Response
{
  "keys": [
    {
      "id": "clxyz123...",
      "name": "Production Key",
      "keyType": "standard",
      "keyPrefix": "sk-bl-abc1",
      "keySuffix": "XyZ9",
      "enabled": true,
      "spendLimitUsd": 10.00,
      "spendLimitPeriod": "month",
      "expiresAt": null,
      "createdAt": "2026-01-01T00:00:00.000Z",
      "lastUsed": "2026-03-01T12:34:56.000Z",
      "requestCount": 1234,
      "totalTokens": 5678901
    }
  ]
}

建立子密钥

POST https://bazaarlink.ai/api/v1/keys
Authorization: Bearer sk-bl-YOUR_MGMT_KEY
Content-Type: application/json

{
  "name": "Agent Key",
  "limit": 10.00,
  "limit_reset": "monthly",
  "expires_at": "2026-12-31T23:59:59Z"
}

# limit_reset: daily | weekly | monthly
# expires_at:  ISO 8601 datetime (optional)

# Response — save the key value, it won't be shown again
{
  "id": "clxyz789...",
  "name": "Agent Key",
  "key": "sk-bl-xyz789abcdef...",
  "keyType": "standard",
  "spendLimitUsd": 10.00,
  "spendLimitPeriod": "month",
  "expiresAt": "2026-12-31T23:59:59.000Z",
  "enabled": true,
  "createdAt": "2026-03-01T00:00:00.000Z"
}

更新密钥

PATCH https://bazaarlink.ai/api/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY
Content-Type: application/json

{"enabled": false}              # disable key
{"spendLimitUsd": 5, "spendLimitPeriod": "week"}  # set spend limit
{"spendLimitUsd": null}         # remove spend limit
# Response: {"updated": true}

撤销密钥

DELETE https://bazaarlink.ai/api/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Returns 204 No Content on success

查询余额

GET https://bazaarlink.ai/api/v1/credits
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Response
{
  "data": {
    "total_credits": 12.345,
    "total_usage": 3.210
  }
}

查询用量

GET https://bazaarlink.ai/api/v1/usage?period=month
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# period: day | week | month | year

应用程式识别

透过请求标头识别您的应用程式,让系统追踪使用量、显示在仪表板上,并在未来提供更细致的分析。

注意
这些标头完全选填,不影响 API 功能。但建议设定,有助于除错和使用量归因。

可用标头

HeaderDescription
HTTP-Referer您的网站 URL,用于用量追踪和分析(选填)
X-Title您的应用程式名称,显示在仪表板中(选填)
from openai import OpenAI

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_KEY",
    default_headers={
        "HTTP-Referer": "https://yourapp.com",  # Optional: your site URL
        "X-Title": "My Application",             # Optional: your app name
    },
)

response = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)

错误代码

错误回应格式

模型推理端点会返回 OpenAI 兼容的错误 envelope。部分特殊端点可能省略 type,或依错误路径使用不同值;程序判断请使用 HTTP 状态与 error.code,不要解析 message 文本。

{
  "error": {
    "message": "Insufficient credits. Please top up to continue.",
    "type": "invalid_request_error",
    "code": "insufficient_credits"
  }
}

HTTP 状态与 error.code

串流开始前,HTTP 状态代表错误大类;error.code 可能是相同的数字,也可能是代表特定处理方式的稳定字符串。若有字符串代码应优先判断,否则使用 HTTP 状态;error.message 仅供人阅读。

代码
名称
说明
400请求无效请求格式错误、messages 阵列为空,或缺少必填栏位
401未授权API 密钥遗失、无效或已停用
402需要付款帐户点数不足、单一密钥花费上限已达,或每周 / 每月预算上限已达
403禁止存取帐户已停用或没有此操作的权限
404找不到资源指定的模型、生成任务、密钥或其他资源不存在
409状态冲突资源尚未进入必要状态,例如视频任务尚未完成
410资源已移除指定模型已退役,必须改用其他模型
413请求体过大请求 body 超过 10 MB;请缩小内容或分拆请求
416范围无法满足生成视频内容所要求的 byte range 无效
429请求过多已超过速率限制;请查看 Retry-After 标头后再重试
500伺服器错误BazaarLink 内部错误
502闸道错误所有上游提供者均失败;已尝试故障转移
503服务不可用此模型没有设定上游提供者;请联络管理员
504闸道超时上游连接或串流停滞并超过等待时间

机器可读的账务代码

同样是 402,也可能代表不同的账务控制。请依下列稳定代码显示正确的处理方式。

代码
说明
budget_cap_reached已达到每周或每月的提醒型预算上限;提高或重设预算上限。
credit_limit_exceeded月结组织已用尽硬性信用额度;请联系账务人员。
insufficient_credits预付用户或组织无法保留足够余额;请先充值。
spend_limit_exceededAPI 密钥已达到每日、每周或每月花费上限。

详细错误代码

API 请求失败时,error.code 会告诉你更具体的原因。即使两个错误都是 HTTP 400,处理方式也可能不同:例如 unknown_model 表示模型名称有误,image_too_large 则表示图片太大。请根据下表查找原因和对应的处理方向。

模型与端点
模型查找、生命周期、定价、模态和端点兼容性错误。
代码
HTTP 状态
unknown_model400
invalid_model_id400
model_not_found404
model_retired410
model_endpoint_mismatch400
embedding_on_chat_endpoint400
model_not_priced400
invalid_modality_for_model400
请求与安全
参数、上下文、工具、结构定义和内容安全拒绝。
代码
HTTP 状态
missing_required_field400
unsupported_param400
max_tokens_invalid400
context_too_long400
tool_use_unsupported400
malformed_tool_messages400
invalid_response_format_schema400
invalid_tools_definition400
content_moderation403
content_filter403
unknown_4xx400
图片生成与编辑
图片输入、multipart 编辑、输出和图片管线错误。
代码
HTTP 状态
invalid_image_url400
input_images_not_supported400
invalid_content_type400
mask_not_supported400
unsupported_response_format400
missing_prompt400
missing_image400
too_many_images400
invalid_image_type400
image_too_large400
invalid_n400
pipeline_error502
no_images502
上游路由
安全处理后的供应商连接、认证、限流和可用性错误。
代码
HTTP 状态
upstream_unreachable502
upstream_auth_failed502
upstream_rate_limited429
upstream_unavailable502/503

速率限制、预算与紧急刹车

这些控制可能拒绝原本有效的请求。它们与供应商故障不同,需要不同的恢复操作。

控制机制
HTTP 状态
识别方式
请求速率限制429数字 code 429;遵循 Retry-After 和 X-RateLimit-* 标头。
限流惩罚封锁429数字 code 429、临时限制消息和 Retry-After。
全局支出紧急刹车503数字 code 503、全局支出上限消息,以及 30 或 300 秒的 Retry-After。
组织/团队/成员/用户支出刹车429数字 code 429,消息会指出 spend circuit breaker 和受影响范围。
计费与预算控制402使用上方列出的稳定计费字符串代码。

兼容性提醒:速率限制与紧急刹车目前返回数字型 error.code。请勿假设尚未实现的字符串代码;请依据 HTTP 状态、Retry-After 和文档所述消息判断。

视频与媒体资源状态

视频验证通常返回数字 code 400;任务不存在为 404、模型退役为 410、视频内容尚未完成为 409、视频 byte range 无效为 416。重试前请先轮询至完成或修正 Range 标头。

重试策略

只有在不修改请求也可能恢复的错误才应重试。若有 Retry-After,请依指定秒数等待;否则使用带 jitter 的指数退避。限制重试次数,也不要同时叠加 SDK 自动重试与手动重试。

可退避重试
429、502、503、504。有 Retry-After 时必须优先遵守。生成类请求若遇到结果不明的网络中断,应先查询原任务,避免建立第二个任务。
修正后再重试
400、401、402、403、404、409、410、413、416。请先修正请求、凭证、余额、权限、资源状态或 Range 标头。

错误处理

import random
import time
from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://bazaarlink.ai/api/v1",
    api_key="sk-bl-YOUR_API_KEY",
    max_retries=0,  # Avoid double retries; this example handles them.
)

RETRYABLE = {429, 502, 503, 504}

for attempt in range(5):
    try:
        response = client.chat.completions.create(
            model="openai/gpt-4.1",
            messages=[{"role": "user", "content": "Hello!"}],
        )
        break
    except APIStatusError as error:
        if error.status_code not in RETRYABLE or attempt == 4:
            raise
        retry_after = error.response.headers.get("Retry-After")
        delay = (
            float(retry_after)
            if retry_after
            else min(8, 0.5 * (2 ** attempt)) + random.uniform(0, 0.25)
        )
        time.sleep(delay)

串流错误格式

在任何 token 串流之前发生的错误,会以标准 HTTP 错误回应(JSON body)回传。

串流一旦开始,HTTP 回应已经是 200。客户端必须解析每个 SSE data frame;只要出现顶层 error,或 choices[0].finish_reason === "error",就应视为失败且回应不完整。

串流中途失败时,BazaarLink 会发送最后一个 SSE 事件,内容为顶层 error 对象,接着是 data: [DONE]。部分上游原样转发的 chunk 则可能把错误放在 choice 上(choices[0].finish_reason === "error")— 两种都要处理。

// If the stream fails mid-flight, BazaarLink emits a final SSE event
// with a top-level "error" object, followed by data: [DONE]
data: {"error":{"message":"Upstream stream interrupted. The response is incomplete.","type":"upstream_error","code":502}}

data: [DONE]

// Chunks relayed verbatim from some upstreams may instead carry the error
// inline on the choice: choices[0].finish_reason === "error" with an
// "error" object ({ code, message }) on the choice — handle both shapes.
// Branch on error.code; error.type can vary by failure path.

工具呼叫

工具呼叫(也称为函式呼叫)让模型可以呼叫您定义的外部函式。模型会决定何时呼叫工具并产生结构化参数 — 您的程式码负责执行函式并将结果回传以继续对话。

支援的模型

大多数前沿模型都支援工具呼叫。以下是一些热门选择:

定义工具

每个工具是一个描述模型可呼叫函式的 JSON 物件。parameters 栏位使用 JSON Schema。

name必填
string
函式名称(a-z、A-Z、0-9、底线、连字号)
description必填
string
清楚描述函式应在何时及如何被使用
parameters必填
object
定义函式参数的 JSON Schema 物件

tool_choice 选项

行为
"auto"模型自行决定是否呼叫工具(预设)
"none"模型不会呼叫任何工具
"required"模型必须呼叫至少一个工具
{"type": "function", "function": {"name": "get_weather"}}模型必须呼叫指定的函式

完整流程

工具呼叫是一个多轮流程:(1) 带工具发送请求 → (2) 模型回传 tool_calls → (3) 执行函式 → (4) 回传结果 → (5) 模型生成最终回应。

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1",
    "messages": [{"role":"user","content":"What is the weather in Taipei?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string", "description": "City name"},
            "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
          },
          "required": ["city"]
        }
      }
    }],
    "tool_choice": "auto"
  }'
# Response carries tool_calls — run get_weather() yourself, then send the
# result back with role:"tool" (same shape as the Python/TS steps 3-5) to
# get the model's final answer.

平行工具呼叫

某些模型可以在单一回应中呼叫多个工具。处理每个工具呼叫并回传所有结果:

# Model may return multiple tool_calls
if message.tool_calls:
    messages = [
        {"role": "user", "content": "Weather and time in Tokyo?"},
        message,
    ]

    for tool_call in message.tool_calls:
        # Execute each function
        if tool_call.function.name == "get_weather":
            result = {"temperature": 22, "condition": "Clear"}
        elif tool_call.function.name == "get_time":
            result = {"time": "2026-02-23T15:30:00+09:00"}

        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result),
        })

    # Send all results back at once
    final = client.chat.completions.create(
        model="openai/gpt-4.1",
        messages=messages,
        tools=tools,
    )
    print(final.choices[0].message.content)

流式传输中的工具呼叫

流式传输时,工具呼叫会拆成多个 delta 依序送出——用每个片段的 index 把参数字符串组合起来,等 finish_reason 变成 "tool_calls" 才代表这次工具呼叫已经收完整。

# Streaming: tool_calls arrive as partial deltas indexed by position —
# accumulate function.arguments per index until finish_reason == "tool_calls".
stream = client.chat.completions.create(
    model="openai/gpt-4.1",
    messages=[{"role": "user", "content": "What's the weather in Taipei?"}],
    tools=tools,
    tool_choice="auto",
    stream=True,
)

tool_calls = {}
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.tool_calls:
        for tc in delta.tool_calls:
            entry = tool_calls.setdefault(tc.index, {"id": "", "name": "", "arguments": ""})
            if tc.id:
                entry["id"] = tc.id
            if tc.function.name:
                entry["name"] = tc.function.name
            if tc.function.arguments:
                entry["arguments"] += tc.function.arguments
    if chunk.choices[0].finish_reason == "tool_calls":
        for call in tool_calls.values():
            print(call["name"], json.loads(call["arguments"]))

简易 Agent 循环

只要模型还在要求工具就持续呼叫,直到它回传最终答案为止的通用模式——用 max_iterations 避免无限循环。

# Generic loop: keep calling the model while it keeps requesting tools,
# stop once it returns a plain answer. max_iterations guards against loops.
messages = [{"role": "user", "content": "What's the weather in Taipei, and what time is it there?"}]
max_iterations = 10

for _ in range(max_iterations):
    response = client.chat.completions.create(
        model="openai/gpt-4.1",
        messages=messages,
        tools=tools,
    )
    message = response.choices[0].message
    messages.append(message)

    if not message.tool_calls:
        break  # model gave a final answer

    for tool_call in message.tool_calls:
        args = json.loads(tool_call.function.arguments)
        result = TOOL_MAPPING[tool_call.function.name](**args)
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result),
        })
else:
    print("Warning: max_iterations reached without a final answer")

print(messages[-1].content)

函数定义最佳实践

  • 函数命名要具体:用 get_weather_forecast,不要只写 weather。
  • description 要写清楚函数的用途与适用时机——模型只靠这段文字判断该不该呼叫。
  • 参数尽量用 enum 限制可能值,并在 description 附上示例,降低模型生成错误参数的概率。
  • 只把真正必要的字段标记为 required,选填字段应该真的可以省略。

结构化输出

强制模型返回符合 Schema 的有效 JSON。这对于建立需要程式化解析模型输出的可靠应用程式至关重要。

方法 1:response_format(JSON Schema)

以强制严格的 JSON Schema 合规性:

type必填
string
必须为 "json_schema"
json_schema.name必填
string
Schema 的名称(用于快取)
json_schema.strict
boolean
设为 true 时,保证完全符合 Schema
json_schema.schema必填
object
JSON Schema 定义
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1",
    "messages": [{"role":"user","content":"Review the movie Inception"}],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "movie_review",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "title": {"type": "string"},
            "rating": {"type": "integer", "description": "Rating 1-10"},
            "summary": {"type": "string"},
            "pros": {"type": "array", "items": {"type": "string"}},
            "cons": {"type": "array", "items": {"type": "string"}}
          },
          "required": ["title", "rating", "summary", "pros", "cons"],
          "additionalProperties": false
        }
      }
    }
  }'

提示

  • 使用清晰、描述性的属性名称 — 模型会将其作为上下文。
  • 为 Schema 属性添加描述来引导模型。
  • 设定 strict: true 以保证 Schema 合规(可能略微增加延迟)。
  • 保持 Schema 简单 — 深度巢状的 Schema 可能降低输出品质。
  • 使用不同模型测试 — 某些模型处理复杂 Schema 的能力更强。

助手预填

在消息数组最后加入一条未完成的 assistant 消息,向兼容的模型路由请求接续生成。

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-4.6",
    "messages": [
      {"role":"user","content":"What is the capital of France?"},
      {"role":"assistant","content":"The capital of France is"}
    ]
  }'
# Model continues: " Paris, known for the Eiffel Tower..."
运作方式
BazaarLink 会保留并转发最后一条 assistant 消息。接续行为由所选的上游模型与供应商实现,因此并非每条路由都保证支持。

讯息转换

自动转换讯息以符合模型上下文限制。当您的讯息超过模型的上下文窗口时,转换会从对话中间移除讯息,以智慧地压缩对话。

Auto
上下文窗口 ≤ 8,192 tokens 的模型预设自动套用 middle-out。若要停用,请传入 `transforms: []`;若要对任何模型启用,请传入 `transforms: ["middle-out"]`。

用法

// Enable middle-out on any model
{
  "model": "openai/gpt-4.1",
  "transforms": ["middle-out"],
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    ... // long conversation — middle will be trimmed to fit context
  ]
}

// Disable auto-trimming for small-context models
{ "transforms": [] }

转换类型

转换
说明
middle-out先移除中间的讯息,保留开头(系统提示词、上下文)和结尾(最近的讯息)

预设行为

上下文 ≤ 8k 的模型预设启用 middle-out。较大上下文的模型需明确传入 `transforms: ["middle-out"]` 才会启用。Anthropic Claude 模型无论 transforms 设定为何,均自动强制执行 1,000 则讯息上限。

零资料保留

BazaarLink 预设不储存您的讯息内容。本页说明您的资料处理方式,适用于处理敏感资料的应用程式。

目前的资料处理方式

  • 讯息内容:预设不储存,在记忆体中处理后立即丢弃
  • 计费元资料:token 数量、时间戳记、模型 ID
  • 使用日志:请求统计,不含讯息内容
  • 上游转发:讯息转发至上游供应商,受其隐私政策约束

提示快取

提示快取可以重用之前计算过的 prompt tokens,显著降低成本并减少延迟,特别适合有大量重复系统提示的应用程式。

Note
BazaarLink 会自动追踪快取节省并反映在帐单中。回应中的 `cached_tokens` 栏位显示实际快取命中数量,`cacheDiscount` 栏位显示本次节省金额。

运作方式

是否需要额外设定取决于供应商。OpenAI 系列模型的长重复前缀会自动快取,不需要改请求内容。Claude(Anthropic)模型只有在请求里带明确的 cache_control 标记时才会快取——BazaarLink 不会替你加这个标记,没带就永远不会被快取。BazaarLink 会原封不动转发你送出的快取标记,并在使用量回应中回报实际的快取读写 token 数。

# OpenAI-family models: nothing to add, long repeated prefixes cache automatically.
response = client.chat.completions.create(
    model="openai/gpt-4.1",
    messages=[
        {"role": "system", "content": "You are an expert..."},  # cached automatically if long/repeated
        {"role": "user", "content": "Question here"},
    ],
)

# Check cache savings in the response usage
usage = response.usage
print(f"Prompt tokens: {usage.prompt_tokens}")
print(f"Cached tokens: {usage.prompt_tokens_details.cached_tokens}")
print(f"Cache savings: {usage.prompt_tokens_details.cached_tokens / usage.prompt_tokens * 100:.1f}%")
Claude 需要明确加上 cache_control 标记
在要快取的内容区块加上 cache_control: {"type": "ephemeral"},如下方范例。Anthropic 自己也有一个最短 prompt 长度限制,低于这个长度即使加了标记也不会快取,且不会报错。可以检查回应中的 cached_tokens(OpenAI 格式)或 cache_read_input_tokens / cache_creation_input_tokens(Anthropic 格式)来确认是否真的命中。
# Claude models: you must mark the block to cache yourself.
response = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[
        {
            "role": "system",
            "content": [
                {"type": "text", "text": "You are an expert...", "cache_control": {"type": "ephemeral"}}
            ],
        },  # BazaarLink does not add cache_control on your behalf
        {"role": "user", "content": "Question here"},
    ],
)

usage = response.usage
print(f"Cache read tokens: {getattr(usage, 'cache_read_input_tokens', 0)}")
print(f"Cache write tokens: {getattr(usage, 'cache_creation_input_tokens', 0)}")

推理 Tokens

推理模型(如 DeepSeek R1、o1 系列)在生成最终答案之前,会先在内部进行思考。这些思考过程消耗的 tokens 称为推理 tokens,会分开计费。

Note
BazaarLink 在回应的 `usage.completion_tokens_details.reasoning_tokens` 栏位回报推理 tokens,并在计费中分开显示。

在回应中读取推理 Tokens

response = client.chat.completions.create(
    model="deepseek/deepseek-r1",
    messages=[{"role": "user", "content": "Solve: if f(x) = x^2 + 3x, what is f(5)?"}],
)

# Read reasoning tokens from usage
usage = response.usage
print(f"Completion tokens: {usage.completion_tokens}")
if hasattr(usage, "completion_tokens_details"):
    details = usage.completion_tokens_details
    print(f"Reasoning tokens: {details.reasoning_tokens}")
    print(f"Output tokens: {details.accepted_prediction_tokens}")
const response = await client.chat.completions.create({
  model: "openai/o3-mini",
  messages: [{ role: "user", content: "Prove that sqrt(2) is irrational." }],
  // @ts-ignore - BazaarLink extension
  reasoning_effort: "high",  // low | medium | high
});

const usage = response.usage;
console.log("Reasoning tokens:", usage?.completion_tokens_details?.reasoning_tokens);

思考模式控制

部分模型支援切换「思考」模式。思考模式在输出最终答案前产生内部推理 token,以更多 token 为代价提升输出品质。

模型系列参数预设值
qwen3-*enable_thinking: booleanfalse(平台预设值)
openai/o1, o3, o4-minireasoning_effort: "low" | "medium" | "high"medium
deepseek/deepseek-r1永远启用(无法关闭)
# Qwen3: explicitly enable thinking mode
response = client.chat.completions.create(
    model="qwen/qwen3-32b",
    messages=[{"role": "user", "content": "Prove the Pythagorean theorem"}],
    extra_body={"enable_thinking": True},  # opt-in to thinking
)

# usage.completion_tokens_details.reasoning_tokens shows thinking token count

统一 reasoning 物件(新格式)

BazaarLink 也支援统一的 reasoning 物件,以单一一致的 API 适用所有模型系列:

栏位数值适用模型
reasoning.effort"xhigh" | "high" | "medium" | "low" | "none"OpenAI o-series, Grok
reasoning.max_tokensintegerAnthropic Claude, Gemini
reasoning.excludeboolean从回应中隐藏思考内容(模型仍会推理)
// Claude extended thinking — specify thinking budget in tokens
const response = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4.5",
  messages: [{ role: "user", content: "Prove the Pythagorean theorem" }],
  // @ts-ignore - BazaarLink extension
  reasoning: { max_tokens: 5000 },
});

// OpenAI o3 — specify effort level
const response2 = await client.chat.completions.create({
  model: "openai/o3",
  messages: [{ role: "user", content: "Solve this math problem..." }],
  // @ts-ignore - BazaarLink extension
  reasoning: { effort: "high" },
});

// Hide thinking content from response (model still thinks)
const response3 = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4.5",
  messages: [{ role: "user", content: "What is 2+2?" }],
  // @ts-ignore - BazaarLink extension
  reasoning: { max_tokens: 2000, exclude: true },
});
计费说明
思考 token 以 completion token 计费。部分供应商在思考模式启用时收取较高费率 — Qwen3 开启思考时费率为标准的 2 倍。BazaarLink 预设 Qwen3 的 enable_thinking=false 以避免意外费用。

延迟与效能

优化 AI API 的回应延迟对用户体验至关重要。以下是 BazaarLink 架构中影响延迟的关键因素及最佳化建议。

Note
BazaarLink 记录每次请求的 `duration_ms`(端对端延迟)和 `throughput`(tokens/秒),可透过 GET /api/v1/generation?id=... 查询,或在「使用记录」的 Export CSV 里看到。

影响延迟的因素

  • 模型大小:较大的模型(70B+)通常生成速度较慢
  • 提供商负载:不同时段不同供应商的负载有所差异
  • Token 数量:max_tokens 越大,完成时间越长
  • 串流 vs 非串流:串流(stream: true)可更快取得第一个 token
  • 上下文长度:超长 context 会增加前置处理时间

最佳化建议

  • 优先使用串流(stream: true)以改善感知延迟
  • 使用 :nitro 变体选择高吞吐量供应商
  • 对延迟敏感的场景选择较小的模型(flash/mini/haiku)
  • 使用 provider.sort: "latency" 自动选择最低延迟供应商
  • 启用提示快取以降低重复请求的延迟
import time

# Measure time to first token with streaming
start = time.time()
first_token_time = None

stream = client.chat.completions.create(
    model="google/gemini-2.5-flash",  # Fast model
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content and not first_token_time:
        first_token_time = time.time() - start

print(f"Time to first token: {first_token_time:.3f}s")
# Look up per-request latency and throughput after the fact, using the
# generation ID from the response (or the final streamed chunk).
curl "https://bazaarlink.ai/api/v1/generation?id=chatcmpl-abc123" \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

# Response
{
  "data": {
    "id": "chatcmpl-abc123",
    "model": "google/gemini-2.5-flash",
    "duration_ms": 842,
    "throughput": 61.2,
    "usage": { "prompt_tokens": 12, "completion_tokens": 48, "total_tokens": 60 }
  }
}
# Use provider.sort for automatic latency optimization
response = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    extra_body={
        "provider": {
            "sort": "latency",  # Always pick lowest-latency provider
        }
    },
)

可用性优化

BazaarLink 透过多层机制最大化 API 可用性,包括自动故障转移、熔断器和供应商健康监控。

Note
BazaarLink 追踪所有上游供应商的可用性状态。当供应商错误率超过阈值时,熔断器会自动触发,将请求路由至下一个可用供应商。

可用性机制

  • 熔断器:自动侦测并隔离故障供应商
  • 自动故障转移:无缝切换至备用供应商,无需修改程式码
  • 供应商健康监控:持续追踪各供应商的错误率和延迟
  • 重试逻辑:暂时性错误(5xx)自动重试

熔断器配置

# BazaarLink handles failover automatically — no code changes needed.
# Configure fallback models for maximum resilience:

response = client.chat.completions.create(
    model="openai/gpt-4o",       # Primary model
    messages=[{"role": "user", "content": "Hello!"}],
    extra_body={
        "models": [              # Fallback chain
            "openai/gpt-4o",
            "anthropic/claude-sonnet-4.6",
            "google/gemini-2.5-flash",
        ],
        "route": "fallback",     # Enable fallback routing
    },
)

# Check if failover was used (in usage logs)
# "is_failover": true indicates the primary provider was bypassed
供应商健康监控仅供内部运维查看
GET /api/admin/provider-health 是后台运维仪表板用的内部端点,需要管理员权限,回传完整的运维统计数据(各供应商请求量、错误率、延迟百分位、故障转移统计等),不是给普通客户查询用的公开 API,这里不重复列出实际字段。

安全护栏

为 API 请求加上内容安全机制,过滤有害内容、执行合规政策。BazaarLink 目前只在组织(Organization)层级提供可自定义的内容过滤防护;个人(非组织)API 密钥没有对应设定,内容安全完全依赖各上游模型供应商自己内建的安全系统。

目前范围
个人 API 密钥没有内建的自定义护栏——内容安全完全依赖上游供应商自己的安全系统。若需要可自定义的内容过滤规则(阻挡/遮蔽/记录、关键字与正则、PII 模板),请创建组织并使用组织 API 密钥,设置位置在「内容过滤防护」。

规划中功能(尚未提供,个人与组织密钥皆无)

护栏
说明
PII 侦测侦测并遮蔽个人识别信息
主题限制限制模型回应仅涵盖批准的主题
输出验证在返回前根据自定义规则验证模型输出

目前行为

个人 API 密钥:所有上游供应商都有自己的内容安全系统,触发内容过滤的模型回应会回传 finish_reason: "content_filter",BazaarLink 不做额外过滤。组织 API 密钥:org_admin 可以在「内容过滤防护」设置自定义规则(阻挡/遮蔽/记录),套用在文字送到模型之前。

Cursor IDE 集成

把 BazaarLink 设成 Cursor 的 OpenAI Override URL,立即在 Cursor 内调用所有模型。支持 Responses API 自动转换、工具格式规范化,并用 bz- 前缀规避 Cursor 对 Claude 模型的拦截。

快速设置

在 Cursor 打开 设置 → 模型,然后:

  1. 把 Override OpenAI Base URL 设为 https://bazaarlink.ai/v1
  2. 把 Override OpenAI API Key 设为你的 sk-bl-... BazaarLink 密钥
  3. 输入你想用的 model 名称 — Claude 模型请看下方 bz- 前缀规则。
向后兼容
旧网址 https://bazaarlink.ai/v1/cursor 仍可使用 — 现在它只是 /v1/chat/completions 的一行转发。新设置请直接用 /v1。

bz- 前缀(用于 Claude 模型)

Cursor 在 client side 看到 claude- 开头的模型名称会强制走它自己的 Anthropic 集成,完全略过你的 Override URL。要让 Cursor 把请求送到 BazaarLink,在模型名称前面加 bz-。我们的 server 会去掉前缀后再用 alias map 解析剩下的部分。

在 Cursor 输入解析为
bz-claude-sonnet-4.6anthropic/claude-sonnet-4.6
bz-claude-opus-4.7anthropic/claude-opus-4.7
gpt-4oopenai/gpt-4o
gemini-2.5-flashgoogle/gemini-2.5-flash

点号和连字号的版本都会被规范化:bz-claude-sonnet-4.6 和 bz-claude-sonnet-4-6 会解析到同一个模型。

CURSOR_MODEL_MAP 环境变量(运营者覆写)

如果你是自架 BazaarLink,设这个环境变量可以把任何 Cursor 端的模型名称重新映射到目录的 canonical id:

CURSOR_MODEL_MAP=gpt-claude-sonnet:anthropic/claude-sonnet-4.6,gpt-opus:anthropic/claude-opus-4.7

这样 Cursor 端输入的 gpt-claude-sonnet 会在 server 端被映射成 anthropic/claude-sonnet-4.6。当你想让 Cursor 以为某个模型是 GPT 家族(才会走 Override URL),实际上你想用 Claude 提供服务时很有用。

自动处理的事项

当请求送到 /api/v1/chat/completions 时,BazaarLink 会自动套用以下兼容性转换 — 你的 client 端不用做任何事:

  • 自动检测 Responses API body — 如果 body 有 input 而没有 messages,会自动转成 Chat Completions 格式(Cursor 对 GPT 家族模型会送 Responses API 格式)。
  • 包装扁平的 tool 定义 — Cursor Agent 送的是 { name, description, parameters } 没有 function 包装。我们会包好,避免 Anthropic 回 Tool '' not found in provided tools。
  • 矫正错误格式的 tool_choice — Cursor 送的是 { type: "auto" }(对象形式,没 function)。OpenAI 规范要求 auto/none/required 用字符串形式,所以我们强制转换。
  • 送到非 OpenAI 供应商时剥除 OpenAI 专用字段 — parallel_tool_calls、logprobs、top_logprobs、logit_bias、service_tier、user 在转发前会被移除(否则 Anthropic 会回 400)。
  • 把 max_output_tokens 对应成 max_tokens,同时移除 Responses-API 专用字段(previous_response_id、truncation、background、store)。reasoning 字段在原生 Chat Completions body 会保留。

Cursor Agent 模式

工具调用走的是标准 Chat Completions tool-call 流程。Cursor 送 tools(Shell、Read、Write、Grep 等)和 tool_choice: "auto";BazaarLink 转发给你选的供应商,由供应商决定要不要调用工具。工具调用以标准 OpenAI tool_calls deltas 形式回传;Cursor 在本地执行并继续对话。不管你选 gpt-4o(原生 OpenAI)还是 bz-claude-sonnet-4.6,运作方式都一样。

Debug 上游拒绝
如果你看到供应商回 4xx 错误,去 admin 的「供应商健康」面板看。每笔 4xx 响应都会把完整的上游错误 body 和我们转发的请求 body 摘要存起来 — 点任何 🔴 那一行就能展开看 JSON。

模型路由

BazaarLink 使用 provider/model-name 格式将请求路由到正确的上游供应商。这让您可以透过单一 API 端点存取主流模型。

模型 ID 格式

{provider}/{model-name}

# Examples
openai/gpt-5.4-mini
anthropic/claude-sonnet-4.6
google/gemini-3-flash-preview
deepseek/deepseek-v3.2

路由优先顺序

当您发送请求时,BazaarLink 依以下顺序解析上游供应商:

  1. 精确匹配 — 寻找与完整模型 ID 匹配的模型路由
  2. 供应商万用字元 — 回退至 provider/* 路由(例如 openai/*)
  3. 全域万用字元 — 回退至 * 万用字元路由
  4. 默认供应商密钥 — 仅限已收录模型,使用已启用且标记为默认的供应商密钥

模型页面浏览所有可用模型。

自动路由

Auto Router v3 会先把请求评分为 14 个任务层级之一,再使用该层级当前设置的主要模型与备用链。付费与免费路由表可在后台分别管理。

  • auto — 使用付费路由表;成功完成请求的实际模型按公开价格计费。
  • auto:free — 使用免费路由表;免费额度内扣款为 0。额度用完后,有余额的账户可能转为付费 auto,除非关闭付费 fallback。

如何使用

将 model 设为 "auto"(付费)或 "auto:free"(免费)以启用自动路由:

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Review this TypeScript function"}]}'

v3 如何选择 tier

通用 tier 为 simple、standard、complex、reasoning;专用 tier 为 coding、vision、image、video、data、search、social、email、calendar、trading。若分数落在低置信度边界,系统会提升一级,避免低估任务难度。

  • 层级评分:根据 messages、tools、长度、关键字与结构特征,选出 14 个 tier 之一
  • 硬规则覆盖:图片输入、形式推理及特定专用任务可直接指定 tier
  • 查询路由:按模式读取该 tier 当前的 primary 与最多 5 个 fallback;停用的 tier 直接返回 503
  • 执行顺序:先尝试 primary,再按后台设置顺序尝试 fallback
  • 回应追踪:解析后的模型会在回应本体和 X-Auto-Resolved-Model 标头中回传

当前实际使用的模型表

下表直接读取推理服务与后台使用的同一份实时设置。管理员可随时调整每个 tier 的主要模型、备用顺序与启用状态,无需重新部署。

auto

Tier
Primary
Fallbacks
State
simpleopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-haiku-4.5
enabled
standardgoogle/gemini-3-flash-preview
openai/gpt-5.4-minianthropic/claude-haiku-4.5
enabled
complexgoogle/gemini-3.1-pro-preview
anthropic/claude-sonnet-4.6openai/gpt-5.4-pro
enabled
reasoninganthropic/claude-opus-4.7
openai/gpt-5.4-progoogle/gemini-3.1-pro-preview
enabled
codingopenai/gpt-5.3-codex
anthropic/claude-sonnet-4.6openai/gpt-5.4-pro
enabled
visionopenai/gpt-5.4-image-2
enabled
imageopenai/gpt-5.4-image-2
enabled
videobytedance/seedance-2.0-fast
bytedance/seedance-2.0anthropic/claude-sonnet-4.6
enabled
dataopenai/gpt-5.4-pro
anthropic/claude-sonnet-4.6google/gemini-3.1-pro-preview
enabled
searchperplexity/sonar-pro
perplexity/sonar-reasoning-proopenai/gpt-5.4-pro
enabled
socialopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-haiku-4.5
enabled
emailopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-sonnet-4.6
enabled
calendaropenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-preview
enabled
tradinganthropic/claude-opus-4.7
openai/gpt-5.4-progoogle/gemini-3.1-pro-preview
enabled

auto:free

Tier
Primary
Fallbacks
State
simpledeepseek/deepseek-v4-flash
enabled
standarddeepseek/deepseek-v4-flash
enabled
complexminimax/minimax-m2.5
enabled
reasoningminimax/minimax-m2.5
enabled
codingdeepseek/deepseek-v4-flash
enabled
visionopenai/gpt-5.4-image-2
disabled
imageopenai/gpt-5.4-image-2
disabled
videogoogle/gemini-2.5-flash-lite
disabled
datadeepseek/deepseek-v4-flash
enabled
searchminimax/minimax-m2.5
enabled
socialdeepseek/deepseek-v4-flash
enabled
emaildeepseek/deepseek-v4-flash
enabled
calendardeepseek/deepseek-v4-flash
enabled
tradingdeepseek/deepseek-v4-flash
enabled

部分模型提供受限速的免费额度。免费资格由平台按模型授予 — 直接用原本的模型 ID 调用即可;:free 后缀只是可选别名(对付费模型自行加上 :free 不会变免费)。

超出免费额度之后
额度用完后,只要账户有余额,请求会自动改以该模型的付费价格继续执行(不会中断服务),费用与一般付费调用相同。若你希望超额时直接失败而不是被计费,发送 X-Free-Fallback: false 头部,或在密钥设置中关闭自动转付费 — 这时会返回 429。账户没有余额时,超额请求一律返回 429。
X-Auto-Resolved-Model
实际选用的模型会同时出现在 X-Auto-Resolved-Model 响应标头与响应本体的 model 字段。

模型变体

在任何模型 ID 后加上后缀来改变路由行为。BazaarLink 支援 7 种变体类型。

变体类型
有两类变体:独立模型 ID(带后缀的模型是独立的端点)和路由捷径(后缀改变 BazaarLink 选择供应商的方式,但不改变模型本身)。

独立模型 ID

这些变体作为独立模型存在,各自拥有定价和功能。BazaarLink 优先尝试完整模型 ID(含后缀),若无匹配则回退至基础模型。

:free
:extended
:thinking
:exacto

路由捷径

这些后缀修改供应商选择方式,不改变模型身份。路由匹配前会先去除后缀。

:floor   # lowest listed input price first
:nitro   # throughput-oriented shortcut
:online  # enable web-search routing

多供应商行为

对于支援变体的上游供应商,后缀会原样传递。对于直连供应商(如直连 OpenAI、Fireworks),后缀会被去除,由 BazaarLink 在本地处理路由。

免费模型

部分模型提供受限速的免费额度。免费资格由平台按模型授予 — 直接用原本的模型 ID 调用即可;:free 后缀只是可选别名(对付费模型自行加上 :free 不会变免费)。

  • 直接调用原模型 ID(例如 deepseek/deepseek-v4-flash),免费额度内的请求自动免费。
  • 免费用量按用户限制每分钟请求数(RPM)与每日上限,额度随账户等级(未充值 / 已充值)调整。
  • 超过免费额度且账户有余额时,请求会自动以列出的付费价格继续。发送 X-Free-Fallback: false 可关闭自动转付费、改收 429。无余额时,超额请求返回 429。
  • GET /api/v1/models 会为每个提供免费额度的模型列出 :free 条目;auto:free 永远路由到免费模型。

当前提供免费额度的模型

直接用这些模型 ID 调用即可享有免费额度。列表随上架调整,建议以 API 查询为准。

deepseek/deepseek-v4-flash

免费额度上限

项目
数值
每分钟请求数 (RPM)10 / min
每日请求额度150 / day
账户等级倍率 — 未充值× 1
账户等级倍率 — 已充值× 3

每日额度 = 上表每日请求额度 × 你的账户等级倍率,各免费模型分开计算;auto:free 另有以 IP 为单位的并行上限。个别模型可由平台单独设定更严或更宽的限制,实际值以模型页的「免费额度」区块为准。

超出免费额度之后

额度用完后,只要账户有余额,请求会自动改以该模型的付费价格继续执行(不会中断服务),费用与一般付费调用相同。若你希望超额时直接失败而不是被计费,发送 X-Free-Fallback: false 头部,或在密钥设置中关闭自动转付费 — 这时会返回 429。账户没有余额时,超额请求一律返回 429。

# Return 429 instead of switching to paid routing
-H "X-Free-Fallback: false"

组织管理

如果多人共用 BazaarLink,可以建立一个组织,把成员分到不同 Team,统一管理 API 密钥、可用模型、预算与账务。组织持有共用余额,Team 和成员可以另外设置每月花费上限。

管理你的组织
要新增 Team、邀请成员或调整组织设置,请 前往设置,选择要管理的组织

三层预算系统

每次 API 请求都会检查个人、Team 和组织限制。达到每月预算或余额不足时返回 HTTP 402;支出紧急刹车返回 HTTP 429。

  1. 成员月度预算(OrgMember.monthlyBudget)
  2. Team 月度预算(Team.monthlyBudget)
  3. 组织 Credits 余额(Organization.credits)

费用报表

进入某个组织的管理后台后,打开「报表」即可查看四种每月费用分析:

  • 总览:月度总花费、毛利率、每日趋势折线图
  • 按 Team:各 Team 花费、占比、模型明细、预算使用率
  • 按模型:各 AI 模型花费、平均单价($/1M tokens)
  • 按成员:各成员花费(仅 org_admin 可看)

所有维度均支援 CSV 汇出,含 BOM(Excel 直接开启不乱码)。

建立与管理组织

  1. 前往「设置」,在组织区块建立新组织
  2. 建立后点击组织名称,进入该组织的管理后台
  3. 在管理后台建立 Team,并按需设置成本中心代码和每月预算
  4. 邀请成员(填入 email、指定角色与 Team)
  5. 为成员建立 API 密钥,密钥的用量自动归属到对应的 Team / 成员
  6. 前往「报表」页面查看按 Team / 模型 / 成员分组的月度花费

成员角色

org_admin组织管理员。可管理所有 Team、成员、API 密钥、可用模型、预算、账务、报表、设置和紧急刹车。
billing_viewer财务查看者。可查看组织总览、账务、API 密钥列表和费用报表,但不能修改设置,也看不到逐一成员的花费。
team_adminTeam 管理员。只能管理自己 Team 的成员、邀请、API 密钥、预算和紧急刹车。
member普通成员。可使用分配给自己的组织 API 密钥,并受到个人、Team、组织预算和模型限制。

组织还可以管理什么?

除了成员和 Team,组织管理后台还集中提供以下功能:

  • API 密钥:按组织、Team 或成员建立密钥,查看归属并限制可用模型
  • 内容过滤防护:在文字发送给模型前阻挡、遮蔽或记录敏感内容
  • Allowed Models:限制整个组织、特定 Team、成员或 API 密钥可调用的模型
  • 预算与紧急刹车:设置每月上限,以及分钟/小时支出保护
  • 报表与账务:查看花费、模型用量、Team 分摊、余额、信用额度和付款资料
  • 变更与安全记录:跟踪设置变更、内容过滤命中和其他安全事件
  • 机构方案:教育类组织可另外管理学生 Session 和配额

内容过滤防护

这是组织自己的文字检查规则。使用组织 API 密钥发送请求时,系统会先检查文字,再决定是否发送给模型。org_admin 可在“设置 → 内容过滤防护”中启用、编辑和测试规则。

  • block(阻挡):整个请求返回 HTTP 403,不会发送给模型
  • redact(遮蔽):把匹配文字替换成 [REDACTED],再将处理后的内容发送给模型
  • flag(记录):请求照常发送,但把命中项目写入组织审计记录
  • 可使用内置的敏感信息和 Prompt Injection 模板,也可新增关键词或正则规则
  • 最多 100 条规则;正则规则会先检查安全性,也可使用测试文字预览结果
目前只检查文字输入
目前适用于 Chat Completions、Responses 的纯文字 input,以及 Messages 的文字内容。图片、音频、视频、部分结构化/多模态内容和模型输出不在检查范围内;请勿将它视为完整的数据泄露防护或模型输出审核。

Management API (v1)

Management API 可用于列出组织、建立 Team、加入成员或调整预算,不必手动操作网页。`/api/v1/orgs` 负责组织与成员管理;费用报表使用下方独立的 `/api/orgs/:orgId/reports/*` 路径。

认证
GET /api/v1/orgs 只列出密钥拥有者所属的组织,可使用有效 API 密钥或登录 Session。读取或修改指定组织、Team、成员时,Bearer 必须是 Management Key,而且密钥拥有者必须是该组织的 org_admin;浏览器操作则使用 org_admin 的登录 Session。

组织(Organizations)

GET/api/v1/orgs

列出呼叫者所属的所有组织,包含角色与 joinedAt。

GET/api/v1/orgs/:orgId

取得组织详细资料,包括团队与成员数量。

curl https://bazaarlink.ai/api/v1/orgs \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

Teams

GET/api/v1/orgs/:orgId/teams

列出团队及其成员数,依名称排序。

POST/api/v1/orgs/:orgId/teams
name必填
string
团队显示名称(在组织内须唯一)
costCenterCode
string
会计成本中心代码
monthlyBudget
number | null
团队每月花费上限(USD)
PATCH/api/v1/orgs/:orgId/teams/:teamId

部分更新 — 仅传送要变更的字段。

DELETE/api/v1/orgs/:orgId/teams/:teamId
# Create a team
curl https://bazaarlink.ai/api/v1/orgs/{orgId}/teams \
  -X POST \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Engineering", "costCenterCode": "ENG-001", "monthlyBudget": 500}'

成员(Members)

GET/api/v1/orgs/:orgId/members

列出所有成员,包含巢状的 user(id/name/email)与团队资讯。

POST/api/v1/orgs/:orgId/members
email必填
string
现有 BazaarLink 用户的 Email
role
string
org_admin | billing_viewer | team_admin | member(预设:member)
teamId
string
指派至团队(角色为 team_admin 时必填)
monthlyBudget
number | null
每位成员每月花费上限(USD)

若 email 无对应 BazaarLink 帐号则回传 404;已是成员则回传 409。预设角色:member。

PATCH/api/v1/orgs/:orgId/members/:memberId

部分更新 role、teamId 或 monthlyBudget。

DELETE/api/v1/orgs/:orgId/members/:memberId

若移除对象为最后一位 org_admin,回传 400。

# Add a member
curl https://bazaarlink.ai/api/v1/orgs/{orgId}/members \
  -X POST \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "alice@example.com", "role": "member", "monthlyBudget": 50}'

# Remove a member
curl https://bazaarlink.ai/api/v1/orgs/{orgId}/members/{memberId} \
  -X DELETE \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

Reports API

Reports API 是组织报表页面实际使用的数据来源,也可用于内部仪表板、每月对账或自动下载 CSV。org_admin 可查看所有报表;billing_viewer 可查看总览、Team 和模型数据,但不能查看逐一成员的花费。支持登录 Session 或 Bearer Management Key。

请传入 year 和 month(1–12)。overview 与 by-team 缺省时使用当前月份;by-model、by-member 和 export 则要求两者都必须提供。建议每次都明确传入两个参数。

端点
说明
GET /api/orgs/:orgId/reports/overview总花费、毛利率、每日趋势
GET /api/orgs/:orgId/reports/by-team各团队花费、占比 %、模型分布、预算使用率
GET /api/orgs/:orgId/reports/by-model各模型花费、平均价格($/1M tokens)
GET /api/orgs/:orgId/reports/by-member各成员花费 — 仅限 org_admin
GET /api/orgs/:orgId/reports/exportCSV 下载;可加 ?view=overview|by-team|by-model|by-member
# Monthly overview via management key
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/overview?year=2026&month=3" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

# By-team breakdown
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/by-team?year=2026&month=3" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

# Export CSV (downloads file)
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/export?year=2026&month=3&view=by-team" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -o report.csv

错误响应对照

401API key 无效或已撤销
403RBAC 阻挡(呼叫者角色不足)或模型不在 Allowed Models 白名单
402每月预算、信用额度或可用余额不足
429速率限制或组织/Team/成员层级的支出紧急刹车;若有 Retry-After 请按其等待
503平台全局支出紧急刹车,或服务暂时不可用

允许模型(白名单)

限制您的组织、团队或个别成员可调用的模型。适用于阻挡昂贵或未审核的模型、强制统一模型规格,或将团队限定于单一供应商。

运作方式

  • 三个独立层级 — 组织、团队、成员 — 各自维护一份清单(数据库中以 String[] 存储)。
  • 三层皆为空时,所有模型皆可使用(默认行为)。
  • 当一个或多个层级非空时,实际生效清单为各非空层级的交集 — 模型必须在所有受限层级都被允许才能通过。
  • 变更于数秒内生效(60 秒内存缓存 + 5 分钟 Redis 缓存;更新时两者皆会清除)。

格式规则

  • 精确匹配 — 例如 openai/gpt-4o(仅限此精确模型)。
  • 供应商通配符 — 例如 openai/*(openai/ 前缀下的任何模型)。
  • 仅限小写。每份清单最多 200 项,每项最多 100 字符。

管理位置

Org Portal → Allowed Models。org_admin 可编辑组织 / 团队 / 成员清单;team_admin 可编辑自己的团队及其下成员。

拦截时的错误响应

调用未允许的模型会返回 HTTP 403,body 如下:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": {
    "message": "Model is not allowed for this account",
    "code": "model_not_allowed"
  }
}

管理 API

所有端点皆接受 Web Session 或 Bearer Management Key(sk-bl-...)。PATCH 会替换整份清单;传 [] 即可清空。

# Org-level list
GET    /api/orgs/:orgId/allowed-models
PATCH  /api/orgs/:orgId/allowed-models

# Team-level list
GET    /api/orgs/:orgId/teams/:teamId/allowed-models
PATCH  /api/orgs/:orgId/teams/:teamId/allowed-models

# Member-level list
GET    /api/orgs/:orgId/members/:memberId/allowed-models
PATCH  /api/orgs/:orgId/members/:memberId/allowed-models

# Example: restrict an org to OpenAI + a specific Anthropic model
curl -X PATCH https://bazaarlink.ai/api/orgs/$ORG_ID/allowed-models \
  -H "Authorization: Bearer sk-bl-..." \
  -H "Content-Type: application/json" \
  -d '{"allowedModels": ["openai/*", "anthropic/claude-sonnet-4.6"]}'

支出熔断(Spend Kill Switch)

双窗口支出上限,当上游成本飙升时阻挡后续请求。设计用于在失控脚本、无限循环或密钥被盗滥用造成实际损失之前及时拦截。

运作方式

  • Redis 中按 scope 追踪两个固定窗口:1 分钟与 1 小时上游成本(USD)。
  • 任一窗口的支出达到阈值时,该 scope 的后续请求皆会被拒绝,直到窗口于整点边界重置为止。
  • 默认值:每分钟 $5、每小时 $20,默认启用。
  • 计数器存于 Redis 并设有 TTL — 自动恢复,组织 / 团队 / 成员等级触发后无需手动重置。

Scope(成员覆盖团队,团队覆盖组织)

每一层皆可设定自身阈值。解析顺序为 成员 → 团队 → 组织 → 平台默认 — 每个字段(cbEnabled、cbMinuteUsd、cbHourlyUsd)以第一个非 null 值为准。

  • 组织层级 — 适用于该组织下的所有 key。在 Org Portal → Circuit Breaker 设定。
  • 团队层级 — 适用于标记到该团队的所有 key。对这些 key 覆盖组织设定。
  • 成员层级 — 仅适用于标记到该成员的 key。覆盖团队与组织设定。

触发行为

触发时请求会快速失败(不会发出上游调用)。响应为 HTTP 429,body 如下:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{
  "error": {
    "message": "Spend circuit breaker tripped at member scope (minute window: $5.2341 ≥ $5.00). Try again later or contact your organization owner."
  }
}
全局与作用域
另有一个独立的全局平台级熔断(由运维人员控制,不会显示于组织门户),返回 HTTP 503 并带有 Retry-After header。运维人员设定它以保护平台抵御多租户滥用 — 无法从您的组织设定覆盖。

审计日志

每次触发事件与每次设定变更都会被记录:

  • 触发事件 — 动作 org.cb.tripped / team.cb.tripped / org_member.cb.tripped。每个 scope+window 每小时去重为一笔,避免持续触发刷爆日志。
  • 设定变更 — 动作 org.cb.update / team.cb.update / org_member.cb.update。记录变更前后的值与执行者。

管理 API

组织管理员可透过 API 读取与更新设定。所有端点皆接受 Web Session 或 Bearer Management Key(sk-bl-...)。PATCH body 可只送部分字段;传 null 会清空该字段并回退至上层设定。

# Org-level config
GET    /api/orgs/:orgId/circuit-breaker
PATCH  /api/orgs/:orgId/circuit-breaker

# Team-level config
GET    /api/orgs/:orgId/teams/:teamId/circuit-breaker
PATCH  /api/orgs/:orgId/teams/:teamId/circuit-breaker

# Member-level config
GET    /api/orgs/:orgId/members/:memberId/circuit-breaker
PATCH  /api/orgs/:orgId/members/:memberId/circuit-breaker

# Example: tighten the org-level cap to $2/min, $10/hr
curl -X PATCH https://bazaarlink.ai/api/orgs/$ORG_ID/circuit-breaker \
  -H "Authorization: Bearer sk-bl-..." \
  -H "Content-Type: application/json" \
  -d '{"cbMinuteUsd": 2, "cbHourlyUsd": 10, "cbEnabled": true}'

# GET response (org scope)
{
  "settings":         { "cbEnabled": true, "cbMinuteUsd": 2,  "cbHourlyUsd": 10  },
  "resolvedSettings": { "cbEnabled": true, "cbMinuteUsd": 2,  "cbHourlyUsd": 10  },
  "liveSpend":        { "minuteSpend": 0.4123, "hourSpend": 3.8721 }
}

API 密钥轮换

定期轮换 API 密钥是安全最佳实践。BazaarLink 支援零停机的密钥轮换 — 先建立新密钥并部署至应用程式,确认正常后再删除旧密钥,整个过程不中断服务。

注意
API 密钥可随时从仪表板或透过管理 API 撤销。撤销后立即生效,所有使用该密钥的请求将立即失败。

轮换步骤

  1. 建立新的 API 密钥
  2. 更新您的应用程式或环境变数使用新密钥
  3. 确认新密钥正常运作
  4. 停用或删除旧密钥
# Key CRUD via Bearer auth requires a MANAGEMENT key (keyType: "management").
# Standard keys get 403 on /api/v1/keys — create a management key first,
# or rotate keys from the dashboard UI instead.

# Step 1: Create new key (management key auth)
POST https://bazaarlink.ai/api/v1/keys
Authorization: Bearer $BL_MANAGEMENT_KEY
{"name": "Production v2"}
# → saves new key: sk-bl-NEW_KEY_VALUE

# Step 2: Update your application
# export BAZAARLINK_API_KEY=sk-bl-NEW_KEY_VALUE

# Step 3: Verify new key works
curl https://bazaarlink.ai/api/v1/models \
  -H "Authorization: Bearer sk-bl-NEW_KEY_VALUE"

# Step 4: Revoke old key (management key auth again)
DELETE https://bazaarlink.ai/api/v1/keys/:old_key_id
Authorization: Bearer $BL_MANAGEMENT_KEY

活动汇出

将完整 API 使用历史下载为 CSV,用于财务审计、成本分析或合规报告。

CSV 汇出

登入后前往「使用记录」页面,点击右上角的「Export CSV」按钮,即可下载完整历史记录为 CSV 档案。无需呼叫 API。

CSV 栏位

Column
Description
dateISO 8601 timestamp (UTC)
modelModel ID (e.g. openai/gpt-4o)
providerUpstream provider name
prompt_tokensInput token count
completion_tokensOutput token count
total_tokensTotal tokens (prompt + completion)
reasoning_tokensReasoning tokens (o-series / thinking models)
cached_tokensPrompt cache hit tokens
cost_usdCost in USD credits
duration_msEnd-to-end latency in milliseconds
finish_reasonstop / length / content_filter / error
statusHTTP status code from upstream
app_nameX-Title header value (app attribution)

JSON 用量查询(API)

如需程式化存取,可透过 API 查询按期间、模型或密钥分组的聚合统计:

# Query usage data (grouped / aggregated)
GET https://bazaarlink.ai/api/v1/usage
Authorization: Bearer sk-bl-YOUR_KEY

# With period filtering (day | week | month | year)
GET https://bazaarlink.ai/api/v1/usage?period=month

# Response
{
  "period": "month",
  "since": "2025-01-01T00:00:00.000Z",
  "credits": 10.5000,
  "totals": {
    "spend": 0.1812,
    "requests": 309,
    "tokens": 161200,
    "promptTokens": 95000,
    "completionTokens": 66200
  },
  "byModel": [{ "model": "openai/gpt-4o", "spend": 0.0028, "tokens": 1200, "requests": 5 }],
  "byKey":   [{ "keyName": "My Agent", "spend": 0.0028, "tokens": 1200, "requests": 5 }],
  "byApp":   [{ "appName": "MyApp", "spend": 0.0015, "tokens": 600, "requests": 3 }],
  "timeSeries": [{ "date": "2025-01-15", "model": "openai/gpt-4o", "cost": 0.0012, "tokens": 500, "requests": 2 }]
}

用量统计

透过 API 查询详细的使用量统计,包括 token 消耗、成本分析和请求历史记录。

注意
使用量资料以美元计费。个别请求记录可在「使用记录」页面查看或透过 Export CSV 下载;聚合统计可透过 `/api/v1/usage` 端点以 Bearer token 查询。

回应栏位说明

FieldTypeDescription
modelstringModel ID used (e.g., openai/gpt-4o)
providerstringUpstream provider name
prompt_tokensnumberInput tokens consumed
completion_tokensnumberOutput tokens generated
total_tokensnumberTotal tokens (prompt + completion)
reasoning_tokensnumberReasoning tokens (for thinking models)
cached_tokensnumberPrompt tokens served from cache
costnumberTotal cost in USD credits
duration_msnumberEnd-to-end latency in milliseconds
throughputnumberGeneration speed in tokens/sec
finish_reasonstringstop | length | content_filter | error
statusnumberHTTP status code from upstream
app_namestring | nullApplication name (X-Title header)
key_namestringAPI key name used for the request
import httpx

# Aggregated stats (Bearer token — period: day | week | month | year)
response = httpx.get(
    "https://bazaarlink.ai/api/v1/usage",
    headers={"Authorization": "Bearer sk-bl-YOUR_KEY"},
    params={"period": "month"},
)

data = response.json()
totals = data["totals"]
print("This month: US$%.4f  (%d requests)" % (totals["spend"], totals["requests"]))

# Cost breakdown by model
for m in data["byModel"]:
    print("  %s: US$%.4f  (%d reqs, %d tokens)" % (m["model"], m["spend"], m["requests"], m["tokens"]))

Institution Plan

「机构临时方案」让机构(学校、企业、研讨会、政府单位等)通过单一的组织级密钥,向成员发放短期会话令牌。成员无需注册平台账号。组织通过邮箱域名(如 nthu.edu.tw)控制哪些成员可以申请令牌;所有用量均计入组织账户。本页以教育场景为例说明,相同机制适用于任何需要短期、多人临时存取的单位。

适用对象
希望让整个班级使用 AI API、又不想为每位学生单独建立账号、也不想把长期 API 密钥交给未成年学生的学校与教育机构。

架构概览

  • 机构 Key以 sk-edu- 开头。由 org_admin 在组织密钥页面建立。不能直接作为 Bearer token 调用 API — 直接调用会返回 403。
  • Member Session Token以 edu-sess- 开头。学生通过邮箱验证后获得。默认有效期 24 小时;组织管理员可随时撤销。
  • Allowed Domains组织配置可申请会话的邮箱域名(精确匹配,无后缀绕过)。
  • 用量归属所有学生请求均计入组织账户。可在组织仪表板按会话与按邮箱查看用量。

步骤 1 — 平台管理员将组织类型设为 Education

在 sales@bazaarlink.ai / support@bazaarlink.ai 找到目标组织,切换到「Org Type」分页,选择 Education,并设置允许的邮箱域名:

{
  "orgType": "education",
  "eduConfig": {
    "allowedDomains": ["nthu.edu.tw", "student.nthu.edu.tw"],
    "sessionTtlSeconds": 86400,
    "verificationTtlSeconds": 900,
    "maxSessionsPerEmailPerKey": 5
  }
}
域名采精确匹配
nthu.edu.tw 仅匹配 @nthu.edu.tw — 不会匹配 @nthu.edu.attacker.com。子域名必须显式列出(如 student.nthu.edu.tw)。

步骤 2 — 组织管理员建立 机构 Key

在组织的 API Keys 页面,建立新密钥时选择「Education」作为密钥类型。系统会生成 sk-edu-... 密钥并仅显示一次 — 请妥善保存,并通过官方渠道发放给该组织的学生。

步骤 3 — 学生申请验证码

学生前往 /access 输入机构密钥与学校邮箱;或直接调用 API:

POST/api/edu/request-code
curl -X POST https://bazaarlink.ai/api/edu/request-code \
  -H "Content-Type: application/json" \
  -d '{
    "key": "sk-edu-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "email": "alice@nthu.edu.tw"
  }'

# Success (incl. unknown key/email — enumeration defence) → {"ok":true,"sent":true}
# Rate limit / resend cooldown → 429 {"error":"rate_limited"} or {"error":"cooldown"}
# Sends a 6-digit verification code to the email; default 15-minute lifetime
防枚举
request-code 无论密钥是否存在或邮箱域名是否被允许,一律返回 202,防止攻击者探测哪些 edu 密钥存在。失败尝试会记录在组织审计日志中。

步骤 4 — 学生提交验证码换取会话令牌

POST/api/edu/verify
curl -X POST https://bazaarlink.ai/api/edu/verify \
  -H "Content-Type: application/json" \
  -d '{
    "key":   "sk-edu-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "email": "alice@nthu.edu.tw",
    "code":  "646291"
  }'

# Success → 200
{
  "token":     "edu-sess-827d11a1ec67d175cfd4f67f929261f4",
  "expiresAt": "2026-05-04T11:16:00.163Z",
  "organization": { "id": "...", "name": "NTHU AI Lab" }
}

# Wrong code → 400 {"error":"invalid"}
# 5 wrong attempts → 429 {"error":"too_many_attempts"} (code invalidated; re-request)

步骤 5 — 使用会话令牌调用 API

将 edu-sess-... 令牌作为 Bearer token,调用任何 chat / completions / embeddings 端点:

curl -X POST https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer edu-sess-827d11a1ec67d175cfd4f67f929261f4" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
sk-edu- 密钥不可直接使用
将 sk-edu-... 直接作为 Bearer token 发送至 chat 端点会返回:
403 — Education keys cannot be used directly. Visit /access to exchange for a session.
这是有意设置的反向闸口 — 防止学校把长期密钥泄漏给个别学生。

组织仪表板 — 监控与撤销

Education 类型的组织会在侧边导览看到 Education 分页,提供:

  • Settings调整允许的域名、TTL、每个邮箱在每把密钥下的最大会话数,以及每个会话的请求 / token / USD 配额。
  • Sessions列出所有 active / expired / revoked 会话;可按邮箱筛选;可单独撤销会话。
  • 用量统计每个会话的调用次数、token 消耗与累计费用。

安全与限制

项目默认值说明
Session TTL24 小时会话令牌有效期;过期后需重新验证。
验证码 TTL15 分钟邮箱验证码的有效期。
验证码长度6 位数字在 Redis 中以 HMAC-SHA256 哈希存储,绝不明文。
猜测次数上限5 次超过后立即作废该验证码。
request-code 冷却时间60 秒同一 (key, email) 重复请求的最小间隔。
单 IP 限流10 / 15 分钟防垃圾。
单密钥限流100 / 小时防止批量邮件轰炸。
每个邮箱最大会话数5可在 eduConfig 中配置;防止单一信箱囤积令牌。
撤销传播延迟≤ 60 秒L1/L2 缓存 TTL;DB 撤销后最多需 60 秒传播至所有节点。

计费与用量归属

通过会话令牌发出的所有请求 100% 计入持有 edu 密钥的组织账户,与上游供应商(OpenAI / Anthropic / 等)按 token 计费的方式一致。组织仪表板支持按会话、按邮箱、按密钥钻取查看。

回报问题

透过回报问题、错误或建议帮助我们改善 BazaarLink。我们积极监控所有回馈管道。

如何回报

管道
最适用于
回应时间
联络页面一般回馈、功能需求1-2 个工作天
电子邮件错误报告、技术问题24 小时内
API 回应标头自动回报的错误和指标自动

应包含的资讯

  • 请求 ID(来自回应 id 栏位)
  • 使用的模型和传送的参数
  • 预期行为与实际行为
  • 时间戳记和问题频率
  • 错误讯息或 HTTP 状态码

请访问我们的联络页面提交回馈。

常见问题

BazaarLink 与直接呼叫 OpenAI 有什么不同?
BazaarLink 提供美元计费(台币报价)、统一发票、中文支援,以及跨主流模型的单一 API。您可以使用相同的程式码存取 OpenAI、Anthropic、Google 等服务。
我需要更改现有程式码吗?
只需更改 base URL 和 API 密钥。所有其他设定(模型 ID 除外)保持不变。
BazaarLink 会储存我的讯息吗?
预设情况下,我们不储存讯息内容。我们仅记录 token 数量和时间戳记以用于帐单目的。
如何取得统一发票?
统一发票在月底自动开立给商业方案及以上的用户。如需立即开立,请联络我们的支援团队。
支援哪些付款方式?
接受主流信用卡(Visa、Mastercard、American Express)。
支援哪些 OpenAI SDK 功能?
对话完成、串流、工具呼叫、结构化输出(response_format)和助手预填都可使用。功能直接传递至上游供应商。
可以搭配 LangChain 或 CrewAI 等 Agent 框架使用吗?
可以!任何支援 OpenAI API 的框架都可与 BazaarLink 搭配使用。只需设定 base URL 并使用 BazaarLink API 密钥。请参阅 Agent 应用章节了解更多范例。
客服
客服
您好!有什么可以协助?
请留下消息,我们会尽快回复。