Migration guide

Guide for migrating legacy chainhooks to v2

Migrating legacy definitions

The legacy Platform API and Chainhooks UI have been retired. This guide shows how to convert saved v1 definitions to v2. If you need help recovering a definition or retiring an existing v1 chainhook, contact support.

What you'll learn

Review your saved v1 chainhook definitions.
Convert predicate-based filters into explicit v2 event definitions.
Register v2 chainhooks and test delivery.

Prerequisites

  • Hiro API key for the Chainhooks API.
  • Saved v1 chainhook definitions, including filters and webhook URLs.
  • (optional) If you use TypeScript and Node.js, you can install the Chainhooks client library to easily parse incoming Chainhooks v2 payloads

Gather your v1 definitions

Use your saved configurations or exports to identify the filters, networks, and webhook URLs you want to migrate. If you do not have a copy, contact support before proceeding.

Start mapping to the new v2 format

Translate v1 structures to v2 formats before creating new hooks. The following table shows the mapping between v1 and v2 structures:

v1v2Notes
if_this.scopefilters.events[].typeReplace scope/action combos with a single event type.
if_this.actionstypetransfer maps to *_transfer.
then_that.http_post.urlaction.urlv2 handles secrets automatically.
networks.mainnetnetwork: "mainnet"Create one v2 hook per network.
authorization_headerWebhook secret managementUse rotateConsumerSecret() after registration.

Example

{
"name": "stx-transfers",
"networks": {
"mainnet": {
"if_this": { "scope": "stx_event", "actions": ["transfer"] },
"then_that": { "http_post": { "url": "https://example.com/webhooks" } }
}
}
}

For more details on the format changes, see the Filters reference guide.

Create v2 chainhooks

Register each chainhook with the SDK or REST API, mirroring the mapped filters.

const v2Chainhook = {
"version": "1",
"name": "stx-transfers",
"chain": "stacks",
"network": "mainnet",
"filters": {
"events": [{ "type": "stx_transfer" }]
},
"action": {
"type": "http_post",
"url": "https://example.com/webhooks"
},
"options": {
"decode_clarity_values": true,
"enable_on_registration": true
}
};
const response = await fetch('https://api.hiro.so/chainhooks/v1/me/', {
method: 'POST',
headers: {
'x-api-key': process.env.HIRO_API_KEY!,
'content-type': 'application/json',
},
body: JSON.stringify(v2Chainhook),
});

Validate v2 chainhooks

Confirm that each chainhook is enabled and that your webhook receives the expected events. Update your application to handle the v2 payload format.

Enablement checks on v2

const response = await fetch(`https://api.hiro.so/chainhooks/v1/me/${uuid}`, {
method: 'GET',
headers: {
'x-api-key': process.env.HIRO_API_KEY!,
'content-type': 'application/json',
},
});
const chainhook = await response.json();
console.log(chainhook.status.enabled);

Filter reference

Common scopes

v1Typical Actionsv2Extras
stx_eventtransferstx_transferInclude sender or recipient filters as needed.
contract_calln/acontract_callAdd contract_identifier and function_name.
ft_eventtransferft_transferSpecify asset_identifier.
nft_eventtransfer, mintnft_transfer · nft_mintProvide asset_identifier.

For more details, check out the Filters reference page.

Replaying past blocks

Chainhooks v2 does not have the ability to specify a start block in a hook’s configuration for past block scans.

However, you can use the Replay Block API endpoint to request any block replay you need at any time. Once requested, you will receive that block’s information through the same webhook payload endpoint you use for real-time updates within a couple seconds.

This method ensures you have complete control over which blocks you need to replay whenever you need to.

Next steps

How is this guide?