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% 交易費。
  •  • 付款方式與各渠道手續費:以即時結帳頁顯示為準。
  •  • 符合資格的台幣渠道:適用營業稅與台灣電子統一發票條件會在付款前顯示。
  •  • 銀行電匯:大額或企業儲值請聯繫我們安排電匯與客製發票。
  • 發票:僅由目前實際提供且標示可開票的付款渠道,或經確認的企業帳務安排提供。需要統編、採購或月結的公司應在付款前聯絡業務確認(Net-30 可議)。
舉例
購買 US$10.00 額度時,即時付款頁會在確認前列出可用渠道、最終收款金額、適用手續費或稅額,以及收據或發票資格。入金後 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 應用
所有請求會先經過內容審查;不符合使用規範者不會送往模型端,並回傳 403。

五分鐘內開始使用。BazaarLink 與 OpenAI SDK 完全相容 — 只需更改

基礎 URL

https://api.bazaarlink.ai/v1

api.bazaarlink.ai 是 API 專用入口,與網站分開部署。先前的基礎網址 https://bazaarlink.ai/api/v1 仍完全支援,既有整合無需變更。

使用 OpenAI SDK

BazaarLink 與 OpenAI SDK 完全相容。只需更改 base URL 和 API 金鑰 — 所有其他程式碼保持不變。

from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/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-4o)。常見家族(gpt-*、claude-*)在所有端點都會自動補上前綴,chat/completions 另外會把無歧義的裸模型名(例如 gemini-2.5-flash)從目錄解析成完整 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://api.bazaarlink.ai/v1、API 金鑰換成 sk-bl- 開頭的 BazaarLink 金鑰。

  1. base URL:https://openrouter.ai/api/v1 → https://api.bazaarlink.ai/v1
  2. API 金鑰:sk-or-... → sk-bl-...(於 /keys 建立)
  3. 模型 ID:同樣使用 provider/model 格式(例如 anthropic/claude-sonnet-4.6);完整清單見 GET /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://api.bazaarlink.ai/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.3-codexanthropic/claude-sonnet-4.6google/gemini-2.5-flash-lite另有 115 個
檔案 / PDFbase64 資料 URI(`data:application/pdf;base64,...`)openai/gpt-5.3-codexanthropic/claude-sonnet-4.6google/gemini-2.5-flash-lite另有 57 個
音訊純 base64 — 不支援 URL,需提供 `format` 欄位google/gemini-2.5-flash-litebytedance/seedance-2.0google/gemini-3.1-flash-lite-preview另有 15 個
影片URL(CDN)或 base64 資料 URIgoogle/gemini-2.5-flash-liteqwen/qwen3.8-maxz-ai/glm-5v-turbo另有 38 個

範例:

# Image — URL or base64 data URI
curl https://api.bazaarlink.ai/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://api.bazaarlink.ai/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://api.bazaarlink.ai/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://api.bazaarlink.ai/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://api.bazaarlink.ai/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 回應。重試時請使用指數退避策略。

Response Headers

每筆成功回應都會帶上 rate limit headers,方便 client 端追蹤使用量:

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 Insufficient Credits
當帳戶餘額歸零時,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://api.bazaarlink.ai/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://api.bazaarlink.ai/v1/videos \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"bytedance/seedance-2.0","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://api.bazaarlink.ai/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://api.bazaarlink.ai/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://api.bazaarlink.ai/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://api.bazaarlink.ai/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Returns 204 No Content on success

查詢餘額

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

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

查詢用量

GET https://api.bazaarlink.ai/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://api.bazaarlink.ai/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

內容審查

所有請求在送往模型端之前,都會先經過自動化內容審查。不符合使用規範的請求會被拒絕,不會送達模型,並回傳 403 錯誤。

會被攔截的內容類別

審查依據我們的使用規範(Acceptable Use Policy)進行,主要攔截以下類別的內容:

  • 性剝削內容
  • 暴力威脅
  • 違法行為的操作指導
  • 生物危害相關內容

403 回應格式

請求被審查攔截時,會收到以下格式的錯誤回應:

{
  "error": {
    "message": "Your prompt was blocked by content moderation.",
    "type": "invalid_request_error",
    "code": "content_filter"
  }
}

被攔截的請求不會計費——你不會為被拒絕的請求付費。

誤判申訴

如果你認為某次請求被誤判攔截,請聯繫支援團隊並附上請求時間與(如方便的話)request id,我們會協助複查。

隱私說明

每一筆請求都會經過自動化內容審查。

判定為違規的請求,我們會保留其內容作為合規舉證之用。

其他請求不會保留完整提示詞內容。

速率限制、預算與緊急煞車

