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% 交易費。
  •  • 付款方式與各渠道手續費:以即時結帳頁顯示為準。
  •  • 符合資格的台幣渠道:適用營業稅與台灣電子統一發票條件會在付款前顯示。
  •  • 銀行電匯:大額或企業儲值請聯繫我們安排電匯與客製發票。
  • 發票:以 OEN(信用卡)儲值會直接開立台灣電子統一發票並寄送到您的 Email,可填統編。需要採購或月結的公司請聯絡業務(Net-30 可議)。
舉例
購買 US$10.00 額度時,即時付款頁會在確認前列出可用渠道、最終收款金額、適用手續費或稅額,以及收據或發票資格。入金後 US$10.00 餘額按官方牌價扣用,模型消耗端不再加價。

關於匯率

外幣換算採即時匯率;月結以報帳(結算)時匯率為準,儲值入金則以入金當下匯率換算為帳戶餘額。匯率與時間隨帳務留存以供查核。

失敗請求不收費(Zero Completion Insurance)

如果上游請求失敗,而且沒有可結算的用量資料,BazaarLink 會自動退回整筆預扣款。就算串流已經開始、途中才中斷,該次仍扣款 0 美元。

哪些情況不收費
不用開啟任何設定,所有公開推論與媒體 API 都會自動套用。即使上游供應商已向 BazaarLink 收費,BazaarLink 也可能自行吸收該筆失敗成本,不會轉嫁給你。
  • 上游無法連線、拒絕請求,或沒有回傳可用結果
  • 串流在收到最終用量資料前中斷,即使先前已回傳部分內容
  • 回應沒有 usage,或 usage 是所有數值皆為 0 的空資料

output tokens 為 0,不代表一定免費

usage.cost 是此請求收取的美元金額。即使 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 完全相容 — 只需更改

超過 100 秒的長請求建議使用 stream:true。非串流請求約 12 秒後(預設值,可由部署設定調整)會先回應 200 並開始傳送 keepalive 空白;之後若出錯,會以 200 + error JSON 回傳。keepalive 是 JSON 本文前的空白,標準 JSON 解析器會忽略。

基礎 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-.
從瀏覽器直接呼叫(CORS)
公開 API 的每個 /v1 回應都帶 Access-Control-Allow-Origin: *,所以你可以直接在瀏覽器 JavaScript 用 fetch 或 OpenAI SDK 呼叫。請勿把 API 金鑰打包進前端程式碼 — 任何打開網頁的人都看得到;請改用可撤銷、有額度上限的金鑰,或經由你自己的後端轉發。
Model ID 格式 — 建議用 provider/model 完整格式
GET /v1/models 列出「claude-sonnet-4.6」等 id,以及「anthropic/claude-sonnet-4.6」等 canonical alias。請求接受兩種格式;請使用清單中的 id 或 alias。
✓ claude-sonnet-4.6   anthropic/claude-sonnet-4.6

自帶上游金鑰(BYOK)

將上游 API 金鑰綁定至個人帳戶或組織。符合條件的請求會優先使用您的金鑰。上游發生錯誤時,請求可以改試其他可用來源;若沒有可用來源,請求會回傳錯誤。個人金鑰在金鑰頁管理,組織金鑰在組織設定中管理。 前往 BYOK 設定 →

內容過濾

為你的 API 流量啟用雙向內容防護:偵測到提示注入的請求會被擋下(400),請求與回應中的敏感資料(API 金鑰、信用卡號、身分證字號等)會被自動遮蔽。規則與豁免清單可自訂,並提供使用統計。 前往內容過濾設定 →

社群資料(:social)

當問題與 X、Instagram、Threads、TikTok、抖音、小紅書、YouTube 或 Reddit 等社群平台有關時,在模型名稱後加上 :social。模型回答前,BazaarLink 會先取得該平台上相符的貼文、個人檔案或留言,作為參考資料提供給模型。若平台資料未能及時取得,請求會退回一般網路搜尋,確保您仍能得到回答。

範例

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 60 \
  -d '{
    "model": "gpt-5.4-mini:social",
    "messages": [{ "role": "user", "content": "X 上最近有哪些關於 GPT-6 的貼文?" }]
  }'

