指南
Webhooks
webhook 端點接收工作區的警報規則路由給它的內容:被阻擋的發布、等待人來處理的結果、已結束的託管執行、生產監控的警報。每次投遞都是以端點密鑰簽章的 JSON 本文,因此您的伺服器在處理之前可以確認它來自您的工作區。
新增端點
在工作區的 Integrations 頁面上,Owner 或 Admin 以一個名稱和連接埠 443 或 8443 上的公開 https URL 新增簽章 webhook。接著頁面會顯示端點的簽章密鑰,它以 whsec_ 開頭。請當下就複製:它會加密儲存,不會再次顯示。要更換它,請刪除端點後重新新增。
然後,在 Alerts 頁面上,將該端點選為一條或多條規則的管道。「Send a test」會寄送一次 oloproof.test 投遞,並顯示您的伺服器回應的狀態。
傳送的內容
{
"type": "oloproof.gate_blocked",
"id": "dlv_8c1f0a2b3c4d5e6f7a8b9c0d",
"created_at": "2026-10-26T14:03:00.000Z",
"workspace": "acme",
"rule": { "id": "rul_1a2b3c4d5e6f7a8b9c0d1e2f", "name": "Do not ship" },
"event": "gate_blocked",
"items": [
{
"project": "support",
"kind": "run",
"id": "run_20261026T140100_4f2a",
"release_action": "BLOCK",
"rules": [["faithfulness", "FAIL"]],
"href": "https://oloproof.com/app/workspaces/acme/projects/support/runs/run_20261026T140100_4f2a"
}
],
"more": 0
}一個項目包含 id、引擎的判定狀態、發布動作、作業的狀態與結果、依引擎寫下的監控水準、閾值與區間,以及連結。它從不包含案例的輸入、輸出、預期答案或標籤。一次投遞最多包含 50 個項目;more 計算超出部分的事件數。
驗證投遞
每次投遞都帶有三個 Standard Webhooks 格式的標頭:
- webhook-id:投遞的 id,每次重試都相同。
- webhook-timestamp:本次嘗試寄送的時間,以自 1970 年起的秒數表示。
- webhook-signature:v1, 加上 id.timestamp.body 的 base64 HMAC-SHA256,以密鑰的位元組(whsec_ 之後的部分,經 base64 解碼)為金鑰。
請對收到的原始本文計算簽章,以常數時間比較,並拒絕與您的時鐘相差超過五分鐘的時間戳記。
import base64, hashlib, hmac, time
def verify(secret: str, headers: dict, body: bytes) -> bool:
key = base64.b64decode(secret.removeprefix("whsec_"))
msg = f"{headers['webhook-id']}.{headers['webhook-timestamp']}.".encode() + body
expected = base64.b64encode(hmac.new(key, msg, hashlib.sha256).digest()).decode()
fresh = abs(time.time() - int(headers["webhook-timestamp"])) <= 300
given = [part.split(",", 1)[-1] for part in headers["webhook-signature"].split()]
return fresh and any(hmac.compare_digest(expected, sig) for sig in given)import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, headers, body) {
const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
const id = headers["webhook-id"], ts = headers["webhook-timestamp"];
const expected = createHmac("sha256", key).update(`${id}.${ts}.${body}`).digest("base64");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
return fresh && headers["webhook-signature"].split(" ").some((part) => {
const sig = Buffer.from(part.split(",").pop());
return sig.length === expected.length && timingSafeEqual(sig, Buffer.from(expected));
});
}Standard Webhooks 的函式庫驗證的是同樣的標頭。
投遞
請在十秒內以任一 2xx 狀態回應。其他任何回應(包括重新導向)都算失敗的嘗試,會在 1、5、30、120 與 360 分鐘後重試,之後放棄。由於回應可能在您的伺服器處理之後遺失,同一次投遞可能送達兩次:請用 webhook-id 捨棄重複。一條規則對每個事件最多觸發一次,所以新的 id 就是新的投遞。
每次嘗試之前都會重新解析端點的名稱,請求只會送往公開位址:迴路、私有、鏈路本機、共用、保留與雲端中繼資料位址都會被拒絕,帶有其中之一的 IPv6 形式也一樣。連線建立在經過檢查的位址上,憑證則依名稱進行檢查。
Slack
Slack 端點是一個傳入 webhook URL。它接收一則簡短的英文訊息,每個事件一行,並附上每個結果的連結。Slack 不檢查簽章標頭,但標頭照樣會寄送。