Skip to main content

Using Webhooks

Add a new Secure Webhook

To create a new Secure Webhook go to Blockfrost Dashboard and click on Add webhook button. In the webhook settings, fill in the webhook name, select the trigger event your app needs, and create the necessary Trigger conditions. Do not worry about not getting everything right, you can update the settings anytime.

The webhook endpoint URL should be set to a publicly accessible HTTPS URL, where you will process the events sent via webhook request. If you do not have your backend exposed to the web, follow the steps in Test your webhook to test with a web server running on your local machine.

Rollbacks and a required number of confirmations

Events are sent to your webhook endpoint after reaching the number of confirmations you specified in Secure Webhook Settings. It may happen that the Cardano network rollbacks a few blocks, invalidating events that have been sent. Due to rollbacks, you may receive the same event multiple times.


Let's say you set up a Secure Webhook for a transaction event with the number of required confirmations set to 0. The transaction you are interested in gets included in a block so you will be notified about the transaction. Then the block is rolled back and the same transaction is included in a new block. You will receive another transaction event with the same transaction hash, but the hash of the block in which the transaction was included will differ from the first event).

We recommend verifying that the event you received has not been rolled back or increasing the number of required confirmations before the event is sent to your endpoint.

Process a webhook request

Create an HTTP endpoint on your backend where you will process incoming events and trigger actions you want to execute. The endpoint must accept POST requests with data in JSON format and return a successful status code (2xx).

Each request body is an object with several fields. The event type is stored in type field. The event itself is included in payload field. For the complete structure of a webhook request, see Events overview.

Don't forget to verify that the event originated from Blockfrost, not a third party just pretending to be Blockfrost. See Check signatures.

Here is a quick example of a web application that implements /webhook endpoint and leverages the Blockfrost SDK to verify the webhook signature:

Missing an example for your favorite language?

Earn a bounty for contributing examples in your favorite language. Everyone can participate and earn rewards for contributions. Join the Blockfrost Bounty Program now!

// Example of Node.js Express app with /webhook endpoint
// for processing events sent by Blockfrost Secure Webhooks
const express = require("express");
const blockfrost = require("@blockfrost/blockfrost-js");
const { verifyWebhookSignature, SignatureVerificationError } = blockfrost;

// You will find the webhook secret auth token in the Webhook settings in the Blockfrost Dashboard

const app = express();

// Define endpoint /webhook that accepts POST requests
express.json({ type: "application/json" }),
(request, response) => {
const signatureHeader = request.headers["blockfrost-signature"];

// Make sure that Blockfrost-Signature header exists
if (!signatureHeader) {
console.log("The request is missing Blockfrost-Signature header");
return response.status(400).send(`Missing signature header`);

// Validate the webhook signature
try {
JSON.stringify(request.body), // stringified request.body
600 // optional param to customize maximum allowed age of the webhook event, defaults to 600s
} catch (error) {
// In case of invalid signature verifyWebhookSignature will throw SignatureVerificationError
// for easier debugging you can access passed signatureHeader and webhookPayload values (error.detail.signatureHeader, error.detail.webhookPayload)
return response.status(400).send("Signature is not valid!");

// Signature is valid
const type = request.body.type;
const payload = request.body.payload;

// Process the incoming event
switch (type) {
case "transaction":
// process Transaction event
console.log(`Received ${payload.length} transactions`);
// loop through the payload (payload is an array of Transaction events)
for (const transaction of payload) {
console.log(`Transaction ${transaction.tx.hash}`);

case "block":
// process Block event
console.log(`Received block hash ${payload.hash}`);

case "delegation":
// process Delegation event
console.log(`Received ${payload.length} delegations`);
// loop through the payload, payload is an array of objects with fields: "tx" (an object) and "delegations" (an array)
for (const transaction of payload) {
for (const delegation of transaction.delegations) {
`Delegation from address ${delegation.address} included in tx ${transaction.tx.hash}`

case "epoch":
// process Epoch event
`Epoch switch from ${payload.previous_epoch.epoch} to ${payload.current_epoch.epoch}`

console.warn(`Unexpected event type ${type}`);

// Return status code 2xx
response.json({ processed: true });

app.listen(6666, () => console.log("Running on port 6666"));


In case your webhook endpoint is responding with one of following error status codes: 400, 408, 413, 429, 500, 502, 503, 504, 521, 522 or 524, Blockfrost will resend the request 2 more times with few seconds of backoff between each request. Body of the request is the same between retries, the ID of the retried request will be the same as the ID of the original request that failed.


To help you with troubleshooting problems with your endpoint, check the list of recent failed requests in Secure Webhook settings in Blockfrost Dashboard.

If your webhook endpoint doesn't respond with a successful status code (2xx) within few seconds then the request will time out.


To prevent unexpected issues, your application should be prepared for a scenario in which the webhook request never arrives. To keep your app fully functioning and still provide a good user experience, you can manually fetch the data via the traditional Blockfrost API.

Test your webhook

The easiest way to explore the data sent via a webhook is to point it to a service such as It generates a random URL and displays every request sent to this address and its body.

Local web server

In order to test Secure Webhooks with your endpoint implementation running on your local HTTP dev server, you need to expose it to the web. Fortunately, services like will set it up for you.

Follow Loophole documentation to download the CLI or the Desktop GUI app, create an account and expose your local HTTP server.


To expose a local web server running on port 6666 via CLI, run the command loophole http 6666. In the Webhook settings, set the webhook endpoint to the URL you will see in the output (if you are using the example do not forget to append /webhook at the end).

$ loophole http 6666
Loophole - End to end TLS encrypted TCP communication between you and your clients
Registering your domain... Success!
Starting local proxy server... Success!
Initializing secure tunnel... Success!

Forwarding ->