注意事項

  • 等待時間:社群資料為即時取得,:social 請求可能需要 20 至 40 秒才開始回答;超過 40 秒會退回網路搜尋。請將用戶端逾時設定為至少 60 秒。:online 為一般網路搜尋,速度不受影響。
  • 價格:使用社群資料回答的查詢,與 :online 共用同一份每日免費搜尋額度(沒有餘額時每天 5 次,有餘額或訂閱時每天 10 次,於 UTC 00:00 重置)。超過額度後,每次查詢會依 Data API 價格表(見 GET /v1/data/catalog)計費,並加上模型本身的 token 費用。退回網路搜尋的查詢,計費方式與 :online 相同。
  • 涵蓋範圍:GET /v1/data/catalog 所列的平台。與這些平台無關的查詢,會由網路搜尋回答。
  • 相容性:支援 POST /api/v1/chat/completions、/api/v1/messages 與 /api/v1/responses,串流與非串流皆可,引用來源與 :online 相同。:online 與 :social 不能同時用在同一個模型名稱上(會回傳 400 invalid_web_search_options)。

從 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 候選清單、串流、工具呼叫、結構化輸出的 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
帳單以美元計價,並可開立台灣電子統一發票。:nitro 等上游專屬路由控制會被忽略;BazaarLink 支援的路由方式請參閱 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-6-lunaanthropic/claude-sonnet-4.6google/gemini-3.1-flash-lite-preview另有 99 個
檔案 / PDFbase64 資料 URI(`data:application/pdf;base64,...`)openai/gpt-6-lunaanthropic/claude-sonnet-4.6google/gemini-embedding-2-preview另有 26 個
音訊純 base64 — 不支援 URL,需提供 `format` 欄位google/gemini-3.1-flash-lite-previewxiaomi/mimo-v2.6-flashgoogle/gemini-3.1-pro-preview另有 15 個
影片URL(CDN)或 base64 資料 URIgoogle/gemini-3.1-flash-lite-previewqwen/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-3.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-3.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-3.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-3.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

回應可能包含 x-request-id、非串流回應的 x-generation-id、x-ratelimit-*、適用時的 retry-after,以及 auto 或 auto:free 路由的 x-auto-resolved-model。

x-request-id: 85e6f35c71a31f19-SJC
x-generation-id: 85e6f35c71a31f19-SJC
x-ratelimit-limit: 200
x-ratelimit-remaining: 198
x-ratelimit-reset: 1740000060
retry-after: 5
x-auto-resolved-model: openai/gpt-4o

點數限制

收到 402 代表帳戶餘額或金鑰花費上限已歸零,而非請求過於頻繁。這類回應不會帶速率限制標頭;若在串流過程中觸發,會以 SSE 錯誤事件回傳,而非直接改變 HTTP 狀態碼。

402 Insufficient Credits
當帳戶餘額歸零時,API 會回傳 HTTP 402,訊息為 "Insufficient credits. Please top up to continue." — 請監控回應中的 usage.cost 以即時掌握花費。

IP 白名單

每把 API 金鑰都可以設定獨立的 IP 白名單,只有來自指定來源 IP 的請求能使用這把金鑰。

什麼情況適合使用

適合部署在具有固定出口 IP 的正式環境伺服器或企業內網服務。若應用程式從家用網路、行動網路或其他會變動的位址發出請求,請先確認出口 IP 穩定,否則可能把自己鎖在外面。

如何設定

前往 /keys ,打開該把金鑰的「⋯」選單,選擇「IP 白名單」,輸入項目後儲存。

也可以使用 PATCH /api/v1/keys/:id,搭配登入 session 或 Management API key 設定:

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

{
  "allowedCidrs": [
    "203.0.113.7",
    "198.51.100.0/24"
  ]
}

# Clear the allowlist and return to unrestricted access
{"allowedCidrs": []}

項目格式

在 UI 中每行輸入一個值;使用 API 時,將相同值放進 `allowedCidrs` 陣列。可接受裸 IPv4 位址、IPv4 CIDR,或 IPv6 字面值(僅精確比對)。

203.0.113.7
198.51.100.0/24
2001:db8::1

運作方式

