Webhook
環境中一有事情發生,Usher 就能立即通知你的伺服器:有人加入、登入、更改資料或離開。每個事件都是一個傳送到你所選地址的已簽署 POST 請求;如果你的伺服器沒有回應,就會再試一次。
加入端點
在 Usher Console 中打開環境,然後選擇 Webhook → 新增端點。提供一個你的 https:// 地址,並選擇它要接收的事件。Console 只會顯示一次端點的簽署機密(whsec_…):請將它與伺服器的其他機密存放在一起。
| 事件 | 時機 |
|---|---|
user.created | 有人建立了帳户 |
user.updated | 帳户有所變更:電郵、姓名、驗證狀態或停權(包括你組織的目錄透過 SCIM 執行的停權) |
user.deleted | 帳户已刪除 |
session.created | 有人登入 |
session.ended | 工作階段結束:已登出、遭撤銷或提前到期 |
傳送測試會將一個 webhook.test 事件只傳送到該端點,不論它訂閱了哪些事件。
收到的內容
請求
POST /usher/webhooks HTTP/1.1
content-type: application/json
user-agent: Usher-Webhooks/1
webhook-id: msg_2fk7x…
webhook-timestamp: 1793643116
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=內文
{
"type": "user.created",
"timestamp": "2026-11-02T18:11:56.412Z",
"data": {
"user": {
"id": "Qz3m…",
"email": "lena@acme.com",
"emailVerified": false,
"name": "Lena Live",
"image": null,
"banned": false,
"createdAt": "2026-11-02T18:11:56.380Z",
"updatedAt": "2026-11-02T18:11:56.380Z"
}
}
}事件描述的是用户和工作階段,絕不包含機密:沒有權杖、沒有密碼雜湊、沒有角色,也不會說明某人為什麼遭到停權。
檢查每一次傳遞
Usher 按照 Standard Webhooks 規格簽署,因此它的任何程式庫都能替你檢查簽名。請拒絕任何無法通過驗證的內容。這些程式庫也會拒絕時間戳記相差超過五分鐘的請求,因此舊的傳遞內容無法被重送。
app/usher/webhooks/route.ts
// a route that receives Usher's webhooks (Node, the standardwebhooks package)
import { Webhook } from 'standardwebhooks'
const wh = new Webhook(process.env.USHER_WEBHOOK_SECRET!) // whsec_…, from Usher Console
export async function POST(request: Request) {
const body = await request.text() // the raw body: the signature covers it byte for byte
let event: { type: string; timestamp: string; data: Record<string, unknown> }
try {
event = wh.verify(body, Object.fromEntries(request.headers)) as typeof event
} catch {
return new Response('bad signature', { status: 400 })
}
// webhook-id is the same on every attempt: skip one you have handled already
if (await alreadyHandled(request.headers.get('webhook-id')!)) return new Response(null, { status: 204 })
await queue(event) // answer quickly; do the work afterwards
return new Response(null, { status: 204 })
}- 在 15 秒內回應,回傳任何
2xx狀態碼。其他任何回應(包括重新導向)都會視為失敗。 - 預期會重複:一則訊息在每次嘗試中都保有相同的
webhook-id;已經處理過的就略過。 - 不要依賴順序:重試可能在較新的事件之後才送達。
當你的伺服器沒有回應
Usher 會按順序在 5 秒、5 分鐘、30 分鐘、2 小時、5 小時、10 小時和 10 小時後再試(總共大約一天半),之後便會放棄。Console 的傳遞記錄會顯示每則訊息的每次嘗試,以及你伺服器的最後一次回應,而重新傳送會從頭開始一次傳遞。
新的機密
在 Console 中按下 新機密,會產生另一個機密並只顯示一次。在接下來的 24 小時內,每次傳遞都會帶有兩個簽名,每個機密各一個,讓你可以部署新機密而不漏掉任何內容。之後就只有新機密會簽署。
傳遞的來源
Webhook 會經由 Usher 的對外連線代理送出,而該代理不會連線到私人或內部地址。端點必須是公開名稱上的 https:// 地址:不能是 IP 地址、私人名稱,或 Usher 自己網域上的地址。