認證
金鑰格式、逐把金鑰的限制、以及洩露之後該做什麼。
每個請求都要在 Authorization 標頭裡帶上 API Key:
Authorization: Bearer sk-spicy-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx沒有其他認證方式。開放 API 面(/api/v1/*)只認 Bearer 金鑰,不認 Cookie、不認查詢參數。
文字與影片相容介面(/v1、/v1beta)用的是同一把金鑰,另外也接受 Anthropic SDK 使用的 x-api-key 與 Google GenAI SDK 使用的 x-goog-api-key 標頭,官方 SDK 只改 Base URL 就能用,見文字模型與串流。這兩個標頭在 /api/v1 上無效;任何一面都不接受放在網址查詢參數裡的金鑰。
三個控制面,三套憑證
平台有三個字首不同、憑證體系也完全獨立的面。你作為 API 使用者只會用到第一個,但知道另外兩個存在,就能少追查一類問題:拿錯面的憑證一定是 401,不會是「權限不夠」。
| 面 | 字首 | 憑證 | 誰在用 |
|---|---|---|---|
| 開放 API | /api/v1 | Authorization: Bearer sk-spicy-… | 你的伺服器端程式碼 |
| 使用者控制台 | /console/v1 | 瀏覽器工作階段 Cookie + CSRF 權杖標頭 | 網頁控制台 |
| 營運管理 | /admin/v1 | 管理員工作階段;敏感操作須確認目前帳號的密碼 | 我們的營運團隊,你不會接觸到 |
憑證不能跨面使用
三個面的工作階段簽章金鑰、audience 與 Cookie 名稱各自獨立。把控制台的 Cookie 拿去呼叫 /api/v1,或者把 API Key 塞進控制台請求,都會被判為無效憑證——不是權限不足,是根本通不過驗證。
這不是限制,是設計:一把洩露的 API Key 無法用來登入你的控制台,反過來一段被竊取的瀏覽器工作階段也發不出 API 呼叫。
三個面的差別不止是憑證:
/api/v1按帳號做速率限制,全部介面共用一個桶,見速率限制。它不做跨來源檢查——伺服器對伺服器的呼叫沒有 Origin 標頭可以檢查,靠的是金鑰本身。/console/v1掛了 CORS 白名單與 CSRF 驗證,因為它的憑證是 Cookie,而 Cookie 會被瀏覽器自動附帶。這一面下有一小組匿名可讀的路徑(公開的模型目錄),只有 GET,沒有任何寫方法。/admin/v1在我們的程式碼執行之前就有一層邊緣身分驗證,之後還有密碼登入、敏感操作的密碼再確認、按角色的授權與完整稽核記錄。登入介面本身也要過這幾層。
健康檢查不在任何一面下
/healthz 與 /readyz 不掛身分驗證,也不掛地區檢查——編排系統的探測請求不經過 CDN,掛上地區判定會讓它永遠探測失敗。這兩個端點不回傳任何業務資料。
金鑰長什麼樣
固定字首 sk-spicy- 加 48 個十六進位字元。
| 部分 | 說明 |
|---|---|
sk-spicy- | 固定字首。讓金鑰在日誌、程式碼儲存庫和 GitHub 的金鑰掃描服務裡能被一眼認出來 |
| 隨後 8 碼 | 查詢碼。我們用它定位到唯一一筆記錄,它本身不參與驗證 |
| 其餘 40 碼 | 真正的秘密。資料庫裡只存加鹽加胡椒的雜湊,我們自己也讀不出原文 |
固定字首是刻意的:被掃描服務掃到並主動通知你,遠好過等著被人拿去盜刷額度。
金鑰只在建立時顯示一次
遺失了只能重建,我們無法找回。這不是功能缺失——能找回就意味著我們存了明文。
絕不要把金鑰放進前端
瀏覽器和 App 裡的一切都能被讀出來
打包、混淆、拆成幾段再拼起來,全都不算保護——任何人開啟開發者工具或反編譯 APK 都能拿到。一把洩露的金鑰可以一直被盜刷到你的餘額或日消費上限見底。
前端要用生成能力時,讓你自己的伺服器端代為轉發:瀏覽器呼叫你的介面,你的伺服器端再帶著金鑰呼叫我們的 API。順帶你還能在那一層做自己的使用者配額和內容稽核。
同理,也不要把金鑰放進:行動 App 的二進位檔、桌面用戶端、公開的 Notebook、CI 的日誌輸出、以及任何會被 curl -v 印到終端機、再被貼進工單的地方。
每把金鑰可以單獨限制
在控制台可以逐把設定,這些限制由伺服器端強制執行:
| 限制 | 作用 | 觸發時的業務碼 |
|---|---|---|
| 日消費上限 | 新建金鑰預設帶一個較低的值。設定寫錯或金鑰洩露時,損失有天花板 | 40202 |
| 月消費上限 | 這把金鑰這個自然月最多能花多少,按 UTC 自然月計算 | 40202 |
| 累計消費上限 | 一把金鑰一生能花的總額。發給外部合作夥伴時特別有用 | 40202 |
| IP 白名單 | 只允許指定 CIDR 呼叫。伺服器端整合建議開啟 | 40302 |
| 可用模型範圍 | 例如測試環境的金鑰只開便宜的模型 | 40301 |
IP 白名單比對的是 CDN 判定的真實用戶端 IP,不是我們看到的直接連線對端——所以照你的出口 IP 設定即可。
輪替與停用
- 按環境分金鑰(正式 / 預備 / 本機)。出事時能精確停用一把而不影響其他。
- 計畫性輪替:先建新金鑰,切換並驗證後停用舊金鑰。這個順序只適用於舊金鑰仍可信的情況。
- 停用即時生效,不需要等任何快取過期。
金鑰洩露了怎麼辦
立刻停用
在控制台停用那把金鑰。停用是即時的。
建新的替換
停用已洩露的金鑰後,再建立替代金鑰並更新伺服器端設定,不要為了準備替代金鑰而繼續保留已洩露的金鑰。停用會阻止新請求,不會取消已經受理的任務。
查有沒有被用過
到控制台的請求日誌裡按時間範圍翻,看有沒有你不認識的呼叫、不認識的模型、不認識的來源 IP。
收緊設定
給新金鑰設定合適的 IP 白名單和日上限,並清除程式碼、日誌或部署設定中造成這次洩露的來源。
發生了非預期消費請聯絡我們,附上任務 ID 或 request_id。
認證失敗長什麼樣
{
"code": 401,
"msg": "Credentials are invalid or expired",
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}HTTP 狀態碼同為 401。
不存在的金鑰、格式不對的金鑰、被停用的金鑰、過期的金鑰,回傳完全相同的回應。 這是防止有人靠回應差異去列舉哪些金鑰是存在的。所以拿到 401 時不要試圖從錯誤訊息判斷具體原因,去控制台看金鑰狀態。
帳號本身不可用(電子郵件未驗證、已停用)時是 403,msg 預設為 This account cannot call the API right now(語言可依錯誤說明的語言切換)——這一類換金鑰沒有用。