這些控制可能拒絕原本有效的請求。它們與供應商錯誤不同,也需要不同的復原方式。

控制機制
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://api.bazaarlink.ai/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-4o",
            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://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "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-4o",
        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-4o",
    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-4o",
        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://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "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://api.bazaarlink.ai/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-4o",
  "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-4o",
    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 /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://api.bazaarlink.ai/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://api.bazaarlink.ai/v1
  2. 把 Override OpenAI API Key 設為你的 sk-bl-... BazaarLink 金鑰
  3. 輸入你想用的 model 名稱 — Claude 模型請看下方 bz- 前綴規則。
向後相容
舊版的 /cursor 相容端點仍可使用,兩個主機都支援(https://api.bazaarlink.ai/v1/cursor 與 https://bazaarlink.ai/api/v1/cursor)。它只是 /v1/chat/completions 的一行轉發 — 新設定請改用上方的基礎網址。

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 提供服務時很有用。

自動處理的事項

當請求送到 /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://api.bazaarlink.ai/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
simpleqwen/qwen3.7-flash
enabled
standardqwen/qwen3.7-flash
enabled
complexqwen/qwen3.7-flash
enabled
reasoningqwen/qwen3.7-flash
enabled
codingqwen/qwen3.7-flash
enabled
visionopenai/gpt-5.4-image-2
disabled
imageopenai/gpt-5.4-image-2
disabled
videogoogle/gemini-2.5-flash-lite
disabled
dataqwen/qwen3.7-flash
enabled
searchqwen/qwen3.7-flash
enabled
socialqwen/qwen3.7-flash
enabled
emailqwen/qwen3.7-flash
enabled
calendarqwen/qwen3.7-flash
enabled
tradingqwen/qwen3.7-flash
enabled

部分模型提供受限速的免費額度。免費資格由平台按模型授予 — 直接用原本的模型 ID 呼叫即可;:free 後綴只是可選別名(對付費模型自行加上 :free 不會變免費)。

超出免費額度之後
額度用完後,只要帳戶有餘額,請求會自動改以該模型的付費價格繼續執行(不會中斷服務),費用與一般付費呼叫相同。若你希望超額時直接失敗而不是被計費,送出 X-Free-Fallback: false 標頭,或在金鑰設定中關閉自動轉付費 — 這時會回傳 429。帳戶沒有餘額時,超額請求一律回 429。 當請求真的被這樣降級時,回應會帶上 x-bl-free-fallback: daily 或 x-bl-free-fallback: rpm 標頭,標示是哪個上限觸發的,讓你在請求當下就能偵測到這次轉換,而不必等到帳單才知道。沒有降級的請求不會帶這個標頭。
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 /v1/models 會為每個提供免費額度的模型列出 :free 條目;auto:free 永遠路由到免費模型。

目前提供免費額度的模型

直接用這些模型 ID 呼叫即可享有免費額度。清單隨上架調整,建議以 API 查詢為準。

qwen/qwen3.7-flash

免費額度上限

項目
數值
每分鐘請求數 (RPM)10 / min
每日請求額度50 / day
帳戶等級倍率 — 未儲值× 1
帳戶等級倍率 — 已儲值× 2

每日額度 = 上表每日請求額度 × 你的帳戶等級倍率,各免費模型分開計算;auto:free 另有以 IP 為單位的平行上限。個別模型可由平台單獨設定更嚴或更寬的限制,實際值以模型頁的「免費額度」區塊為準。

超出免費額度之後

額度用完後,只要帳戶有餘額,請求會自動改以該模型的付費價格繼續執行(不會中斷服務),費用與一般付費呼叫相同。若你希望超額時直接失敗而不是被計費,送出 X-Free-Fallback: false 標頭,或在金鑰設定中關閉自動轉付費 — 這時會回傳 429。帳戶沒有餘額時,超額請求一律回 429。

當請求真的被這樣降級時,回應會帶上 x-bl-free-fallback: daily 或 x-bl-free-fallback: rpm 標頭,標示是哪個上限觸發的,讓你在請求當下就能偵測到這次轉換,而不必等到帳單才知道。沒有降級的請求不會帶這個標頭。

# 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 金鑰、預算與緊急煞車,不能管理其他 Team。
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、加入成員或調整預算,不必手動操作網頁。`/v1/orgs` 是組織與成員管理;費用報表則使用下方獨立的 `/api/orgs/:orgId/reports/*` 路徑。

認證方式
GET /v1/orgs 只會列出金鑰擁有者所屬的組織,可使用有效 API 金鑰或登入 Session。讀取或修改指定組織、Team、成員時,Bearer 必須是 Management Key,而且金鑰擁有者必須是該組織的 org_admin;瀏覽器操作則使用 org_admin 的登入 Session。Management Key 可在該組織的「API 金鑰」頁建立。

組織(Organizations)

GET/v1/orgs

列出呼叫者所屬的所有組織,包含角色與加入時間。

GET/v1/orgs/:orgId

取得組織詳細資訊,含團隊與成員數量。

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

Teams

GET/v1/orgs/:orgId/teams

列出所有團隊及其成員數,依名稱排序。

POST/v1/orgs/:orgId/teams
name必填
string
團隊顯示名稱(在組織內必須唯一)
costCenterCode
string
會計成本中心代碼
monthlyBudget
number | null
團隊每月花費上限(美元)
PATCH/v1/orgs/:orgId/teams/:teamId

部分更新 — 只需傳入要變更的欄位。

DELETE/v1/orgs/:orgId/teams/:teamId
# Create a team
curl https://api.bazaarlink.ai/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/v1/orgs/:orgId/members

列出所有成員,含巢狀 user 資訊(id/name/email)與所屬團隊。

POST/v1/orgs/:orgId/members
email必填
string
已存在的 BazaarLink 使用者 email
role
string
org_admin | billing_viewer | team_admin | member(預設:member)
teamId
string
指派至團隊(若 role 為 team_admin 則必填)
monthlyBudget
number | null
個別成員每月花費上限(美元)

若 email 無對應 BazaarLink 帳號則回傳 404;已是成員則回傳 409。預設角色:member。

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

部分更新 role、teamId 或 monthlyBudget。

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

若移除對象為最後一位 org_admin,回傳 400。

# Add a member
curl https://api.bazaarlink.ai/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://api.bazaarlink.ai/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 則要求兩者都必須提供。為避免結果因端點而異,建議每次都明確傳入 year 和 month。

Endpoint
說明
GET /api/orgs/:orgId/reports/overview總花費、毛利率、每日趨勢
GET /api/orgs/:orgId/reports/by-team各團隊花費、佔比、模型分佈、預算使用率
GET /api/orgs/:orgId/reports/by-model各模型花費、平均單價(每百萬 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 秒 + Redis 快取 5 分鐘;更新時兩者皆會清除)。

Pattern 格式

  • 完全比對 — 例如 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

所有 endpoint 均接受 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)

