當網站發生特定事件時,Kanorio 可即時通知您的系統:買家付款、包裹出貨或送達、訪客提交表單、寄件網域失效、寄送額度用盡、流量突破里程碑等。透過連接 Zapier、Make、n8n 或您自建的程式,即可自動將資料寫入試算表、轉發至團隊聊天群組、建立客服工單,或同步至您的 ERP 與 CRM 系統。
您可在網站主控台的技術設定中的「串接」分頁進行設定。Webhook 為商務版功能,僅限網站擁有者與管理員新增或管理;其他成員無法查看網址、金鑰及推送紀錄。
每個網站最多可新增 5 個 Webhook。
展開每個端點後,皆可設定「訂閱事件」:
目前支援的事件如下(欄位細節請見文末「事件參考」):
| 事件 | 發送時機 | 事件代碼 |
|---|---|---|
| 訂單付款 | 買家完成付款時 | ec.order.paid |
| 貨態更新 | 包裹出貨、到店、送達或配送異常時 | ec.shipment.statusChanged |
| 表單回覆 | 訪客提交表單時,包含完整題目與答案 | customers.form.submitted |
| 寄件網域失效 | 寄件網域驗證失敗時 | customers.sendingDomain.degraded |
| 寄送額度提醒 | 額度用盡、自動加購、加購達上限或扣款失敗時 | customers.messagingQuota.alert |
Webhook 的發送與否僅取決於此處的訂閱設定。各情境面板雖會顯示「N 個端點已訂閱」或「尚未連接」,但開關控制權在於此處。
Webhook 不會取代寄給您的 Email。啟用 Webhook 後,原本寄給擁有者的通知信(如新訂單與表單回覆)仍會正常發送;貨態更新的團隊 Email 預設為關閉。若需調整團隊 Email,請至「自動通知」設定。
展開每個端點即可查看「最近推送」紀錄:包含事件、結果、HTTP 狀態與時間;展開單筆紀錄可查看嘗試次數、耗時、下次重試時間與錯誤原因。7 天內的通知可「查看內容」以檢視發送資料,亦可點擊「重送」再次發送;重送將使用相同的通知編號,接收端可據此判斷是否重複。
「傳送測試」不會計入失敗次數,排查問題時可放心多次測試。
Kanorio 會從固定的 IP 發送 Webhook。若您的接收端僅允許白名單來源,請將以下三個 IPv4 全部加入(首次發送、測試與手動重送來自前兩個,自動重試來自第三個):
| 用途 | IP |
|---|---|
| 首次發送、測試、手動重送 | <MAIN_EGRESS_IP_1> |
| 首次發送、測試、手動重送 | <MAIN_EGRESS_IP_2> |
| 自動重試 | 168.144.105.51 |
白名單僅為額外防護,無法取代簽章驗證:請務必驗證 X-Kanorio-Signature(詳見下方「給工程師」)。若 IP 需變更,我們會先在此公告,並保留新舊 IP 並行一段時間後再移除舊 IP。
不會。Webhook 不經由 Kanorio 寄信,因此不計入 Email 寄送額度。
端點將暫停推送,設定與金鑰將保留,列表上會標示「超出方案」。升級回商務版後即可立即恢復。
當接收端回應過慢或出錯時,Kanorio 會進行重試;您亦可能手動重送。請使用 X-Kanorio-Delivery(或 JSON 中的 id)來判斷是否已處理過該通知。
目前可先透過 Zapier 或 Make 轉發:利用 Webhook 接收 Kanorio 的通知,再轉發至 Slack 頻道或 LINE。
Webhook 會將訂單與表單答案發送至 Kanorio 以外的系統,因此網址與簽章金鑰僅擁有者與管理員可見。其他成員僅能查看端點名稱與狀態。
沒有獨立的沙盒環境。請使用「傳送測試」確認連線,並透過「查看內容」檢視真實事件發送的資料;開發階段可先將端點指向 webhook.site 這類接收服務來觀察格式。
每則通知皆為 POST 請求,Content-Type: application/json,並附帶以下 header:
| Header | 內容 |
|---|---|
X-Kanorio-Event |
| 流量里程碑 |
| 網站累計瀏覽量突破 100、500 時 |
site.analytics.milestone |
| 串接暫停 | Webhook 因連續失敗被暫停時(不會發送至該端點) | customers.teamDestination.disabled |
| 測試事件 | 點擊「傳送測試」時 | team.test |
事件代碼,與 JSON 中的 event 相同 |
X-Kanorio-Delivery | 通知編號,與 JSON 中的 id 相同;重試與重送時不變 |
X-Kanorio-Signature | 簽章,格式為 t=時間戳,v1=簽章;金鑰輪替期間會有兩個 v1 |
User-Agent | Kanorio-Notifications/1.0 |
接收端回應任何 2xx 即視為成功,回應內容不會被讀取。請在 8 秒內回應;若需較長處理時間,請先回傳 200 再進行非同步處理。Kanorio 不會跟隨重導,3xx 將視為失敗。
所有事件的 JSON 結構相同,接收端僅需設定一次:
{ "version": "1", "id": "3f9c2a…", "event": "ec.order.paid", "occurredAt": "2026-09-29T12:00:00.000Z", "websiteId": "cmk…", "title": "新訂單 #1024,NT$1,280", "summary": "「我的商店」收到一筆已付款的訂單。", "fields": [{ "label": "訂單編號", "value": "#1024" }], "data": { "…": "依事件而異,見下方事件參考" }, "actionUrl": "https://app.kanorio.com/store/transactions?tx=…" }
| 欄位 | 型別 | 說明 |
|---|---|---|
version | string | 目前為 "1"。僅新增欄位不會變更版本號;移除或修改既有欄位才會升版,並於此處公告 |
id | string | 通知編號(32 碼),與 X-Kanorio-Delivery 相同。重試與重送時不變,請用此欄位進行去重 |
event | string | 事件代碼,詳見上方事件表 |
occurredAt | string | 事件發生時間,ISO 8601(UTC) |
websiteId | string | 網站 ID。同一個端點僅會收到建立該端點之網站的事件 |
title、summary | string | 依網站語系排版的一行標題與摘要,可直接轉發至聊天群組 |
fields | array | { label, value } 陣列,供人類閱讀的細節(訂單編號、金額、表單題目與答案等)。標籤文字隨網站語系變更,程式判斷請使用 data |
data | object | 事件原始資料,不隨語系改變。各事件欄位詳見下方 |
actionUrl | string | null | 回到 Kanorio 後台查看該筆資料的連結 |
以下為各事件的 data 欄位。「可空」表示該欄位可能為 null。
ec.order.paid 訂單付款買家完成付款、訂單成立時發送;每筆訂單發送一次。
| 欄位 | 型別 | 可空 | 說明 |
|---|---|---|---|
orderId | string | 訂單 ID,與後台網址 ?tx= 相同 | |
orderNumber | number | ✓ | 人類可讀的訂單編號(例如 1024);極早期訂單可能無此欄位 |
amount | number | 買家支付總額(商品+運費),以該幣別的最小單位計算(ISO 4217 minor unit):NT$1,280 為 128000、US$12.80 為 1280、日圓無小數則 ¥1,280 為 1280。換算顯示金額請除以 10 的「小數位數」次方 | |
currency | string | ISO 4217 大寫,例如 TWD、USD | |
itemCount | number | 品項數量 | |
customerName | string | ✓ | 買家姓名 |
customerEmail | string | ✓ | 買家 Email |
ec.shipment.statusChanged 貨態更新出貨單進入出貨、到店、送達或配送異常時發送;同一張出貨單的每個貨態各發送一次。
| 欄位 | 型別 | 可空 | 說明 |
|---|---|---|---|
orderId | string | 訂單 ID | |
orderNumber | number | ✓ | 訂單編號 |
shipmentId | string | 出貨單 ID;一筆訂單可能有多張出貨單 | |
status | string | IN_TRANSIT(已出貨)、AT_STORE(已到店)、DELIVERED(已送達)、EXCEPTION(配送異常) | |
carrier | string | 物流服務代碼,例如 PAYUNI_LOGISTICS、MANUAL(賣家自寄) | |
trackingNumber | string | ✓ | 追蹤號碼/託運單號 |
storeName | string | ✓ | 超商取貨的門市名稱;宅配為 null |
customers.form.submitted 表單回覆訪客提交表單且通過垃圾判定時發送;每筆回覆發送一次。
| 欄位 | 型別 | 可空 | 說明 |
|---|---|---|---|
formId | string | 表單 ID | |
formName | string | 表單名稱 | |
submissionId | string | 回覆 ID | |
submitter | object | { name, email, phone },各欄位可為 null;由表單內的姓名、Email、電話題目自動辨識 | |
answers | array | 依題目順序,每題一個物件(見下表) |
answers[] 的每一項:
| 欄位 | 型別 | 說明 |
|---|---|---|
fieldId | string | 題目 ID,同一張表單內固定;請使用此欄位而非 label 對應欄位 |
type | string | 題型:short_text、long_text、email、phone、name、choice、date、time、rating、file |
label | string | 題目文字 |
value | string | string[] | number | null | 原始答案。單選為字串、多選為字串陣列、評分為數字、日期時間為字串(YYYY-MM-DD、HH:mm)、檔案題為檔案 ID(一個或多個);未填寫為 null |
display | string | 人類可讀字串,與 fields 相同;檔案題顯示檔名 |
customers.sendingDomain.degraded 寄件網域失效已驗證的自有寄件網域驗證失效時發送;同一個網域每天最多發送一次。
| 欄位 | 型別 | 說明 |
|---|---|---|
domain | string | 失效的寄件網域 |
customers.messagingQuota.alert 寄送額度提醒寄送額度狀態變更時發送。
| 欄位 | 型別 | 說明 |
|---|---|---|
reason | string | exhausted(本期額度用盡)、auto_upgraded(已自動加購一級)、auto_upgrade_limit(本期自動加購達上限)、payment_failed(加購費用扣款失敗) |
quota | number | 本期額度(封) |
levels | number | 目前的加購級數 |
periodStart | string | 本期起算時間,ISO 8601 |
site.analytics.milestone 流量里程碑網站累計瀏覽量突破里程碑時發送,每個里程碑發送一次。
| 欄位 | 型別 | 說明 |
|---|---|---|
milestone | number | 100 或 500 |
customers.teamDestination.disabled 串接暫停某個 Webhook 端點被自動暫停時發送(連續失敗達門檻或接收端回傳 410)。僅會發送至其他正常的端點。
| 欄位 | 型別 | 說明 |
|---|---|---|
destinationId | string | 被暫停的端點 ID |
failures | number | 連續失敗次數 |
lastError | string | 最後一次錯誤,例如 HTTP 503、逾時 |
team.test 測試事件點擊「傳送測試」時發送,僅發送一次、不重試、不寫入推送紀錄。
驗證方式:
X-Kanorio-Signature 取出 t 與所有 v1。t、一個英文句點與原始請求內容(未經解析、重新序列化的 raw body)串接,例如 1790000000.{"version":"1",…}。v1 比對,相符才接受。Node.js 範例:
import { createHmac, timingSafeEqual } from "node:crypto"; function verify(rawBody, header, secret) { const parts = header.split(",").map((part) => part.split("=")); const t = parts.find(([key]) => key === "t")?.[1]; const signatures = parts.filter(([key]) => key === "v1").map(([, value]) => value); if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); return signatures.some( (v1) => v1.length === expected.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1)) ); }
Zapier、Make、n8n 等服務通常無處編寫驗證邏輯;其接收網址本身包含隨機路徑,通常不需額外驗證簽章。
簽章金鑰可在串接列表展開該端點後,點擊「顯示」查看。若懷疑金鑰外流,請點擊「產生新金鑰」:
v1),任一相符即可。