Slack 如何傳遞 Webhook

Slack 要求 3 秒內回 2xx,重試 3 次,一小時內有超過 95% 的嘗試失敗就停用 Event Subscriptions。附簽章格式與 Node 驗證程式。

傳遞行為

取自服務商自己的文件,最後檢查於 2026-08-06。服務商沒寫數字的地方,這張表也不填。

回應時限3 秒

檢查你的處理程式能否及時回應

重試重試 3 次:立即、1 分鐘後、5 分鐘後
放棄60 分鐘內有超過 95% 的嘗試失敗時,停用 Event Subscriptions
出處https://docs.slack.dev/apis/events-api/

簽章

用一個經測試套件證明可運作的驗證程式核對過,不是照文件抄來的。最後驗證於 2026-08-20。

演算法HMAC-SHA256
簽章內容v0:{timestamp}:{body}
編碼hex
標頭x-slack-signature = v0=hex
容許時間差5 分鐘

驗證簽章

要用原始請求主體(raw body),逐位元組原封不動,並在任何 JSON 解析之前取得。框架只要重新序列化 payload,這頁上的每一種機制就會立刻失效。

const crypto = require("node:crypto");

const ts = req.headers["x-slack-request-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) throw new Error("stale");

const expected =
  "v0=" +
  crypto
    .createHmac("sha256", signingSecret) // Slack App → Basic Information
    .update(`v0:${ts}:${rawBody}`)
    .digest("hex");
const received = Buffer.from(req.headers["x-slack-signature"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);

容易踩的坑

三秒是主要發送端裡最緊的時限,而三次重試都落在五分鐘內。處理程式只要是變慢而不是當機,四次嘗試就會在同一場事故裡全部失敗。

停用規則看的是比率,不是次數:60 分鐘內超過 95% 的嘗試失敗,整個應用程式的 Event Subscriptions 就會被關掉,使用者會看著機器人在頻道裡突然沒了回應。

延伸閱讀

AnyHook 架在接收 Slack Webhook 的端點前面:大約 1 秒就回應,伺服器當機時依自己的排程重試,並讓每個事件都能重播。 換一個網址,程式碼不用動;要接受重試與重播,改為檢查 AnyHook-Signature,因為 Slack 自己的簽章在 5 分鐘後就會過期。

運作方式 →