留空(送出空的 [] 陣列)代表允許所有來源 IP。這是預設值,現有金鑰行為維持不變。

來源 IP 取自 `cf-connecting-ip` 標頭。

名單非空但解析不到來源 IP 時,請求會被拒絕(fail-closed)。

⚠️ 重要:被拒絕的請求只會回一般 401
如果來源 IP 不在名單內,或無法解析來源 IP,回應與「金鑰無效」完全相同的一般 HTTP 401,不會有專屬錯誤訊息。這是刻意的安全設計,避免竊得金鑰的人知道白名單存在;代價是設錯時症狀跟金鑰失效一模一樣,而且很難除錯。儲存前請先確認自己的伺服器出口 IP 已經在名單內。
⚠️ 重要:IPv6 只支援完全相同字串比對
IPv6 不做網段運算,位址必須和字串完全相同。如果您的 IPv6 位址會變動,可能會被鎖在外面;只有 IPv4 支援 /0–/32 CIDR 網段。
設定後何時生效
PATCH 或頁面儲存成功後,執行更新的執行個體會立即清除快取。正常情況下,其他執行個體最慢約 15 秒內同步;若共享 Redis 暫時不可用,跨執行個體的失效無法即時傳播,最長可能受 1 小時快取 TTL 影響。

個人緊急煞車

針對您所有 API 金鑰套用的固定 1 分鐘 / 1 小時 USD 支出上限。當時間窗口的門檻被觸及時,新的請求將收到 HTTP 429;窗口於整點邊界自動重置。

cbEnabled
boolean
啟用
cbMinuteUsd
number | null
每分鐘 USD 上限 · 使用預設值
cbHourlyUsd
number | null
每小時 USD 上限 · 使用預設值
(繼承預設值)
數值至少為 0.01(或留空使用預設值)
個人緊急煞車 · 調整 →

帳號安全

除了帳號密碼,BazaarLink 也支援兩步驟驗證,為登入多加一層保護。

啟用兩步驟驗證(TOTP)

  1. 前往「設定」頁面,找到「兩步驟驗證(TOTP)」區塊,點擊「啟用兩步驟驗證」。
  2. 用驗證器 App(例如 Google Authenticator)掃描畫面上的 QR code,或手動輸入下方顯示的密鑰。
  3. 輸入驗證器產生的 6 位數驗證碼並確認,即完成啟用。

啟用後系統會顯示 8 組備援碼(僅顯示這一次),每組 10 碼、限用一次;請立即抄下或複製,保存在手機以外的安全地方,手機遺失或無法使用驗證器時可用備援碼登入。

啟用後的登入流程
之後每次登入,除了密碼(或 Google 登入)之外,還需要輸入驗證器產生的驗證碼或一組備援碼,才能完成登入。

其他帳號防護

搭配下列功能,可以進一步降低金鑰外洩或誤用造成的損失:

  • IP 白名單 — 將 API 金鑰限制在指定的來源 IP 才能使用。
  • 個人緊急煞車 — 對單一分鐘與單一小時的花費各自設定上限,超過即自動暫停。
  • 金鑰花費上限 — 建立或更新 API 金鑰時,設定每日、每週或每月的花費上限。

圖片生成

透過 /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-3.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!"}],
)

錯誤代碼

錯誤回應格式

錯誤 envelope 依端點而異。若有 error.type,請搭配 HTTP 狀態碼判斷;error.code 可能是字串或數字狀態碼,也可能省略;error.message 僅供顯示。

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

HTTP 狀態與 error.code

錯誤 envelope 依端點而異。若有 error.type,請搭配 HTTP 狀態碼判斷;error.code 可能是字串或數字狀態碼,也可能省略;error.message 僅供顯示。

代碼
名稱
說明
424依賴失敗您自行設定的 BYOK 金鑰被上游供應商拒絕;請在 BYOK 設定中檢查或輪替。此錯誤只會在 strict 模式出現
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,也可能代表不同的帳務控制。請依下列穩定代碼顯示正確的處理方式。

代碼
說明
byok_key_invalid您自行設定的 BYOK 金鑰被上游供應商拒絕;請在 BYOK 設定中檢查或輪替。此錯誤只會在 strict 模式出現。
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
byok_key_invalid424

內容審查

