- Tools
- Chainhooks
- Migration
Migration guide
Guide for migrating legacy chainhooks to v2
Managing v1 chainhooks
Legacy v1 chainhooks remain read-only in the Platform UI, but you manage them through the Platform API.
What you'll learn
Capture and analyze all existing v1 chainhooks.
Convert predicate-based filters into explicit v2 event definitions.
Register v2 chainhooks, test delivery, and retire the originals safely.
Prerequisites
- Hiro API key for access to both the Platform and Chainhooks API.
Get a list of v1 chainhooks
Use the Platform API to fetch the chainhooks you want to migrate.
index.ts
const response = await fetch(`https://api.platform.hiro.so/v1/ext/${process.env.HIRO_API_KEY}/chainhooks`, {headers: {'content-type': 'application/json'}});const chainhooks = await response.json();
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:
| v1 | v2 | Notes |
|---|---|---|
if_this.scope | filters.events[].type | Replace scope/action combos with a single event type. |
if_this.actions | type | transfer maps to *_transfer. |
then_that.http_post.url | action.url | v2 handles secrets automatically. |
networks.mainnet | network: "mainnet" | Create one v2 hook per network. |
authorization_header | Webhook secret management | Use 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 and cleanup legacy chainhooks
Stream events through both versions, confirm delivery, then clean up the legacy definitions.
Best practices
Keep both v1 and v2 hooks active until you verify delivery parity.
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);
Delete legacy chainhooks
const response = await fetch(`https://api.platform.hiro.so/v1/ext/${process.env.HIRO_API_KEY}/chainhooks/${uuid}`,{method: 'DELETE',headers: {'content-type': 'application/json'}});await response.json();
Filter reference
Common scopes
| v1 | Typical Actions | v2 | Extras |
|---|---|---|---|
stx_event | transfer | stx_transfer | Include sender or recipient filters as needed. |
contract_call | n/a | contract_call | Add contract_identifier and function_name. |
ft_event | transfer | ft_transfer | Specify asset_identifier. |
nft_event | transfer, mint | nft_transfer · nft_mint | Provide asset_identifier. |
For more details, check out the Filters reference page.