TicketWave Logo
Webhooks

總覽

以簽章的 HTTP 請求,將 TicketWave 事件接收到你自己的應用程式中。

Webhooks

Webhook 是 TicketWave 傳送給你的 HTTP 請求。每當你的伺服器發生某件事——例如工單開啟、成員被列入黑名單——TicketWave 就會把一個 JSON 主體以 POST 方式送到你擁有的 URL。

這和 Log Channels 的差別在於:log channels 會把 embed 寫進 Discord 讓人閱讀,而 webhooks 則是把原始事件直接交給你的程式碼處理。

Webhooks 是 premium 功能。沒有 premium,就無法建立端點,也不會傳送任何事件。

建立端點

開啟端點頁面

伺服器儀表板 → WebhooksEndpoints

新增端點

點擊 Add Endpoint,並填入兩個欄位:

FieldDescription
Endpoint URL接收請求的 https:// URL
Event Types這個端點應接收哪些事件

端點只會接收你勾選的類型。不允許完全不選——至少要選一個。

複製簽章密鑰

TicketWave 會在端點建立的當下產生一組簽章密鑰(whsec_…)。打開端點清單,點擊眼睛圖示顯示它,然後將其複製到你的應用程式設定中。

請把這個密鑰當成密碼看待。任何拿到它的人都能偽造通過你簽章驗證的請求。請把它放在環境變數中,絕不要放進你的儲存庫。

傳送測試事件

使用端點列上的 Send test event 按鈕(紙飛機圖示)。它會送出一個真實、完整簽章的請求,payload 中包含 "test": true,讓你可以在真正的工單依賴它之前先確認接收端運作正常。

結果會像其他傳送一樣,顯示在 Webhooks 歷史紀錄中。

端點需求

RequirementDetail
Scheme僅限 https://http:// 會被拒絕
Host必須可公開解析。私有、loopback、link-local 與 CGNAT 位址都會被拒絕
Response任何 2xx 狀態都視為成功
Timeout你有 10 秒 回應
Redirects不會跟隨。3xx 會視為失敗
Limit每個伺服器最多 5 個端點

主機檢查會在你儲存端點時,以及每一次傳送前都執行一次,所以如果某個網域之後開始解析到內部位址,就會停止傳送到它。

請求內容

每次傳送都是一個帶有 JSON 主體的 POST

標頭

HeaderExampleMeaning
Content-Typeapplication/json一律是 JSON
User-AgentTicketWave-Webhooks/1.0.5傳送它的 bot 版本
X-TicketWave-Eventticket.created事件類型
X-TicketWave-Deliverywh_3f2a…這次傳送的唯一 id
X-TicketWave-Timestamp1786224191Unix 秒數,簽章的一部分
X-TicketWave-Signaturesha256=9f86d0…請求的 HMAC

主體

每個 payload 都使用相同的包裝格式。只有 data 會依事件類型而不同:

{
  "event": "ticket.created",
  "timestamp": "2026-08-26T08:23:11.000Z",
  "guild_id": "123456789012345678",
  "data": {
    "ticket_id": "ticket-1042",
    "ticket_num_id": 1042,
    "channel_id": "998877665544332211",
    "category": "🤖 Support",
    "user": { "id": "987654321098765432", "username": "Luna" },
    "created_at": "2026-08-26T08:23:11.000Z"
  }
}

請參閱 Event Reference 以查看每種類型的 data 物件。

驗證簽章

任何發現你端點 URL 的人都可以向它送出 POST 請求。簽章就是用來分辨真實的 TicketWave 傳送與偽造請求的方法。

一定要驗證。 一個未經驗證、卻會在你的系統中建立或關閉資料的端點,就等於敞開大門。

簽章是如何產生的

TicketWave 會把時間戳記與 原始 請求主體用一個點號串接起來,然後使用你的端點密鑰對結果執行 HMAC-SHA256:

signed_payload = X-TicketWave-Timestamp + "." + raw_request_body
signature      = HMAC_SHA256(signed_payload, your_endpoint_secret)

標頭會帶上這個摘要,並以十六進位編碼與前綴表示:sha256=<digest>

你的接收端必須做什麼

讀取原始主體。 請用你實際收到的精確位元組來驗證。如果你的框架先解析 JSON,然後你再重新序列化,鍵的順序或空白可能會改變,摘要就會不一致。

使用你的密鑰,對 timestamp + "." + rawBody 重新計算 HMAC

固定時間比較(Node 中可用 crypto.timingSafeEqual)。單純的 === 會洩漏時間資訊。

檢查時間戳記是否夠新——預設容許五分鐘是個不錯的做法。時間戳記包含在簽章的 payload 中,因此攻擊者無法用新的時間戳記重放舊請求。

完整實作可見 Example Server 頁面。

重試

失敗的傳送會自動重試。

Attempts3(第一次嘗試加上 2 次重試)
Backoff1 秒,接著 5 秒
Retried on網路錯誤、逾時、408429 以及任何 5xx
Not retried on其他所有 4xx——這表示你的端點是刻意拒絕該請求

由於重試,你的端點可能會收到同一個事件兩次。請把 X-TicketWave-Delivery 當作冪等鍵:記住你已處理過的 id,並忽略重複項目。

傳送不保證順序。如果兩張工單同時建立,請求可能會以任一順序到達——如果順序對你很重要,請使用主體中的 timestamp 欄位。

傳送歷史

儀表板的 Webhooks 頁面會列出每一次傳送,以及它的狀態、回應碼、耗時與嘗試次數。打開某一列即可查看實際送出的請求 payload,以及你的伺服器回傳的回應。

失敗的傳送可以在詳細頁面中使用 Retry Webhook 重新送出。它會把原始 payload 再次送到同一個端點,並記錄一筆新的傳送。

歷史紀錄會保留 30 天,之後會自動清理。

疑難排解

ProblemFix
無法儲存端點URL 必須是 https://,且解析到公開位址
所有項目都顯示失敗,且沒有回應碼請求根本沒有到你這裡——可能是逾時、DNS 失敗或連線被拒絕
簽章永遠不相符你是在對解析後的主體做雜湊,而不是原始位元組,或是忘了 timestamp + "." 前綴
傳送過一陣子後就停止檢查你的主機是否開始回傳 4xx——這些不會被重試
某個事件一直沒收到端點沒有訂閱該類型,或伺服器失去 premium
重複事件重試時屬於預期行為——請根據 X-TicketWave-Delivery 去重

下一步

How is this guide?