所有請求在送往模型端之前,都會先經過自動化內容審查。不符合使用規範的請求會被拒絕,不會送達模型,並回傳 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??????? 429?? Retry-After ? X-RateLimit-* ?????
限流懲罰封鎖429數字 code 429、暫時限制訊息及 Retry-After。
全域支出緊急煞車503數字 code 503、全域支出上限訊息,以及 30 或 300 秒的 Retry-After。
組織/團隊/成員/使用者支出煞車429數字 code 429,訊息會指出 spend circuit breaker 及受影響範圍。
帳務與預算控制402使用上方列出的穩定帳務字串代碼。

錯誤 envelope 依端點而異。若有 error.type,請搭配 HTTP 狀態碼判斷;error.code 可能是字串或數字狀態碼,也可能省略;error.message 僅供顯示。

影片與媒體資源狀態

影片驗證通常回傳數字 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 ????????? error ??????? SSE ?????? data: [DONE]??????????????????????????

data: {"error":{"message":"The request could not be completed.","type":"upstream_error","code":502}}

data: [DONE]

// 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 訊息。接續行為由所選的上游模型與供應商實作,因此並非每條路由都保證支援。

訊息轉換

The client-supplied transforms field is ignored and removed before an upstream request. It cannot enable or disable message transformations. BazaarLink may apply context handling under its own server-side rules; shorten the input or select a model with a larger context window when needed.

Unsupported request field
Do not rely on transforms values such as middle-out; they do not change how this request is routed or processed.

零資料保留

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/gpt-5.5",
  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/gpt-5.5, gpt-5.6-sol, gpt-5.4reasoning_effort: "low" | "medium" | "high"medium
