Getting Started

Creating a webhook using the AvaCloud portal

There are many websites you can use to test out webhooks. For example, you can use https://webhook.site/ and copy your unique URL. Once you have the URL, you can test using the following steps:

1 - Navigate to the AvaCloud dashboard

2 - Click "Create Webhook"

3 - Fill out the form with the unique URL generated in https://webhook.site/ and the address you want to monitor. In this example, we want to monitor USDC on the mainnet. The address for the USDC contract is the C-chain is 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E. The event type is address_activity and leave the event signature empty.

4 - Click Create and go to webhook.site, you should see something like this:

Managing webhooks using Glacier API

You can programmatically manage webhooks using Glacier API. For example:

1 - Navigate to the AvaCloud dashboard

2 - Click "Add API Key"

3 - Copy your API key and use it to create a webhook. For example:

curl --location 'https://glacier-api.avax.network/v1/webhooks' \
--header 'Content-Type: application/json' \
--header 'x-glacier-api-key: <YOUR_API_KEY>' \
--data '{
    "url": "https://webhook.site/af5cfd05-d104-4573-8ff0-6f11dffbf1eb",
    "chainId": "43114",
    "eventType": "address_activity",
    "metadata": {
        "addresses": ["0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"]
    },
   "name": "Dokyo",
   "description": "Dokyo NFT"
   "includeInternalTxs": true,
   "includeLogs": True
}'

Use all Glacier methods at your convenience to create, update, delete or list the webhooks in your AvaCloud account.

Local testing with a Node.js Express app

If we want to test the webhook in our computer and we are behind a proxy/NAT device or a firewall we need a tool like Ngrok. Avacloud will trigger the webhook and make a POST to the Ngrok cloud, then the request is forwarded to your local Ngrok client who in turn forwards it to the Node.js app listening on port 8000.
Go to https://ngrok.com/ create a free account, download the binary, and connect to your account. Create a Node.js app with Express and paste the following code to receive the webhook:

const express = require('express');
const app = express();

app.post('/callback', express.json({ type: 'application/json' }), (request, response) => {
   const { body, headers } = request;
   // Handle the event
   switch (body.eventType) {
       case 'address_activity':
           console.log("*** Address_activity ***");
           console.log(body);
           break;
       // ... handle other event types
       default:
           console.log(`Unhandled event type ${body}`);
   }
   // Return a response to acknowledge receipt of the event
   response.json({ received: true });
});

const PORT = 8000;
app.listen(PORT, () => console.log(`Running on port ${PORT}`));

Run the app with the following command:

node app.js

The Express app will be listening on port 8000. To start an HTTP tunnel forwarding to your local port 8000 with Ngrok, run this next:

./ngrok http 8000

You should see something like this:

ngrok                                                                                                                                                                           (Ctrl+C to quit)
                                                                                                                                                                                                
Take our ngrok in production survey! https://forms.gle/aXiBFWzEA36DudFn6                                                                                                                        
                                                                                                                                                                                                
Session Status                online                                                                                                                                                            
Account                       [email protected] (Plan: Free)                                                                                                                            
Update                        update available (version 3.7.0, Ctrl-U to update)                                                                                                                
Version                       3.5.0                                                                                                                                                             
Region                        United States (us)                                                                                                                                                
Latency                       -                                                                                                                                                                 
Web Interface                 http://127.0.0.1:4040                                                                                                                                             
Forwarding                    https://825a-2600-1700-5220-11a0-385f-7786-5e74-32cb.ngrok-free.app -> http://localhost:8000                                                                      
                                                                                                                                                                                                
Connections                   ttl     opn     rt1     rt5     p50     p90                                                                                                                       
                              0       0       0.00    0.00    0.00    0.00                                                                                                                      
                                                                             

Copy the HTTPS forwarding URL and append the/callbackpath and type the address you want to monitor.
If we transfer AVAX to the address AvaCloud will detect the payment and the webhook will be triggered. Now we can receive the event on our local server. The response should be something like this:

