Ethereum Webhooks: Real-Time On-Chain Event Notifications
A webhook turns something that happened on Ethereum, a token transfer, a swap, a new block, into an HTTP POST hitting your backend seconds, or milliseconds, later. It is the push model every exchange deposit system, liquidation bot, NFT tracker and onchain alert service is built on.
Ethereum itself has no native webhook API. What the protocol gives you are lower-level primitives: log queries, WebSocket subscriptions and the Beacon API event stream. Every "Ethereum webhook API" you can buy is a thin service that translates those primitives into HTTP callbacks. This guide explains the primitives, compares hosted webhook providers with running your own, and shows how to self-host the whole pipeline on a node you control.
How Ethereum webhooks actually work
Almost everything worth reacting to on Ethereum is an event log. When a smart contract emits an event, the node stores a log entry with the contract address, an array of up to four indexed topics and a data field for the non-indexed parameters. The first topic is always the event signature: the keccak256 hash of the event's canonical declaration. Transfer(address,address,uint256) hashes to 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, and that one value identifies every ERC-20 and ERC-721 transfer on the chain. You can compute any signature yourself with our keccak256 hash tool.
Nodes expose those logs two ways. eth_getLogs queries historical ranges and is the backbone of catch-up and backfill, subject to the block-range and result caps we cover in our eth_getLogs guide. eth_subscribe over WebSocket pushes matching logs the moment the node indexes a new block, and can also stream pending transaction hashes straight from the mempool. A webhook service is nothing more than a process that holds those subscriptions and forwards each match as an HTTP POST, with retries, signing and deduplication layered on top.
Three ways to get webhooks for on-chain events
Hosted webhook APIs like Alchemy Notify, QuickNode QuickAlerts or Moralis Streams are the fastest to set up: you configure a filter in a dashboard and their infrastructure calls your URL. The trade-offs appear at volume. You pay per delivered event or per compute unit, the filter language is whatever the provider ships, latency includes their queueing and multi-tenant fan-out, and migrating means rebuilding every stream against a different proprietary API.
Running your own small service against a remote RPC endpoint removes the lock-in: standard eth_subscribe filters work against any provider. But the subscription now rides a public-internet WebSocket that drops and must be resumed with careful eth_getLogs catch-up, and busy filters burn metered requests on infrastructure you still do not control.
The third option is the one this page is really about: run the webhook service on the same machine as the node. On BLAZED.sh your container or script deploys directly on the host of a fully synced Ethereum node and subscribes over a local WebSocket, so the hop between "node saw the log" and "your code saw the log" is measured in single-digit milliseconds instead of internet round-trips, and connections to ws://eth:8545 do not flap the way public-internet WebSockets do.
| Hosted webhook API | DIY on remote RPC | On the node (BLAZED.sh) | |
|---|---|---|---|
| Setup | Minutes, dashboard | Hours, your code | Hours, your code |
| Event freshness | Provider queue + internet | Internet WebSocket | Local socket, sub-10ms |
| Filter flexibility | Provider's schema | Full JSON-RPC | Full JSON-RPC + mempool |
| Cost at volume | Per event or compute unit | Metered per request | Subscription credits, deliveries free |
| Lock-in | Proprietary streams | None | None, standard RPC |
Webhook recipes: transfers, mints, swaps and mempool alerts
ERC-20 transfer webhooks
The most requested webhook by far is "tell me when this wallet receives tokens". Because the sender and recipient of a Transfer event are indexed, the node can do the filtering for you: pass the wallet address, zero-padded to 32 bytes, in the topic position you care about. This complete example fires for every USDC transfer into one wallet and forwards the raw log:
import { WebSocketProvider, zeroPadValue } from "ethers";
const provider = new WebSocketProvider("ws://eth:8545");
// keccak256("Transfer(address,address,uint256)")
const TRANSFER =
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const WALLET = zeroPadValue("0x742d35Cc6634C0532925a3b8D12C0b5cb5aAa101", 32);
// Fires for every USDC transfer INTO the wallet
provider.on({ address: USDC, topics: [TRANSFER, null, WALLET] }, (log) => {
fetch("https://your-app.com/hooks/usdc-in", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(log),
});
});NFT transfers and mints
ERC-721 uses the same Transfer signature as ERC-20, with one structural difference: the token ID is indexed too, so an NFT transfer log carries four topics while a token transfer carries three. A mint is simply a transfer whose from topic is the zero address, so a mint-alert webhook is the snippet above with the collection's contract address and the zero address padded into topic position two.
DeFi events: swaps and liquidations
The same pattern covers any protocol event once you know its signature. Uniswap V2 pair swaps are 0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822, and lending protocols emit liquidation events you can watch across every market of a protocol by filtering on topic0 alone, without pinning the contract address. Watching thousands of pools this way is exactly the workload where per-event hosted pricing hurts and a subscription against your own node does not.
Pending transactions: mempool webhooks
Everything above fires after a block is mined. If you need alerts before inclusion, for front-running protection, sniping detection or deposit pre-confirmation, subscribe to newPendingTransactions or read txpool_content directly. Hosted webhook products mostly do not expose the mempool at all; on your own node it is one more subscription on the same socket. Our guide on accessing the Ethereum mempool goes deep on this, and you can watch it live in our mempool visualizer.
eth/v1/events: the consensus-layer event stream
Since the merge there is a second event source most webhook guides ignore: every consensus client (Lighthouse, Prysm, Teku, Nimbus) serves the standard Beacon API /eth/v1/events endpoint as a Server-Sent Events stream. Its topics cover the chain's heartbeat rather than contract activity: head for every new block, finalized_checkpoint when an epoch finalizes, chain_reorg when the head moves sideways, plus attestations and validator lifecycle events.
# Server-Sent Events stream from any consensus client (Lighthouse shown)
curl -N "http://localhost:5052/eth/v1/events?topics=head,finalized_checkpoint"
event: head
data: {"slot":"1234567","block":"0x9a2f...","epoch_transition":false, ...}It is a pull-side stream, not an HTTP callback, but it slots naturally into a webhook pipeline: use head as the tick that triggers your execution-layer reads, and finalized_checkpoint to promote earlier deliveries from "seen" to "final" so downstream systems can act on money-moving events with confidence.
Build your own webhook service in about 100 lines
A production-shaped webhook service needs surprisingly little code: load a config of filters and target URLs, open one WebSocket to the node, attach a listener per filter, and POST each log with exponential-backoff retries. We maintain a complete, runnable version with a config-driven design, a Dockerfile and a local test receiver in our step-by-step tutorial: building real-time Ethereum event notifications. Deploying it on BLAZED.sh is pushing the container and setting RPC_URL=ws://eth:8545; the docs cover the deployment flow.
Whatever you build on, three failure modes separate toy webhook services from reliable ones. Reorgs: logs near the head can be emitted and then removed, so deliver with the block hash attached and either wait for confirmations or send correction events. Catch-up: after downtime, backfill with chunked eth_getLogs calls rather than one giant range. Idempotency: retries mean duplicates, so receivers should deduplicate on transaction hash, log index and block hash together.
Why placement decides webhook latency
Ethereum produces a block every 12 seconds, and the value of an event notification decays fast within that window: a liquidation alert that arrives 800ms after the competition's is worthless. A hosted webhook stack pays the provider's internal queueing plus an internet hop to your server; a remote WebSocket pays the internet hop on every event. Co-locating the subscriber on the node host removes both, which is the same architectural argument we make for IPC and local transports versus HTTP. The webhook POST to your backend still crosses the internet, but it starts from an event your code saw at node speed, with any enrichment reads (balances, receipts, traces) already done over the local socket at 1 credit per call.
Ethereum webhooks: frequently asked questions
Does Ethereum have a built-in webhook API?
No. The protocol itself only exposes pull and subscription primitives: eth_getLogs for querying past events, eth_subscribe over WebSocket for live logs and pending transactions, and the Beacon API eth/v1/events stream on consensus clients. A webhook API is a service layer that translates those primitives into HTTP POST callbacks. You can rent that layer from a hosted provider or run your own small service against a node.
How do I get a webhook when an ERC-20 transfer happens?
Subscribe to logs where the first topic is the keccak256 hash of Transfer(address,address,uint256), which is 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, and the address is the token contract. To watch a specific wallet, add its address, zero-padded to 32 bytes, as the second topic for outgoing transfers or the third topic for incoming ones. POST every matching log to your endpoint.
What is eth/v1/events?
It is the Beacon API event stream that every Ethereum consensus client (Lighthouse, Prysm, Teku, Nimbus) serves as Server-Sent Events. Topics include head, block, attestation, finalized_checkpoint and chain_reorg. It is a push stream rather than an HTTP callback, but it is the cleanest source for new-block and finality notifications, and it pairs well with execution-layer log subscriptions in a webhook pipeline.
Should I use webhooks or WebSockets for Ethereum events?
They solve different halves of the problem. A WebSocket is a persistent connection your service holds to a node; a webhook is an HTTP POST pushed to any URL. The usual architecture is both: one service holds a WebSocket subscription to the node and fans events out as webhooks to consumers that cannot hold a connection, like serverless functions, Slack, or a customer's backend.
How do Ethereum webhooks handle chain reorganizations?
Logs near the chain head can be emitted and later removed when a block is orphaned; subscriptions redeliver such logs with removed set to true. A robust pipeline either waits a few confirmations before delivering, or delivers immediately with the block hash attached and sends a correction event on reorg. Receivers should deduplicate on the combination of transaction hash, log index and block hash.
How much does it cost to run your own Ethereum webhook service?
On BLAZED.sh your subscription grants a monthly credit balance and most RPC calls cost 1 credit. A subscription-driven webhook service is cheap by construction: it holds one eth_subscribe stream and makes occasional reads, and the outbound webhook deliveries are plain HTTP requests that draw no credits at all. The Beta plan is 75 euro per month with 1M credits, 1 container and 2 scripts; pricing is still being finalized.
Ship your webhook service on the node
Deploy the container next to a fully synced Ethereum node: local WebSocket, mempool access, no rate limits, predictable per-request credits.