deepseek/deepseek-r1—永遠啟用(無法關閉)
# Qwen3: explicitly enable thinking mode
response = client.chat.completions.create(
    model="qwen/qwen3.7-flash",
    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 GPT-5.6 Sol — specify effort level
const response2 = await client.chat.completions.create({
  model: "openai/gpt-5.6-sol",
  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)以改善感知延遲
  • 對延遲敏感的場景選擇較小的模型(flash/mini/haiku)
  • 啟用提示快取以降低重複請求的延遲
import time

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

stream = client.chat.completions.create(
    model="google/gemini-3.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=BAZAARLINK_REQUEST_ID" \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

# Response
{
  "data": {
    "id": "85e6f35c71a31f19-SJC",
    "model": "google/gemini-3.5-flash",
    "duration_ms": 842,
    "throughput": 61.2,
    "usage": { "prompt_tokens": 12, "completion_tokens": 48, "total_tokens": 60 }
  }
}

可用性優化

上游發生錯誤時,請求可以改試其他可用來源;若沒有來源可處理,請求會回傳錯誤。熔斷器會限制重複嘗試,平台也會監測供應來源狀態。

Note
BazaarLink 追蹤所有上游供應商的可用性狀態。當供應商錯誤率超過閾值時,熔斷器會自動觸發,將請求路由至下一個可用供應商。

可用性機制

  • 熔斷器:自動偵測並隔離故障供應商
  • 上游來源發生問題時,請求可以改試其他可用來源;若沒有可用來源,請求會回傳錯誤。
  • 供應商健康監控:持續追蹤各供應商的錯誤率和延遲
  • 重試邏輯:暫時性錯誤(5xx)自動重試

熔斷器配置

# If an upstream source returns an error, the request can try another available source.
# Requests handled by a platform model are billed at that model's catalog price.

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

# Check whether another source handled the request (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-3.5-flashgoogle/gemini-3.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-v4.1-flash

路由優先順序

當您發送請求時,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
simpledeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
standarddeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
complexdeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
reasoningdeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
codingdeepseek/deepseek-v4-flash-0731free
qwen/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
datadeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
searchdeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
socialdeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
emaildeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
calendardeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled
tradingdeepseek/deepseek-v4-flash-0731free
qwen/qwen3.7-flash
enabled

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

超出免費額度之後
免費額度用完後,帳戶仍有餘額時,超額請求會依該模型付費價格計費;若希望超額時收到 429,請傳送 X-Free-Fallback: false 標頭或在金鑰設定中關閉付費轉換。餘額不足時,超額請求會回傳 429。 當請求真的被這樣降級時,回應會帶上 x-bl-free-fallback: daily 或 x-bl-free-fallback: rpm 標頭,標示是哪個上限觸發的,讓你在請求當下就能偵測到這次轉換,而不必等到帳單才知道。沒有降級的請求不會帶這個標頭。
X-Auto-Resolved-Model
實際選用的模型會同時出現在 X-Auto-Resolved-Model 回應標頭與回應本體的 model 欄位。

模型變體

客戶端路由欄位會被忽略
若請求包含 provider(整個物件)、transforms、route、頂層 service_tier 或 preset,這些欄位會在送往上游前移除,無法選擇上游或價格層級。Chat Completions 與 Responses 端點支援 models 陣列作為本地備援清單:BazaarLink 會自行路由每個模型並依該模型的 BazaarLink 客戶價格計費,清單不會轉發給上游。客戶提供的 :nitro、:floor 與 :exacto 後綴會被忽略;:eco 仍是 BazaarLink 的經濟方案,並在內部對應至 BazaarLink 的 :floor。:free 仍是獨立的目錄模型變體。

獨立模型 ID

:free、:extended 和 :thinking 等目錄變體可代表具有不同能力或目錄價格的項目。上游路由與客戶價格由 BazaarLink 目錄及伺服器端規則決定。

:free
:extended
:thinking
:nitro
:floor
:exacto
網路搜尋附加費用
使用 plugins、:online 或 web_search_options 要求網路搜尋時,現有行為維持不變,且可能產生上游附加費用;費用會計入該請求所用的金鑰,也就是 BazaarLink 平台金鑰或您的 BYOK 金鑰。
:online

免費模型

部分模型提供受限速的免費額度。免費資格由平台按模型授予 — 直接用原本的模型 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
deepseek/deepseek-v4-flash-0731free

免費額度上限

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

每日額度 = 上表每日請求額度 × 你的帳戶等級倍率,各免費模型分開計算;auto:free 另有以 IP 為單位的平行上限。個別模型可由平台單獨設定更嚴或更寬的限制,實際值以模型頁的「免費額度」區塊為準。 免費額度以「單位」計算,並非單純的請求次數:單次請求消耗的單位數會隨 prompt 的 context 長度增加。因此在相同的每日額度下,長 context 請求的實際可用次數會明顯少於短 prompt。

超出免費額度之後

免費額度用完後,帳戶仍有餘額時,超額請求會依該模型付費價格計費;若希望超額時收到 429,請傳送 X-Free-Fallback: false 標頭或在金鑰設定中關閉付費轉換。餘額不足時,超額請求會回傳 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 金鑰有助於安全。請先建立新金鑰、更新並驗證應用程式,再撤銷舊金鑰;此流程不保證零停機。

備註
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)
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_ntd以新台幣計算的扣款金額
duration_msEnd-to-end latency in milliseconds
finish_reasonstop / length / content_filter / error
statusBazaarLink 回應狀態碼
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)
providerstring固定值:bazaarlink(BazaarLink)
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
costnumber此請求向客戶收取的美元金額
duration_msnumberEnd-to-end latency in milliseconds
throughputnumberGeneration speed in tokens/sec
finish_reasonstringstop | length | content_filter | error
statusnumberBazaarLink 回應狀態碼
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 數量和時間戳記以用於帳單目的。
如何取得統一發票?
以 OEN(信用卡)付款會直接開立台灣電子統一發票並寄送到您的 Email,可填統編。企業月結或報價請先聯絡企業服務。
支援哪些付款方式?
接受主流信用卡(Visa、Mastercard、American Express)。
支援哪些 OpenAI SDK 功能?
對話完成、串流、工具呼叫、結構化輸出(response_format)和助手預填都可使用。功能直接傳遞至上游供應商。
可以搭配 LangChain 或 CrewAI 等 Agent 框架使用嗎?
可以!任何支援 OpenAI API 的框架都可與 BazaarLink 搭配使用。只需設定 base URL 並使用 BazaarLink API 金鑰。請參閱 Agent 應用章節了解更多範例。
客服
客服
您好!有什麼可以協助?
請留下訊息,我們會盡快回覆。