跳至內容
0%

什麼是 webhook?

發布於 2026年10月29日閱讀時間 3 分鐘

什麼是 webhook?

webhook 是以 HTTP POST 傳遞的事件通知。當某個系統中發生事件時,該系統會向你控制的 URL 發送請求,請求主體則描述發生了什麼事。你的應用程式完全不需要主動詢問是否有任何變化。

在區塊鏈應用程式中,事件發生在鏈上。使用者的錢包收到 USDC、某個 NFT 易主,或是你部署的合約發出一筆日誌。若沒有 webhook,你的後端就得定時輪詢節點或 API,並比對結果才能發現這些變化。有了 webhook,變化一經偵測就會傳送到你的伺服器。

本指南將說明 webhook URL、端點與 payload 分別是什麼、webhook 與 API 有何不同、傳遞與重試如何運作、如何驗證請求,以及如何在正式環境中處理重複事件與 reorg。

什麼是 webhook?

webhook 連接兩方。發送方負責監看事件。接收方是你的應用程式,它會公開一個 URL。當某個事件符合你訂閱的條件時,發送方會向該 URL 發出 HTTP POST 請求,並附上描述該事件的 JSON 主體,你的伺服器則回應 200 狀態碼,確認已收到。你這一端不會回傳任何資料,因此 webhook 是一種單向、伺服器對伺服器的訊息。

另一種做法是輪詢,也就是按固定排程向資料來源詢問是否有更新。這些請求大多不會帶回任何新資料,而且一個事件最多可能要等上一整個輪詢間隔,才會被你的應用程式看到。webhook 能同時避開這兩個問題,因為只有在有事件需要回報時才會發出請求。

輪詢就像每小時打一次電話給店家,詢問你的訂單到貨了沒。webhook 則是店家在貨到時傳簡訊通知你。

什麼是 webhook URL?

webhook URL 是發送方傳遞事件的公開位址,例如 https://api.example.com/webhooks/alchemy。你在建立 webhook 時,會向提供者註冊這個 URL。請求是由提供者的伺服器發出的,因此這個 URL 必須能從網際網路連線,而且由於 payload 描述的是你的使用者的活動,應該使用 HTTPS。開發期間,可以使用 ngrok 這類通道工具,讓你筆電上的伺服器取得一個暫時的公開 URL。我們的 webhook 快速入門會逐步說明這項設定。

什麼是 webhook 端點?

webhook 端點是你伺服器上的一個路由,負責處理傳送到 webhook URL 的請求。這兩個詞經常被交替使用。URL 是位址,端點則是位址背後的程式碼。

端點的工作應盡量精簡。它會確認請求來自提供者、儲存事件,然後回傳 200。較耗時的工作,例如更新餘額或發送推播通知,應交給背景工作程序處理。如果這些工作在請求中執行,一次緩慢的資料庫呼叫就可能讓提供者誤以為傳遞失敗。

什麼是 webhook payload?

payload 是請求的 JSON 主體。我們所有的 webhook 都使用相同的外層結構,event 欄位則存放該 webhook 類型的資料。以下是 Address Activity webhook(監看一組錢包地址的類型)針對 Ethereum 上一筆 USDC 轉帳所送出的 payload。為節省篇幅,部分欄位已省略。