雙視窗支出上限,當上游成本飆升時阻擋後續請求。設計用來在失控腳本、無窮迴圈或金鑰外洩濫用造成實際金額損失之前及時遏止。

運作原理

  • 每個 scope 在 Redis 中追蹤兩個固定視窗:1 分鐘與 1 小時的上游成本(USD)。
  • 若任一視窗的支出達到門檻,該 scope 後續所有請求都會被拒絕,直到該視窗於整點邊界重置為止。
  • 預設值:每分鐘 $5、每小時 $20;預設為不啟用,需自行開啟。
  • 計數器存放於 Redis 並設有 TTL — 自動恢復,組織 / 團隊 / 成員的觸發無需手動重置。

Scope(成員覆蓋團隊,團隊覆蓋組織)

每個層級可設定自己的門檻。解析順序為 member → team → org → 平台預設值 — 每個欄位(cbEnabled、cbMinuteUsd、cbHourlyUsd)取第一個非 null 的值。

  • 組織層級 — 套用至該組織下的所有金鑰。於 Org Portal → Circuit Breaker 設定。
  • 團隊層級 — 套用至標記給該團隊的所有金鑰。對這些金鑰會覆蓋組織層級的設定。
  • 成員層級 — 僅套用於標記給該成員的金鑰。覆蓋團隊與組織層級。

觸發後的行為

觸發時請求會立即失敗(不會打到上游)。回應為 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."
  }
}
全域 vs 範圍
另有一個獨立的全平台層級 circuit breaker(由維運人員控制,不會顯示於 Org Portal),會回傳 HTTP 503 並帶 Retry-After header。維運人員會用它來防禦多租戶層級的濫用 — 無法從您的組織設定覆蓋。

稽核記錄

所有觸發事件以及所有設定變更都會記錄下來:

  • 觸發事件 — actions org.cb.tripped / team.cb.tripped / org_member.cb.tripped。同一 scope+window 在每小時內去重為一筆,避免持續觸發時把記錄洗掉。
  • 設定變更 — actions org.cb.update / team.cb.update / org_member.cb.update。記錄變更前後的值與操作者。

管理 API

Org admin 可透過 API 讀取與更新設定。所有 endpoint 均接受 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 /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://api.bazaarlink.ai/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://api.bazaarlink.ai/v1/models \
  -H "Authorization: Bearer sk-bl-NEW_KEY_VALUE"