{
  "webhookId": "8ca68f98-18e5-47fb-a669-9ba7a6ed32b0",
  "eventType": "address_activity",
  "messageId": "ad66c866-17b4-44f7-9485-32211170da86",
  "event": {
    "transaction": {
      "blockHash": "0x924ab683b4eba825410b8f233297927aa91af9483fe2d7dd799afbe0e70ea2db",
      "blockNumber": "42776050",
      "from": "0x4962aE47413a39fe219e17679124DF0086f0C369",
      "gas": "296025",
      "gasPrice": "35489466312",
      "maxFeePerGas": "35489466312",
      "maxPriorityFeePerGas": "1500000000",
      "txHash": "0x9d3b6efae152cd17a30e5522b07d7217a9809a4a437b3269ded7474cfdecd167",
      "txStatus": "1",
      "input": "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000065ef6db400000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000009b6e64a8ec600000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000009b6e64a8ec60000000000000000000000000000000000000000000000000001d16b69c3febc194200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042b31f66aa3c1e785363f0875a1b74e27b85fd66c70001f4b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e000bb8d586e7f844cea2f87f50152665bcbc2c279d8d70000000000000000000000000000000000000000000000000000000000000",
      "nonce": "0",
      "to": "0x4dae2f939acf50408e13d58534ff8c2776d45265",
      "transactionIndex": 17,
      "value": "700000000000000000",
      "type": 2,
      "chainId": "43114",
      "receiptCumulativeGasUsed": "2215655",
      "receiptGasUsed": "244010",
      "receiptEffectiveGasPrice": "28211132966",
      "receiptRoot": "0x40d0ea00b2ce9e72a4bdebfbdc8dd4d73ebecbf80f1c107993eb78a5d28a44bf",
      "contractAddress": "0x0000000000000000000000000000000000000000",
      "blockTimestamp": 1710189471
    },
    "logs": [
      {
        "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
        "topic0": "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c",
        "topic1": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic2": null,
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000009b6e64a8ec60000",
        "transactionIndex": 17,
        "logIndex": 39,
        "removed": false
      },
      {
        "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x000000000000000000000000fae3f424a0a47706811521e3ee268f00cfb5c45e",
        "topic2": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000000000000020826ca",
        "transactionIndex": 17,
        "logIndex": 40,
        "removed": false
      },
      {
        "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic2": "0x000000000000000000000000fae3f424a0a47706811521e3ee268f00cfb5c45e",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000009b6e64a8ec60000",
        "transactionIndex": 17,
        "logIndex": 41,
        "removed": false
      },
      {
        "address": "0xfAe3f424a0a47706811521E3ee268f00cFb5c45E",
        "topic0": "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67",
        "topic1": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic2": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000009b6e64a8ec60000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffdf7d93600000000000000000000000000000000000000000000751b593c19962c0ca27000000000000000000000000000000000000000000000000006d2063b8b0f00effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc606b",
        "transactionIndex": 17,
        "logIndex": 42,
        "removed": false
      },
      {
        "address": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x000000000000000000000000a7141c79d3d4a9ad67ba95d2b97fe7eed9fb92b3",
        "topic2": "0x0000000000000000000000004962ae47413a39fe219e17679124df0086f0c369",
        "topic3": null,
        "data": "0x000000000000000000000000000000000000000000000001d75d7654d90a2700",
        "transactionIndex": 17,
        "logIndex": 43,
        "removed": false
      },
      {
        "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic2": "0x000000000000000000000000a7141c79d3d4a9ad67ba95d2b97fe7eed9fb92b3",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000000000000020826ca",
        "transactionIndex": 17,
        "logIndex": 44,
        "removed": false
      },
      {
        "address": "0xA7141C79d3d4a9ad67bA95D2b97Fe7EeD9fB92B3",
        "topic0": "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67",
        "topic1": "0x0000000000000000000000004dae2f939acf50408e13d58534ff8c2776d45265",
        "topic2": "0x0000000000000000000000004962ae47413a39fe219e17679124df0086f0c369",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000000000000020826cafffffffffffffffffffffffffffffffffffffffffffffffe28a289ab26f5d90000000000000000000000000000000000000f410a3539e2dfdf2b8bb00e7cab2f00000000000000000000000000000000000000000000000099a49d85f5d9286a000000000000000000000000000000000000000000000000000000000004375d",
        "transactionIndex": 17,
        "logIndex": 45,
        "removed": false
      }
    ]
  }
}                                                                                                                                                                                      

Create a webhook filter with an event signature

This feature allows you to filter events based on their signature. In a smart contract, events serve as notifications of specific occurrences, like transactions, or changes in ownership. Each event is uniquely identified by its event signature, which is calculated using the keccak 256 hash of the event name and its input argument types.

For example, for an ERC-20 transfer event, the event signature is determined by taking the hash of Transfer(address,address,uint256). To compute this hash yourself, you can use an online keccak-256 converter and you’ll see that the hexadecimal representation of Transfer(address,address,uint256) is 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. For a full list of signatures check https://www.4byte.directory/event-signatures/.

Take into consideration that the Transfer event for ERC-20 and ERC-721 tokens is similar. Here is the Transfer event prototype on each standard:

  • ERC20: event Transfer(address indexed _from, address indexed _to, uint256 _value)
  • ERC721: event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

These two signatures are indeed the same when you hash them to identifyTransfer events. The example below illustrates how to set up filtering to receive transfer events.

curl --location '<https://glacier-api.avax.network/v1/webhooks'>  
--header 'x-glacier-api-key: <YOUR_API_KEY'  
--header 'Content-Type: application/json'  
--data '{  
   "url": "https://webhook.site/30eb3703-04f0-4a01-8903-fe3f5afb78bc",  
   "chainId": "43114",  
   "eventType": "address_activity",  
   "metadata": {  
       "addresses": ["0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"],  
       "eventSignatures": [  
           "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"  
        ]  
   },  
   "name": "USDC",  
   "description": "USDC"  
}'