json
Copied
{ "webhookId": "wh_k63lg72rxda78gce", "id": "whevt_vq499kv7elmlbp2v", "createdAt": "2024-01-23T07:42:26.411977228Z", "type": "ADDRESS_ACTIVITY", "event": { "network": "ETH_MAINNET", "activity": [ { "blockNum": "0xdf34a3", "hash": "0x7a4a39da2a3fa1fc2ef88fd1eaea070286ed2aba21e0419dcfb6d5c5d9f02a72", "fromAddress": "0x503828976d22510aad0201ac7ec88293211d23da", "toAddress": "0xbe3f4b43db5eb49d1f48f53443b9abce45da3b79", "value": 293.092129, "asset": "USDC", "category": "token", "rawContract": { "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "decimals": 6 }, "log": { "logIndex": "0x6e", "removed": false } } ] } }

webhookId 告訴你是哪個 webhook 觸發,id 用來識別這個事件,type 則標示 webhook 類型。activity 中的每一筆項目,都是一筆涉及受監看地址的轉帳。要辨識代幣,請使用 rawContract.address,也就是代幣的合約地址。asset 中的符號來自代幣合約本身,而任何人都可以部署一個自稱 USDC 的代幣。

webhook 與 API 有何不同?

API 會等你呼叫它。你的應用程式發送請求,然後取回資料。webhook 則把方向反過來,由提供者在有事情要回報時主動呼叫你的應用程式。正因為方向相反,webhook 有時也被稱為「反向 API」。

API 請求
輪詢
Webhook
由誰發起
你的應用程式
你的應用程式,定時發起
提供者
資料何時傳送
你發出請求時
每個間隔都會傳送,即使沒有任何變化
僅在事件發生時
典型用途
依需求讀取目前狀態
可接受些許延遲的簡單檢查
在你的伺服器上回應事件

大多數正式環境中的應用程式兩者都會使用。webhook 告訴你發生了某件事,API 呼叫則補足其餘細節。例如,支付後端可能先收到一個入金 webhook,再呼叫 Token API 讀取錢包目前的餘額,然後才顯示給使用者。

當接收端是伺服器端點時,適合使用 webhook。如果接收端是長時間執行的程序,例如交易機器人或即時儀表板,則可改用 WebSocket 訂閱,維持一條開啟的連線,並透過它串流傳送事件。我們的 webhook、WebSocket 與 gRPC 比較說明了如何在三者之間做選擇。

webhook 如何運作?

每次 webhook 傳遞都會經過相同的階段:

  • 你建立訂閱。你建立一個 webhook,設定目標 URL 與篩選條件,指定要監看哪個網路,以及要在該網路上監看什麼,例如一組地址或某個合約的事件。
  • 事件符合條件。新區塊中出現符合你篩選條件的活動。
  • 提供者發送 POST。請求中帶有 payload,以及一個可供你的伺服器驗證的簽章標頭。
  • 你的伺服器確認收到。回應 200 即代表事件已送達。
  • 失敗的傳遞會重試。如果你的伺服器停機、逾時,或回傳任何其他狀態碼,提供者會稍後再試。

在 Alchemy 上,重試採用指數退避,也就是每次失敗後,兩次嘗試之間的等待時間會逐漸拉長。在 Free 與 Pay As You Go 方案中,我們會持續重試最多 10 分鐘;在 Enterprise 方案中則最多一小時,詳見我們的 webhook 快速入門中關於傳遞行為的說明。

無論鏈的出塊速度多快,首次通知在每條鏈上都會依序送達。這項保證僅適用於首次嘗試,因此重試的事件可能比較新的事件更晚抵達。請為每個事件一併儲存區塊編號,並依區塊編號而非抵達時間排序你的紀錄。

如果你的伺服器停機時間超過重試期間,該期間內的事件不會重新傳遞,因此請從鏈上歷史資料補齊缺口。在 Ethereum 與 Transfers API 支援的 L2 上,請用它查詢你遺漏的地址與區塊範圍。在 Stellar 上,Stellar 轉帳端點會回傳某個帳戶依 ledger 範圍篩選的轉帳。在 Solana 上,請使用 getSignaturesForAddress 逐頁往回查詢每個受監看地址的交易。

webhook 在區塊鏈應用程式中有哪些用途?

我們提供四種 webhook 類型,該選哪一種取決於你需要監看什麼。

Webhook 類型
追蹤內容
網路
Address Activity
最多 100,000 個地址轉入或轉出的原生代幣、ERC-20、ERC-721 與 ERC-1155 轉帳
30 多條 EVM 鏈與 Solana
NFT Activity
單一 NFT、整個系列,或某條鏈上所有 NFT 的轉移
Ethereum、Arbitrum、Optimism 與 Polygon
Custom
你透過 GraphQL 查詢選取的任何區塊、交易或日誌資料
每個 webhook 一個網路
Stellar Address Activity
最多 100,000 個帳戶的 XLM 與 Stellar 資產轉帳、DEX 成交,以及 Soroban 合約事件
Stellar

Address Activity webhook 負責最常見的工作,也就是監看一組錢包。支付後端會監看自己的入金地址,並在 USDC 到帳時為使用者入帳。錢包應用程式則會在使用者收到代幣時發送推播通知。ERC-20 轉帳會包含代幣的合約地址,支付後端正是藉此確認入金確實是真正的 USDC。

NFT Activity webhook 針對 NFT 合約提供同樣的功能,適合 NFT 市集與系列儀表板。Custom webhook 則處理其他所有情況。你撰寫一個 GraphQL 查詢來選取所需的區塊資料,例如你自己的合約中帶有特定事件簽章的日誌,webhook 就會針對每個新區塊觸發,且只帶有這些資料。Stellar Address Activity webhook 則將地址追蹤帶到 Stellar,包括 Soroban 合約事件。

每個 webhook 只監看一個網路。若要涵蓋多條鏈,請為每個網路各建立一個 webhook,並讓它們全部指向同一個 URL。webhook 也很適合鏈上 AI 代理,讓代理在受監看的錢包轉移資金時被喚醒,而不必在迴圈中不斷輪詢。

如何驗證 webhook 簽章?

任何人只要找到你的 webhook URL,就能向它發送請求,因此你的端點在採取任何行動之前,必須先確認每個請求都來自提供者。我們會以 HMAC-SHA256 為每個 webhook 請求簽章,這是一種帶金鑰的雜湊,只有持有密鑰的人才能重現。金鑰是你的 webhook 的簽署金鑰,輸入是請求主體,產生的十六進位結果則放在 X-Alchemy-Signature 標頭中。你的伺服器會對收到的主體計算相同的雜湊,並比對兩個值。

每個 webhook 都有各自的簽署金鑰,顯示在 Alchemy 儀表板中該 webhook 的頁面上。這項檢查能否真正保護你,取決於三個細節:

  • 對原始位元組計算雜湊。簽章涵蓋的是傳送時原封不動的主體。如果你的框架先解析了 JSON,而你的程式碼又將它重新序列化,空白與鍵的順序可能會改變,雜湊值就會對不上。
  • 以常數時間比對。在 Node 中使用 crypto.timingSafeEqual,在 Python 中使用 hmac.compare_digest,而不是 === 或 ==,這樣回應時間就不會洩露偽造簽章中有多少部分是正確的。
  • 在做任何其他處理之前先拒絕。回傳 401 並停止處理。不要解析或儲存尚未驗證的 payload。

以下是一個符合上述三點的最精簡 Express 端點:

typescript
Copied
import express from "express"; import { createHmac, timingSafeEqual } from "node:crypto"; // enqueue is your own durable queue (a database table, SQS, BullMQ). // It should resolve only after the event is safely stored. import { enqueue } from "./queue"; const signingKey = process.env.ALCHEMY_WEBHOOK_SIGNING_KEY ?? ""; if (!signingKey) throw new Error("Set ALCHEMY_WEBHOOK_SIGNING_KEY"); function isValidSignature(rawBody: Buffer, signature: string | undefined): boolean { if (!signature) return false; const expected = createHmac("sha256", signingKey).update(rawBody).digest(); const received = Buffer.from(signature, "hex"); return received.length === expected.length && timingSafeEqual(received, expected); } const app = express(); // express.raw() keeps the exact bytes Alchemy signed, so don't parse JSON on this route first. app.post("/webhooks/alchemy", express.raw({ type: "*/*" }), async (req, res) => { if (!isValidSignature(req.body, req.get("x-alchemy-signature"))) { res.sendStatus(401); return; } await enqueue(JSON.parse(req.body.toString("utf8"))); res.sendStatus(200); }); app.listen(8080);

作為第二層防護,你可以設定防火牆,只允許我們的 webhook IP 位址通過。webhook 快速入門的安全性章節列出了這些位址。

你的應用程式該如何處理重複、延遲或受 reorg 影響的 webhook?

請將 webhook 傳遞視為「至少一次」。逾時後的重試可能會送來你的伺服器已經儲存過的事件,因此處理常式必須具備冪等性。處理同一個事件兩次,效果應該與只處理一次相同。

  • 以轉帳而非請求為單位去重。一個 payload 可能帶有多筆轉帳,一筆交易也可能包含多筆轉帳。請用網路、交易 hash,以及該轉帳在交易中的位置組成一個鍵,代幣轉帳的位置是 log.logIndex,內部轉帳則是 typeTraceAddress。外部轉帳只需要交易雜湊,因為一筆交易只會有一筆外部轉帳。將這個鍵存入設有唯一性約束的資料表,並且只有在某次傳遞的鍵與其 log.removed 值都與已儲存的紀錄相符時,才跳過該次傳遞。
  • 先儲存,再確認收到。在事件已持久儲存後才回傳 200,實際的工作則交給背景工作程序處理。如果處理常式在回應前就執行這些工作,就有逾時的風險,而逾時會觸發重試,送來一個你可能已經處理過的事件。
  • 撤銷受 reorg 影響的轉帳。鏈重組,也就是 reorg,會取代最近的區塊,被取代區塊中的交易會從鏈上消失。代幣轉帳帶有 log.removed 欄位,值為 true 表示該交易已不在規範鏈上。log.removed 設為 true 的傳遞會帶有與原始轉帳相同的鍵,因此請將它視為對已儲存紀錄的更新。請將該紀錄標記為已移除,並撤銷你的應用程式針對該轉帳所做的一切處理。
  • 執行不可逆操作前先等待最終性。立即顯示一筆待確認的入金是合理的。但釋出資金、出貨,或將款項計入可提領餘額,都應等到區塊最終確定後再進行。在 Ethereum 上,finalized 區塊標籤會告訴你哪些區塊已達到這個階段。

如何在 Alchemy 上設定 webhook?

先從監聽器著手。我們的 webhook 快速入門提供以 JavaScript、Python、Go 與 Rust 撰寫、內建簽章驗證的入門伺服器,而 webhook 範例儲存庫則有可在本機執行的完整專案。

接著建立 webhook。webhook 儀表板是最快的途徑。選擇類型與網路、加入地址或篩選條件、貼上你的 URL,再使用 Test Webhook 按鈕向你的端點發送一個範例事件。

若要以程式碼建立 webhook,請使用 webhook 儀表板頂端顯示的驗證權杖呼叫 Notify API:

bash
Copied
curl -X POST https://dashboard.alchemy.com/api/create-webhook \ -H "X-Alchemy-Token: $ALCHEMY_WEBHOOK_AUTH_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "network": "BASE_MAINNET", "webhook_type": "ADDRESS_ACTIVITY", "webhook_url": "https://api.example.com/webhooks/alchemy", "addresses": ["0xYOUR_DEPOSIT_ADDRESS"] }'

之後你可以透過同一個 API 新增或移除地址,因此為每位新使用者建立入金地址的應用程式,只需維護一個 webhook,而不必建立數千個。Alchemy CLI 以 alchemy webhook create、list、update 與 delete 封裝了同一個 API,在由程式撰寫代理管理你的 webhook 時特別實用。

Alchemy 儀表板示範
Free video demo

實際體驗 Alchemy 儀表板

30 分鐘導覽:即時示範儀表板中的每項工具。

Watch the demo

開始在 Alchemy 上使用 webhook

Alchemy Webhooks 在 Free 方案中即可使用,無須簽約,也沒有最低用量承諾。很適合作為第一個 webhook 的,是在你控制的錢包上建立的 Address Activity webhook。向該錢包發送一筆小額轉帳,看著 payload 抵達你的端點。接下來,Custom webhook 讓你以相同的傳遞、重試與簽章機制,監看你自己合約的事件。

常見問題

簡單來說,webhook 是什麼?

webhook 是一個應用程式在事件發生時,自動傳送給另一個應用程式的訊息。發送端應用程式會向你提供的 URL 發出 HTTP POST 請求,並在請求主體中附上事件的詳細資訊。你的應用程式不必一直詢問是否有更新,因為更新會直接送過來。

webhook 和 API 有什麼差別?

使用 API 時,你的應用程式發送請求,伺服器再回應資料。使用 webhook 時,伺服器會在事件發生時主動向你的應用程式發送請求,無須你先詢問。API 適合依需求讀取資料,webhook 則適合回應事件。大多數應用程式兩者並用,先收到 webhook,再呼叫 API 取得詳細資訊。

USDC 轉入我的錢包時,如何收到 webhook 通知?

在你接收 USDC 的鏈上建立 Alchemy Address Activity webhook,加入你的錢包地址,並將它指向你伺服器的 URL。每筆轉入的轉帳都會附上發送方、金額與代幣合約地址。請比對 USDC 的合約地址,而不是「USDC」這個符號,因為任何人都能部署同名的代幣。

如何收到 Solana 錢包活動的 webhook 通知?

Alchemy 的 Address Activity webhook 除了支援 30 多條 EVM 鏈,也支援 Solana,因此你可以監看一組 Solana 錢包地址,並在這些地址有活動時收到 POST 請求。Address Activity webhook 文件中附有 Solana 專用設定指南的連結。處理每個請求之前,請先驗證其簽章。

我的智慧合約發出事件時,webhook 能通知我嗎?

可以。Alchemy Custom webhook 接受 GraphQL 查詢,因此你可以篩選出來自你的合約地址、且帶有特定事件簽章的日誌。接著,webhook 會針對每個新區塊觸發,且只帶有符合條件的日誌。每個 Custom webhook 只監看一個網路,因此請在部署合約的每條鏈上各建立一個。

webhook 觸發時,如果我的伺服器停機會怎樣?

Alchemy 會以指數退避重試失敗的傳遞,在 Free 與 Pay As You Go 方案中最多持續 10 分鐘,在 Enterprise 方案中最多一小時。只要你的伺服器沒有回傳 200,該次傳遞就算失敗。如果伺服器停機時間更長,請從鏈上歷史資料回補遺漏的活動,在 Ethereum 與支援的 L2 上使用 Transfers API,在 Solana 與 Stellar 上則使用各鏈本身的歷史資料端點。

一個 webhook 可以追蹤多少個地址?

一個 Alchemy Address Activity webhook 最多可追蹤 100,000 個地址,Stellar Address Activity webhook 也是如此。你可以透過 Notify API 新增或移除地址,無須重新建立 webhook,很適合為每位使用者建立新入金地址的應用程式。

Background gradient

打造區塊鏈魔法

Alchemy 結合最強大的 Web3 開發者產品與工具,並提供資源、社群與卓越的支援。