Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions docs/start-building/webhooks/using-webhooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ To create a new Secure Webhook go to [Blockfrost Dashboard](https://blockfrost.i

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](using-webhooks#test-your-webhook) to test with a web server running on your local machine.

### At-least-once delivery and idempotency

Webhook events are delivered **at least once**. The same logical event can be POSTed to your endpoint more than once for several reasons:

- Your endpoint returned a retryable error and Blockfrost retried (see [Retries](#retries)).
- A transient network or infrastructure event caused an in-flight request to be redelivered.
- A rollback re-emitted an event that was already dispatched at a lower confirmation level.

To make this safe, every event carries a stable `id` field. The `id` is deterministic — the same logical event always has the same `id`, so a duplicate delivery is trivially recognizable.

**Recommended:** treat `id` as an idempotency key. Before acting on an event, check whether you've already processed an event with that `id`; if so, return `2xx` and ignore. Any relational database with a unique index on `id`, a key-value store, or a bounded in-memory LRU is enough. This is the simplest way to make your handler safe against retries, transient duplicates, and rollback re-emissions in a single pass.

### 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.
Expand All @@ -19,13 +31,13 @@ During a rollback, multiple blocks may be invalidated and replaced simultaneousl
For instance, a notification about a block at a higher height might arrive before one for a lower height due to the asynchronous nature of these requests.
:::

Due to a rollback, you may receive the same event multiple times.
Due to a rollback, you may also receive the same event more than once. As described in [At-least-once delivery](#at-least-once-delivery-and-idempotency), duplicate deliveries always carry the same `id`, so deduplicating on `id` covers rollbacks too.

:::note Example
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.
To reduce exposure to rollbacks, increase the number of required confirmations in your webhook settings, or verify on your side that the event has not been rolled back before acting on it.

## Process a webhook request

Expand Down Expand Up @@ -81,7 +93,7 @@ app.post(
SECRET_AUTH_TOKEN,
600 // optional param to customize maximum allowed age of the webhook event, defaults to 600s
);

// Signature is valid
const type = request.body.type;
const payload = request.body.payload;
Expand Down Expand Up @@ -320,6 +332,7 @@ func main() {
### Retries

Blockfrost will attempt to resend the webhook request up to two additional times (making a total of three attempts, including the initial try) if your endpoint returns any of the following HTTP error status codes:

- 400 Bad Request
- 408 Request Timeout
- 413 Payload Too Large
Expand All @@ -346,6 +359,10 @@ To prevent unexpected issues, your application should be prepared for a scenario
To keep your app fully functioning and still provide a good user experience, you can manually fetch the data via the traditional [Blockfrost API](https://docs.blockfrost.io).
:::

:::caution Stale webhooks are auto-disabled
Webhooks whose endpoint has been failing for an extended period are automatically disabled to avoid wasting delivery attempts on a broken target. If your webhook stops firing, check its status in the [Blockfrost Dashboard](https://blockfrost.io/dashboard) and re-enable it once your endpoint is healthy again.
:::

## Test your webhook

### Webhook.site
Expand Down
4 changes: 2 additions & 2 deletions docs/start-building/webhooks/webhooks-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Blockfrost Secure Webhooks support various events such as Transaction, Block, Ep

Each request body has the following fields:

`id` - Unique identifier of the webhook request. Each request, even coming from the same webhook, will have a distinct ID. However, requests that fail are retried multiple times with the same ID. To learn more, see [Retries](./using-webhooks#retries).
`id` - Stable identifier of the event. The `id` is deterministic: the same logical event always carries the same `id`, regardless of how many times it is delivered. Duplicate deliveries (from retries, network glitches, or internal failover) arrive with the **same `id`** the first delivery had, which makes `id` a natural idempotency key on your side. To learn more, see [At-least-once delivery](./using-webhooks#at-least-once-delivery-and-idempotency) and [Retries](./using-webhooks#retries).

`created` - Unix timestamp (in seconds) with the time when our system detected the event.

Expand All @@ -20,7 +20,7 @@ Each request body has the following fields:
`payload` - Event data. For the exact format of each event payload, see breakdown below.

:::caution
It may happen that Cardano network rollbacks a few blocks, invalidating the event that has been sent. Due to rollbacks, you may receive the same event multiple times. To learn more see [Rollbacks](./using-webhooks#rollbacks-and-a-required-number-of-confirmations).
Webhook events are delivered **at least once**, so the same event may arrive more than once. Duplicate deliveries always carry the same `id`, so deduplicating on `id` is enough. See [At-least-once delivery](./using-webhooks#at-least-once-delivery-and-idempotency) and [Rollbacks](./using-webhooks#rollbacks-and-a-required-number-of-confirmations).
:::

## Transaction
Expand Down