NFT Transfer Notification Example

If you want to receive a notification whenever a Dokyo NFT is transferred, you will use an expression like the following:

curl --location 'https://glacier-api.avax.network/v1/webhooks' \
--header 'x-glacier-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
    "url": "https://webhook.site/961a0d1b-a7ed-42fd-9eab-d7e4c7eb1227",
    "chainId": "43114",
    "eventType": "address_activity",
    "metadata": {
        "addresses": ["0x54C800d2331E10467143911aabCa092d68bF4166"],
        "includeInternalTxs": false,
        "includeLogs": true,
        "eventSignatures": [
           "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        ]

    },
    "name": "Dokyo NFT",
    "description": "Dokyo NFT"
}'

Whenever an NFT is transferred you’ll receive a payload like this:

{
  "webhookId": "6d1bd383-aa8d-47b5-b793-da6d8a115fde",
  "eventType": "address_activity",
  "messageId": "6a364b45-47a2-45af-97c3-0ddc2e87ad36",
  "event": {
    "transaction": {
      "blockHash": "0x30da6a8887bf2c26b7921a1501abd6e697529427e4a4f52a9d4fc163a2344b46",
      "blockNumber": "42649820",
      "from": "0x0000333883f313AD709f583D0A3d2E18a44EF29b",
      "gas": "245004",
      "gasPrice": "30000000000",
      "maxFeePerGas": "30000000000",
      "maxPriorityFeePerGas": "30000000000",
      "txHash": "0x2f1a9e2b8719536997596d878f21b70f2ce0901287aa3480d923e7ffc68ac3bc",
      "txStatus": "1",
      "input": "0xafde1b3c0000000000000000000000000…0000000000000000000000000000000000",
      "nonce": "898",
      "to": "0x398baa6ffc99126671ab6be565856105a6118a40",
      "transactionIndex": 0,
      "value": "0",
      "type": 0,
      "chainId": "43114",
      "receiptCumulativeGasUsed": "163336",
      "receiptGasUsed": "163336",
      "receiptEffectiveGasPrice": "30000000000",
      "receiptRoot": "0xdf05c214cee5ff908744e13a3b2879fdba01c9c7f95073670cb23ed735126178",
      "contractAddress": "0x0000000000000000000000000000000000000000",
      "blockTimestamp": 1709930290
    },
    "logs": [
      {
        "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000008cdd7a500f21455361cf1c2e01c0525ce92481b2",
        "topic2": "0x0000000000000000000000000000333883f313ad709f583d0a3d2e18a44ef29b",
        "topic3": null,
        "data": "0x000000000000000000000000000000000000000000000001a6c5c6f4f4f6d060",
        "transactionIndex": 0,
        "logIndex": 0,
        "removed": false
      },
      {
        "address": "0x54C800d2331E10467143911aabCa092d68bF4166",
        "topic0": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
        "topic1": "0x0000000000000000000000000000333883f313ad709f583d0a3d2e18a44ef29b",
        "topic2": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "topic3": "0x0000000000000000000000000000000000000000000000000000000000001350",
        "data": "0x",
        "transactionIndex": 0,
        "logIndex": 1,
        "removed": false
      },
      {
        "address": "0x54C800d2331E10467143911aabCa092d68bF4166",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000000000333883f313ad709f583d0a3d2e18a44ef29b",
        "topic2": "0x0000000000000000000000008cdd7a500f21455361cf1c2e01c0525ce92481b2",
        "topic3": "0x0000000000000000000000000000000000000000000000000000000000001350",
        "data": "0x",
        "transactionIndex": 0,
        "logIndex": 2,
        "removed": false
      },
      {
        "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000008cdd7a500f21455361cf1c2e01c0525ce92481b2",
        "topic2": "0x00000000000000000000000087f45335268512cc5593d435e61df4d75b07d2a2",
        "topic3": null,
        "data": "0x000000000000000000000000000000000000000000000000087498758a04efb0",
        "transactionIndex": 0,
        "logIndex": 3,
        "removed": false
      },
      {
        "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000008cdd7a500f21455361cf1c2e01c0525ce92481b2",
        "topic2": "0x000000000000000000000000610512654af4fa883bb727afdff2dd78b65342b7",
        "topic3": null,
        "data": "0x000000000000000000000000000000000000000000000000021d261d62813bec",
        "transactionIndex": 0,
        "logIndex": 4,
        "removed": false
      },
      {
        "address": "0x398BAa6FFc99126671Ab6be565856105a6118A40",
        "topic0": "0x50273fa02273cceea9cf085b42de5c8af60624140168bd71357db833535877af",
        "topic1": null,
        "topic2": null,
        "topic3": null,
        "data": "0x0000000000009911a89f400000000000000000000…0000010",
        "transactionIndex": 0,
        "logIndex": 5,
        "removed": false
      }
    ]
  }
}