# Step 4: Revoke old key (management key auth again)
DELETE https://api.bazaarlink.ai/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://api.bazaarlink.ai/v1/usage
Authorization: Bearer sk-bl-YOUR_KEY

# With period filtering (day | week | month | year)
GET https://api.bazaarlink.ai/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 下載;聚合統計可透過 `/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://api.bazaarlink.ai/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)

「機構臨時方案」讓機構(學校、企業、研討會、政府單位等)能透過一把組織金鑰,發放短效 session token 給成員使用,成員不需建立平台帳號。組織以 email 網域(例 nthu.edu.tw)控管哪些成員可以申請 token,所有用量計入該組織帳戶。本頁以教育場景為例說明,相同機制適用於任何需要短期、多人臨時存取的單位。

適用對象
需要把 AI API 開放給整批成員(員工、活動參與者、公部門人員、使用者等),但不想為每位成員建帳號、也不想分發長效 API key 的機構。

架構概覽

  • 機構 Key以 sk-edu- 開頭,由 org_admin 在組織金鑰頁建立。不能直接當 Bearer token 打 API(會收到 403)。
  • Member Session Token以 edu-sess- 開頭,成員透過 email 驗證後取得,預設 24 小時有效,可被組織管理員撤銷。
  • Allowed Domains組織設定哪些 email 網域 (精確比對,無 suffix 繞過) 可申請 session。
  • 用量歸屬所有成員請求都計入組織帳戶餘額;可按 session、email 在組織後台檢視用量。

步驟 1 — 申請開通機構臨時方案

聯絡 BazaarLink 業務或客服(sales@bazaarlink.ai / support@bazaarlink.ai),告知貴組織需要啟用機構臨時方案,並提供允許的 Email 網域清單(例如 nthu.edu.tw)。我們會為貴組織開通此功能:

{
  "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 — Org Admin 建立 機構 Key

進入組織 API Keys 頁,建立新金鑰時選擇「Education」類型(這是機構金鑰的內部代號)。系統會產生一把 sk-edu-... 金鑰,只在建立當下顯示一次,請保存好並透過官方管道分發給該組織成員。

步驟 3 — 成員申請驗證碼

成員可透過兩種方式申請驗證碼。(a) 前往 /access 頁面,輸入機構金鑰與機構 Email,由前端代為呼叫 API;(b) 直接呼叫 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
防 enumeration
無論 key 是否存在、email 網域是否符合,request-code 一律回 202,避免攻擊者用此端點探測哪些機構金鑰存在。失敗事件會記錄在組織 audit log。

步驟 4 — 成員輸入驗證碼換 session token

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 — 用 session token 呼叫 API

把 edu-sess-... 當 Bearer token 打任何 chat / completions / embeddings 端點即可:

curl -X POST https://api.bazaarlink.ai/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- key 打 API
若把 sk-edu-... 當 Bearer 直接打 chat 端點會收到:
403 — Education keys cannot be used directly. Visit /access to exchange for a session.
這是設計上的反向閘門,避免機構把長效 key 外流給成員個人保存。

組織後台 — 監控與撤銷

Education 類型組織的側邊欄會出現 Education 分頁,提供:

  • Settings調整 allowed domains、TTL、每 email session 上限、每 session 請求 / Token / USD 配額。
  • Sessions列出所有有效 / 已過期 / 已撤銷的 session,可按 email 篩選,逐筆撤銷。
  • 用量統計每個 session 的呼叫次數、token 消耗、累計費用。

安全性與限制

項目預設說明
Session TTL24 小時session token 有效期,過期需重新驗證。
驗證碼 TTL15 分鐘email 驗證碼有效期。
驗證碼長度6 位數字HMAC-SHA256 雜湊存於 Redis,不存明文。
猜測上限5 次超過則該驗證碼立即失效。
request-code 冷卻60 秒同一 (key, email) 重複申請的最短間隔。
每 IP 限流10 次 / 15 分防 spam。
每 key 限流100 次 / 小時防大量發信。
每 email session 上限5可在 eduConfig 調整,避免單一信箱囤積 token。
撤銷生效≤ 60 秒L1/L2 cache TTL;DB 撤銷後最多 60 秒內全節點生效。

計費與用量歸屬

所有成員透過 session token 產生的請求,費用 100% 計入該機構金鑰所屬組織的餘額,與 OpenAI / Anthropic 等供應商實際計費一致(按 token 計算)。組織後台可逐 session、逐 email、逐 key 查詢用量。

回報問題

透過回報問題、錯誤或建議幫助我們改善 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 應用章節了解更多範例。
客服
客服
您好!有什麼可以協助?
請留下訊息,我們會盡快回覆。