# Authentication
Source: https://developers.avacloud.io/avacloud-sdk/authentication



### Per-Client Security Schemes

This SDK supports the following security scheme globally:

| Name     | Type   | Scheme  |
| -------- | ------ | ------- |
| `apiKey` | apiKey | API key |

The AvaCloud SDK can be used without an API key, but rate limits will be lower. Adding an API key allows for higher rate limits. To get an API key, create one via [AvaCloud](https://app.avacloud.io/) and securely store it. Whether or not you use an API key, you can still interact with the SDK effectively, but the API key provides performance benefits for higher request volumes.

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    const result = await avaCloudSDK.metrics.healthCheck.metricsHealthCheck();

    // Handle the result
    console.log(result);
}

run();
```

<Warning>Never hardcode your API key directly into your code. Instead, securely store it and retrieve it from an environment variable, a secrets manager, or a dedicated configuration storage mechanism. This ensures that sensitive information remains protected and is not exposed in version control or publicly accessible code.</Warning>


# Custom HTTP Client
Source: https://developers.avacloud.io/avacloud-sdk/custom-http



The TypeScript SDK makes API calls using an HTTPClient that wraps the native [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). This client is a thin wrapper around `fetch` and provides the ability to attach hooks around the request lifecycle that can be used to modify the request or handle errors and response.

The `HTTPClient` constructor takes an optional `fetcher` argument that can be used to integrate a third-party HTTP client or when writing tests to mock out the HTTP client and feed in fixtures.

The following example shows how to use the `beforeRequest` hook to to add a custom header and a timeout to requests and how to use the `requestError` hook to log errors:

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";
import { HTTPClient } from "@avalabs/avacloud-sdk/lib/http";

const httpClient = new HTTPClient({
  // fetcher takes a function that has the same signature as native `fetch`.
  fetcher: (request) => {
    return fetch(request);
  }
});

httpClient.addHook("beforeRequest", (request) => {
  const nextRequest = new Request(request, {
    signal: request.signal || AbortSignal.timeout(5000)
  });

  nextRequest.headers.set("x-custom-header", "custom value");

  return nextRequest;
});

httpClient.addHook("requestError", (error, request) => {
  console.group("Request Error");
  console.log("Reason:", `${error}`);
  console.log("Endpoint:", `${request.method} ${request.url}`);
  console.groupEnd();
});

const sdk = new AvaCloudSDK({ httpClient });
```


# Error Handling
Source: https://developers.avacloud.io/avacloud-sdk/error



All SDK methods return a response object or throw an error. If Error objects are specified in your OpenAPI Spec, the SDK will throw the appropriate Error type.

| Error Object               | Status Code | Content Type     |
| :------------------------- | :---------- | :--------------- |
| errors.BadRequest          | 400         | application/json |
| errors.Unauthorized        | 401         | application/json |
| errors.Forbidden           | 403         | application/json |
| errors.NotFound            | 404         | application/json |
| errors.TooManyRequests     | 429         | application/json |
| errors.InternalServerError | 500         | application/json |
| errors.BadGateway          | 502         | application/json |
| errors.ServiceUnavailable  | 503         | application/json |
| errors.SDKError            | 4xx-5xx     | /                |

Validation errors can also occur when either method arguments or data returned from the server do not match the expected format. The SDKValidationError that is thrown as a result will capture the raw value that failed validation in an attribute called `rawValue`. Additionally, a `pretty()` method is available on this error that can be used to log a nicely formatted string since validation errors can list many issues and the plain error string may be difficult read when debugging.

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";
import {
    BadGateway,
    BadRequest,
    Forbidden,
    InternalServerError,
    NotFound,
    SDKValidationError,
    ServiceUnavailable,
    TooManyRequests,
    Unauthorized,
} from "@avalabs/avacloud-sdk/models/errors";

const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    try {
        await avaCloudSDK.data.nfts.reindexNft({
            address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
            tokenId: "145",
        });
    } catch (err) {
        switch (true) {
            case err instanceof SDKValidationError: {
                // Validation errors can be pretty-printed
                console.error(err.pretty());
                // Raw value may also be inspected
                console.error(err.rawValue);
                return;
            }
            case err instanceof BadRequest: {
                // Handle err.data$: BadRequestData
                console.error(err);
                return;
            }
            case err instanceof Unauthorized: {
                // Handle err.data$: UnauthorizedData
                console.error(err);
                return;
            }
            case err instanceof Forbidden: {
                // Handle err.data$: ForbiddenData
                console.error(err);
                return;
            }
            case err instanceof NotFound: {
                // Handle err.data$: NotFoundData
                console.error(err);
                return;
            }
            case err instanceof TooManyRequests: {
                // Handle err.data$: TooManyRequestsData
                console.error(err);
                return;
            }
            case err instanceof InternalServerError: {
                // Handle err.data$: InternalServerErrorData
                console.error(err);
                return;
            }
            case err instanceof BadGateway: {
                // Handle err.data$: BadGatewayData
                console.error(err);
                return;
            }
            case err instanceof ServiceUnavailable: {
                // Handle err.data$: ServiceUnavailableData
                console.error(err);
                return;
            }
            default: {
                throw err;
            }
        }
    }
}

run();

```


# Getting Started
Source: https://developers.avacloud.io/avacloud-sdk/getting-started



### AvaCloud SDK

The AvaCloud SDK provides web3 application developers with multi-chain data related to Avalanche's primary network, Avalanche L1s, and Ethereum. With the Data API, you can easily build products that leverage real-time and historical transaction and transfer history, native and token balances, and various types of token metadata.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/avacloud-sdk.png" />
</Frame>

The SDK is currently available in TypeScript, with more languages coming soon. If you are interested in a language that is not listed, please reach out to us in the [#dev-tools](https://discord.com/channels/578992315641626624/1280920394236297257) channel in the [Avalanche Discord](https://discord.gg/avax).

<CardGroup cols={1}>
  <Card title="AvaCloud SDK TypeScript" icon="npm">
    [https://www.npmjs.com/package/@avalabs/avacloud-sdk](https://www.npmjs.com/package/@avalabs/avacloud-sdk)
  </Card>
</CardGroup>

<CardGroup cols={1}>
  <Card title="AvaCloud SDK TypeScript" icon="github">
    [https://github.com/ava-labs/avacloud-sdk-typescript?tab=readme-ov-file#-avacloud-sdk-typescript-](https://github.com/ava-labs/avacloud-sdk-typescript?tab=readme-ov-file#-avacloud-sdk-typescript-)
  </Card>
</CardGroup>

### SDK Installation

<CodeGroup>
  ```npm NPM
  npm add @avalabs/avacloud-sdk
  ```

  ```pnpm PNPM
  pnpm add @avalabs/avacloud-sdk
  ```

  ```bun Bun
  bun add @avalabs/avacloud-sdk
  ```

  ```yarn Yarn
  yarn add @avalabs/avacloud-sdk zod

  # Note that Yarn does not install peer dependencies automatically. You will need
  # to install zod as shown above.
  ```
</CodeGroup>

### SDK Example Usage

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    const result = await avaCloudSDK.metrics.healthCheck.metricsHealthCheck();

    // Handle the result
    console.log(result);
}

run();

```

Refer to the code samples provided for each route to see examples of how to use them in the SDK. Explore routes here [Data API](/data-api/health-check/get-the-health-of-the-service),
[Metrics API](/metrics-api/health-check/get-the-health-of-the-service) & [Webhooks API](/webhooks-api/webhooks/list-webhooks).


# Global Parameters
Source: https://developers.avacloud.io/avacloud-sdk/global-parameters



Certain parameters are configured globally. These parameters may be set on the SDK client instance itself during initialization. When configured as an option during SDK initialization, These global values will be used as defaults on the operations that use them. When such operations are called, there is a place in each to override the global value, if needed.

For example, you can set `chainId` to `43114` at SDK initialization and then you do not have to pass the same value on calls to operations like getBlock. But if you want to do so you may, which will locally override the global setting. See the example code below for a demonstration.

### Available Globals

The following global parameters are available.

| Name      | Type                          | Required | Description                                              |
| :-------- | :---------------------------- | :------- | :------------------------------------------------------- |
| `chainId` | string                        | No       | A supported EVM chain id, chain alias, or blockchain id. |
| `network` | components.GlobalParamNetwork | No       | A supported network type, either mainnet or a testnet.   |

Example

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
  apiKey: "<YOUR_API_KEY_HERE>",
  chainId: "43114", // Sets chainId globally, will be used if not passed during method call.
  network: "mainnet",
});

async function run() {
  const result = await avaCloudSDK.data.evm.blocks.getBlock({
    blockId: "0x17533aeb5193378b9ff441d61728e7a2ebaf10f61fd5310759451627dfca2e7c",
    chainId: "<YOUR_CHAIN_ID>", // Override the globally set chain id.
  });

  // Handle the result
  console.log(result)
}

run();
```


# Pagination
Source: https://developers.avacloud.io/avacloud-sdk/pagination



Some of the endpoints in this SDK support pagination. To use pagination, you make your SDK calls as usual, but the returned response object will also be an async iterable that can be consumed using the `for await...of` syntax.

Here's an example of one such pagination call:

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    const result = await avaCloudSDK.metrics.evm.chains.listChains({
        network: "mainnet",
    });

    for await (const page of result) {
        // Handle the page
        console.log(page);
    }
}

run();
```


# Retries
Source: https://developers.avacloud.io/avacloud-sdk/retries



Some of the endpoints in this SDK support retries. If you use the SDK without any configuration, it will fall back to the default retry strategy provided by the API. However, the default retry strategy can be overridden on a per-operation basis, or across the entire SDK.

To change the default retry strategy for a single API call, simply provide a retryConfig object to the call:

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    const result = await avaCloudSDK.metrics.healthCheck.metricsHealthCheck({
        retries: {
            strategy: "backoff",
            backoff: {
                initialInterval: 1,
                maxInterval: 50,
                exponent: 1.1,
                maxElapsedTime: 100,
            },
            retryConnectionErrors: false,
        },
    });

    // Handle the result
    console.log(result);
}

run();
```

If you'd like to override the default retry strategy for all operations that support retries, you can provide a retryConfig at SDK initialization:

```javascript
import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

const avaCloudSDK = new AvaCloudSDK({
    retryConfig: {
        strategy: "backoff",
        backoff: {
            initialInterval: 1,
            maxInterval: 50,
            exponent: 1.1,
            maxElapsedTime: 100,
        },
        retryConnectionErrors: false,
    },
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
});

async function run() {
    const result = await avaCloudSDK.metrics.healthCheck.metricsHealthCheck();

    // Handle the result
    console.log(result);
}

run();

```


# Changelog
Source: https://developers.avacloud.io/changelog/changelog



### Jan 08th, 2025

**Signature Aggregator Endpoint Update**

![Aggregated Transactions & Blocks](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/signature-aggregator.png)

📌  The `network` parameter has been added, allowing you to select between the following networks:

* `mainnet`
* `testnet` (Fuji)

This update allows you to aggregate signatures on either the `mainnet` or `Fuji testnet`, providing flexibility in signature aggregation depending on your environment.

Try it out [here](/data-api/signature-aggregator/aggregate-signatures)!

***

### Jan 08th, 2025

**🚀 New API Endpoints: Aggregated Transactions & Blocks Across L1 Chains & Avalanche C-Chain**

![Aggregated Transactions & Blocks](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/aggregated-blocks-transactions.png)

We're excited to introduce **two new API endpoints** that provide **aggregated transaction and block data** across **all supported L1 chains and the Avalanche C-Chain**! These endpoints allow developers to **query, filter, and sort** blockchain data efficiently, unlocking powerful insights across multiple chains.

**📌 Get Started**

* [List Latest Blocks for All Supported EVM Chains](https://developers.avacloud.io/data-api/evm-chains/list-latest-blocks-for-all-supported-evm-chains)
* [List Latest Transactions for All Supported EVM Chains](https://developers.avacloud.io/data-api/evm-chains/list-latest-transactions-for-all-supported-evm-chains)

These enhancements **simplify multi-chain data retrieval**, making it easier for developers to **build cross-chain analytics, wallets, and monitoring tools**. Try them out today and streamline your blockchain data integration! 🚀

***

### Dec 20th, 2024

**Token Reputation Analysis 🛡️🔍**

![Token Reputation Analysis](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/token-reputation.png)

We’re thrilled to introduce Token Reputation Analysis, a new feature for identifying potential security risks with ERC20 tokens on the Avalanche C-Chain!

This update adds a new field, `tokenReputation`, to the [List ERC-20 balances](/data-api/evm-balances/list-erc-20-balances) response. The field categorizes tokens into the following reputations:

* `Benign`: Tokens considered safe based on security analysis.
* `Malicious`: Tokens flagged for suspicious activity, spam, or phishing.
* `null`: Reputation unknown.

**Example Usage**

Here’s an example API call:

```bash
curl -X 'GET' \
  'https://glacier-api.avax.network/v1/chains/43114/addresses/0x51a679853D9582d29FF9e23ae336a0947BD0f337/balances:listErc20?pageSize=10&filterSpamTokens=true&currency=usd' \
  -H 'accept: application/json' | jq
```

As you can see in the response, the `$AVA` token is flagged as `Malicious`:

```json
{
  "erc20TokenBalances": [
    {
      "ercType": "ERC-20",
      "chainId": "43114",
      "address": "0x397e48aF37b7d7660D0Aee74c35b2218D7EFca12",
      "name": "$AVA (https://avalaunch.farm)",
      "symbol": "$AVA",
      "decimals": 2,
      "balance": "8200000",
      "tokenReputation": "Malicious"
    },
    {
      "ercType": "ERC-20",
      "chainId": "43114",
      "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
      "name": "USD Coin",
      "symbol": "USDC",
      "decimals": 6,
      "balance": "1515448052896",
      "tokenReputation": "Benign"
    }
  ]
}
```

Try it out [here](/data-api/evm-balances/list-erc-20-balances)!

***

### Nov 25th, 2024

**Avalanche9000 (Etna Upgrade 🌋)**

![Avalanche9000](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/avalanche9000.jpeg)

**New endpoint to list L1 validators:**

* Added new endpoint to [list all or specific L1 validators](/data-api/primary-network/list-l1-validators)
* Filters include `L1ValidationID`, `SubnetID`, `NodeID`, and `IncludeInactiveL1Validators`.

**Updated transactions endpoint:**

* [List latest transactions on the primary network](/data-api/primary-network-transactions/list-latest-transactions) now supports `l1ValidationID` to fetch transactions linked to specific L1 validators (e.g., `ConvertSubnetToL1Tx`).
* L1 transactions are sorted in descending order with additional filters like `timestamp` and `txTypes`.

**Enhanced transaction properties:**

* P-Chain Transaction responses now include:
  * L1 validator details (`validationID`, `nodeID`, `weight`, `balances`, etc.).
  * Burned AVAX details for increasing L1 validator balance.
  * Validator manager details (`BlockchainID` and `ContractAddress`).

**New block properties:**

* P-Chain blocks now include:
  * `ActiveL1Validators` (total active L1 validators).
  * `L1ValidatorsAccruedFees` (fees from active L1 validators).

**New subnet properties:**

* Subnet details now have:
  * `IsL1` to indicate if a subnet has been converted to an L1.
  * Validator manager details for L1 subnets.

These changes support seamless management and visibility of L1 validators introduced in the Etna upgrade. For more details, see [here](/data-api/etna)

***

### Oct 25th, 2024

**Data API new endpoint - Listing networks an address has interacted with**

Returns a list of all networks on which an EVM address has had activity, filtering out networks with no activity for the provided address.

Endpoint: `GET https://glacier-api.avax.network/v1/chains/address/{address}`

[Gets the list of chains an address has interacted with](/data-api/evm-chains/get-chains-for-address).

Example response:

```json
{
  "indexedChains": [
    {
      "chainId": "43114",
      "status": "OK",
      "chainName": "Avalanche (C-Chain)",
      "description": "The Contract Chain (C-Chain) runs on an Ethereum Virtual Machine and is used to deploy smart contracts and connect to dApps.",
      "platformChainId": "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5",
      "subnetId": "11111111111111111111111111111111LpoYY",
      "vmId": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6",
      "vmName": "EVM",
      "explorerUrl": "https://subnets.avax.network/c-chain",
      "rpcUrl": "https://api.avax.network/ext/bc/C/rpc",
      "wsUrl": "wss://api.avax.network/ext/bc/C/ws",
      "isTestnet": false,
      "utilityAddresses": {
        "multicall": "0xed386Fe855C1EFf2f843B910923Dd8846E45C5A4"
      },
      "networkToken": {
        "name": "Avalanche",
        "symbol": "AVAX",
        "decimals": 18,
        "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg",
        "description": "AVAX is the native utility token of Avalanche. It’s a hard-capped, scarce asset that is used to pay for fees, secure the platform through staking, and provide a basic unit of account between the multiple Subnets created on Avalanche."
      },
      "chainLogoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg",
      "private": false,
      "enabledFeatures": [
        "nftIndexing",
        "webhooks",
        "teleporter"
      ]
    },
    {
      "chainId": "43113",
      "status": "OK",
      "chainName": "Avalanche (C-Chain)",
      "description": "The Contract Chain on Avalanche's test subnet.",
      "platformChainId": "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp",
      "subnetId": "11111111111111111111111111111111LpoYY",
      "vmId": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6",
      "vmName": "EVM",
      "explorerUrl": "https://subnets-test.avax.network/c-chain",
      "rpcUrl": "https://api.avax-test.network/ext/bc/C/rpc",
      "wsUrl": "wss://api.avax-test.network/ext/bc/C/ws",
      "isTestnet": true,
      "utilityAddresses": {
        "multicall": "0xE898101ffEF388A8DA16205249a7E4977d4F034c"
      },
      "networkToken": {
        "name": "Avalanche",
        "symbol": "AVAX",
        "decimals": 18,
        "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg",
        "description": "AVAX is the native utility token of Avalanche. It’s a hard-capped, scarce asset that is used to pay for fees, secure the platform through staking, and provide a basic unit of account between the multiple Subnets created on Avalanche."
      },
      "chainLogoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg",
      "private": false,
      "enabledFeatures": [
        "nftIndexing",
        "webhooks",
        "teleporter"
      ]
    },
    {
      "chainId": "779672",
      "status": "OK",
      "chainName": "Dispatch L1",
      "description": "Environment for testing Avalanche Warp Messaging and Teleporter.",
      "platformChainId": "2D8RG4UpSXbPbvPCAWppNJyqTG2i2CAXSkTgmTBBvs7GKNZjsY",
      "subnetId": "7WtoAMPhrmh5KosDUsFL9yTcvw7YSxiKHPpdfs4JsgW47oZT5",
      "vmId": "mDtV8ES8wRL1j2m6Kvc1qRFAvnpq4kufhueAY1bwbzVhk336o",
      "vmName": "EVM",
      "explorerUrl": "https://subnets-test.avax.network/dispatch",
      "rpcUrl": "https://subnets.avax.network/dispatch/testnet/rpc",
      "isTestnet": true,
      "utilityAddresses": {
        "multicall": "0xb35f163b70AbABeE69cDF40bCDA94df2c37d9df8"
      },
      "networkToken": {
        "name": "DIS",
        "symbol": "DIS",
        "decimals": 18,
        "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/60XrKdf99PqQKrHiuYdwTE/908622f5204311dbb11be9c6008ead44/Dispatch_Subnet_Logo.png",
        "description": ""
      },
      "chainLogoUri": "https://images.ctfassets.net/gcj8jwzm6086/60XrKdf99PqQKrHiuYdwTE/908622f5204311dbb11be9c6008ead44/Dispatch_Subnet_Logo.png",
      "private": false,
      "enabledFeatures": [
        "teleporter"
      ]
    },
    {
      "chainId": "173750",
      "status": "OK",
      "chainName": "Echo L1",
      "description": "Environment for testing Avalanche Warp Messaging and Teleporter.",
      "platformChainId": "98qnjenm7MBd8G2cPZoRvZrgJC33JGSAAKghsQ6eojbLCeRNp",
      "subnetId": "i9gFpZQHPLcGfZaQLiwFAStddQD7iTKBpFfurPFJsXm1CkTZK",
      "vmId": "meq3bv7qCMZZ69L8xZRLwyKnWp6chRwyscq8VPtHWignRQVVF",
      "vmName": "EVM",
      "explorerUrl": "https://subnets-test.avax.network/echo",
      "rpcUrl": "https://subnets.avax.network/echo/testnet/rpc",
      "isTestnet": true,
      "utilityAddresses": {
        "multicall": "0x0E3a5F409eF471809cc67311674DDF7572415682"
      },
      "networkToken": {
        "name": "ECH",
        "symbol": "ECH",
        "decimals": 18,
        "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/7kyTY75fdtnO6mh7f0osix/4c92c93dd688082bfbb43d5d910cbfeb/Echo_Subnet_Logo.png",
        "description": ""
      },
      "chainLogoUri": "https://images.ctfassets.net/gcj8jwzm6086/7kyTY75fdtnO6mh7f0osix/4c92c93dd688082bfbb43d5d910cbfeb/Echo_Subnet_Logo.png",
      "private": false,
      "enabledFeatures": [
        "teleporter"
      ]
    }
  ],
  "unindexedChains": []
}
```

***

### Sep 12th, 2024

**Data API new endpoint - List teleporter messages by address**

Endpoint: `GET https://glacier-api.avax.network/v1/teleporter/addresses/{address}/messages`

[Lists teleporter messages by address](/data-api/teleporter/list-teleporter-messages-address). Ordered by timestamp in descending order.

Example response:

```json
{
    "messages": [{
        "messageId": "25e7bcf7304516a24f5ee597048ada3680dfa3264b27722b46b399da2180dea6",
        "teleporterContractAddress": "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf",
        "sourceBlockchainId": "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5",
        "destinationBlockchainId": "75babf9b4db10c46cd1c4cc28e199cc4acf4c64f78327ff6cda26b8785a7bb5d",
        "sourceEvmChainId": "43114",
        "destinationEvmChainId": "",
        "messageNonce": "29",
        "from": "0x573e623caCfDe4427C460Fc408aDD5AB21220FD7",
        "to": "0xB324bf38e6aFf06670EF649077062A7563b87fC5",
        "data": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006626f6272696b0000000000000000000000000000000000000000000000000000",
        "messageExecuted": false,
        "receipts": [],
        "receiptDelivered": false,
        "rewardDetails": {
            "value": "0",
            "address": "0x0000000000000000000000000000000000000000",
            "ercType": "ERC-20",
            "name": "",
            "symbol": "",
            "decimals": 0
        },
        "status": "pending",
        "sourceTransaction": {
            "txHash": "0x7f5258b78964bc0f7b7abd1b3b99fb8665acb3d67e5ebe8fdf1b9e6ae6402b2a",
            "timestamp": 1722571442,
            "gasSpent": "3338675000000000"
        }
    }, {
        "messageId": "2c56bfe4c816ca2d8241bf7a76ade09cb1cc9ab52dbc7b774184ad7cc9fba2a8",
        "teleporterContractAddress": "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf",
        "sourceBlockchainId": "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5",
        "destinationBlockchainId": "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5",
        "sourceEvmChainId": "43114",
        "destinationEvmChainId": "43114",
        "messageNonce": "28",
        "from": "0x573e623caCfDe4427C460Fc408aDD5AB21220FD7",
        "to": "0xB324bf38e6aFf06670EF649077062A7563b87fC5",
        "data": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006626f6272696b0000000000000000000000000000000000000000000000000000",
        "messageExecuted": false,
        "receipts": [],
        "receiptDelivered": false,
        "rewardDetails": {
            "value": "0",
            "address": "0x0000000000000000000000000000000000000000",
            "ercType": "ERC-20",
            "name": "",
            "symbol": "",
            "decimals": 0
        },
        "status": "pending",
        "sourceTransaction": {
            "txHash": "0xee1b6a56dca07cc35d01a912d0e80b1124f8986b1d375534ef651a822798e509",
            "timestamp": 1722570309,
            "gasSpent": "3338675000000000"
        }
    }]
}
```

***

### August 6th, 2024

**Data API new endpoint- Get L1 details by `subnetID`**

Endpoint: `GET https://glacier-api.avax.network/v1/networks/{network}/subnets/{subnetId}`

This endpoint retrieves detailed information about a specific L1/subnet registered on the network. By providing the network type (mainnet or a testnet) and the L1 ID, you can fetch various details including the subnet’s creation timestamp, ownership information, and associated blockchains.

Example response:

```JSON
{
  "createBlockTimestamp": 1599696000,
  "createBlockIndex": "-1",
  "subnetId": "11111111111111111111111111111111LpoYY",
  "ownerAddresses": [
    ""
  ],
  "threshold": 0,
  "locktime": 0,
  "subnetOwnershipInfo": {
    "addresses": [
      "0"
    ],
    "locktime": 0,
    "threshold": null
  },
  "blockchains": [
    {
      "blockchainId": "11111111111111111111111111111111LpoYY"
    },
    {
      "blockchainId": "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM"
    },
    {
      "blockchainId": "2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5"
    }
  ]
}
```

***

### May 21st, 2024

**Filter spam tokens and new endpoints for the primary network**

The following improvements have been made to the Glacier API:

* **EVM** <br />
  Remove Spam Tokens from Balances Endpoint

  Users can now pass in an optional query parameter `filterSpamTokens` when getting balances for a particular address to filter out balances of tokens that we've determined to be spam. By default, the route will now filter spam tokens unless `filterSpamTokens=false`.
  Try it out [here](/data-api/evm-balances/list-erc-20-balances)!

* **Primary Network** <br />
  In the [List Validators](/data-api/primary-network/list-validators) endpoint, users can now sort validators by Block Index, Delegation Capacity, Time Remaining, Delegation Fee, or Uptime Performance.

  Users can also filter by validator uptime performance using `minUptimePerformance` and `maxUptimePerformance` and by fee percentage using `minFeePercentage` and \`maxFeePercentage.

* **Webhooks** <br />
  A new [API endpoint](/webhooks-api/webhooks/list-adresses-by-webhook) has been added to enable users to list all addresses associated with a webhook.

***

### Aug  20th, 2024

**Webhook service launched**

With Glacier Webhooks, you can monitor real-time events on the Avalanche C-chain and L1s. For example, you can monitor smart contract events, track NFT transfers, and observe wallet-to-wallet transactions.

![webhooks](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/webhooks.png)

**Key Features:** <br />

* **Real-time notifications**: Receive immediate updates on specified on-chain activities without polling.
* **Customizable**: Specify the desired event type to listen for, customizing notifications according to individual requirements.
* **Secure**: Employ shared secrets and signature-based verification to guarantee that notifications originate from a trusted source.
* **Broad Coverage**: Support for C-chain mainnet, testnet, and L1s within the Avalanche ecosystem, ensuring wide-ranging monitoring capabilities.

**Use cases** <br />

* **NFT Marketplace Transactions**: Get alerts for NFT minting, transfers, auctions, bids, sales, and other interactions within NFT marketplaces.
* **Wallet Notifications**: Receive alerts when an address performs actions such as sending, receiving, swapping, or burning assets.
* **DeFi Activities**: Receive notifications for various DeFi activities such as liquidity provisioning, yield farming, borrowing, lending, and liquidations.

For further details, visit our:

* [Overview](/webhooks-api/overview)
* [Getting Started](/webhooks-api/getting-started)


# How to get all transactions of an address
Source: https://developers.avacloud.io/data-api/address-transactions



This guide will walk you through how to retrieve all transactions associated with a specific wallet address on the C-chain network using the Data API.

### Step 1: Setup your account

First, ensure that you have set up [AvaCloud](https://app.avacloud.io/) and have access to your API key. If you’re new to Avacloud, create an account and obtain an API key.

### Step 2: Get All Transactions for an Address

To get all transactions for a specific address you can use [list transactions](/data-api/evm-transactions/list-transactions) endpoint. You’ll need to specify the `chainId` and the `address` for which you want to retrieve the transactions.

Here’s how you can do it:

<CodeGroup>
  ```javascript AvacloudSDK
  import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

  const avaCloudSDK = new AvaCloudSDK({
    glacierApiKey: "<YOUR_API_KEY>",
    chainId: "43114",
    network: "mainnet",
  });

  async function run() {
    const result = await avaCloudSDK.data.evm.transactions.listTransactions({
      pageSize: 10,
      address: "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      sortOrder: "asc",
    });

    console.log(JSON.stringify(result, null, 2));

  }

  run();
  ```

  ```bash cURL
  curl --request GET \
    --url https://glacier-api.avax.network/v1/chains/43114/addresses/0x71C7656EC7ab88b098defB751B7401B5f6d8976F/transactions \
    --header 'x-glacier-api-key: <api-key>'
  ```
</CodeGroup>

### Step 3: Run the script

Once you’ve copied the code into your preferred developer tool, you can run it using the following commands:

```bash
node index.js
```

After running the script, you should see a JSON response similar to this in your terminal:

```json
{
  "transactions": [
    {
      "nativeTransaction": {
        "blockNumber": "43281797",
        "blockIndex": 3,
        "blockHash": "0x85ad9ece9c384554f100318c7d88834ebacf5c9dd970d1406297eb4c90ee850f",
        "txHash": "0x4dde404e7ac7fb9eb10ab780fba9715ef07105312aa3a6367cfc2322cbd352fe",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "92394",
        "gasUsed": "61126",
        "gasPrice": "26500000000",
        "nonce": "16",
        "blockTimestamp": 1711218299,
        "from": {
          "address": "0x5AEdcCaeCA2cb3f87a90713c83872f7515e19c90"
        },
        "to": {
          "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
          "name": "TetherToken",
          "symbol": "USDT",
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/4ac7cb0c-5260-473b-a4bc-b809801aa5da/49d45340a82166bdb26fce4d3e62ce65/43114-0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7.png"
        },
        "method": {
          "callType": "CONTRACT_CALL",
          "methodHash": "0xa9059cbb"
        },
        "value": "0"
      },
      "erc20Transfers": [
        {
          "from": {
            "address": "0x5AEdcCaeCA2cb3f87a90713c83872f7515e19c90"
          },
          "to": {
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "logIndex": 10,
          "value": "400000",
          "erc20Token": {
            "ercType": "ERC-20",
            "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
            "name": "TetherToken",
            "symbol": "USDT",
            "decimals": 6,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/4ac7cb0c-5260-473b-a4bc-b809801aa5da/49d45340a82166bdb26fce4d3e62ce65/43114-0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7.png",
            "price": {
              "value": 0.999436,
              "currencyCode": "usd"
            }
          }
        }
      ]
    },
    {
      "nativeTransaction": {
        "blockNumber": "26002777",
        "blockIndex": 0,
        "blockHash": "0x83c8d5bb1b885d1efaf116da6a9d776088d19c9fdfd06a71d16156c80b339261",
        "txHash": "0xc96e00ce365f2fae67f940985fc8b9af97a051f5bf0f29c891205ca1ae3287d4",
        "txStatus": "1",
        "txType": 0,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "27500000000",
        "nonce": "11",
        "blockTimestamp": 1675878866,
        "from": {
          "address": "0x444782F140e31B5687d166FA077C3049062911Ba"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "3005020000000000"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "25037477",
        "blockIndex": 6,
        "blockHash": "0x048a00b6e40ffdb2b3a4b596cfa6ee2e4479c53099f23afed3145569d2cbfb02",
        "txHash": "0x4c29443c0d8f08d2be1cc6c20bc7a1a05211b91340550edf26d0bd9196c593a3",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "31500",
        "gasUsed": "21000",
        "gasPrice": "26500000000",
        "nonce": "2590",
        "blockTimestamp": 1673917315,
        "from": {
          "address": "0x1C42F2fCc9c7F4a30dC15ACf9C047DDeCF39de06"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "150000000000000000"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "23826282",
        "blockIndex": 0,
        "blockHash": "0x96caae2487206cba32000e49e2f593406981fcf26cffd646da92661ce907fc62",
        "txHash": "0x7aaa1beff9466f8e099b8a25e37b1f748b2623856f65cd479bd721e983ee84ac",
        "txStatus": "1",
        "txType": 0,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "31250000000",
        "nonce": "0",
        "blockTimestamp": 1671433238,
        "from": {
          "address": "0x6B69f15BCEeB1a2326De003ca97b1F61AE57b774"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "57557140067572377"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "23249650",
        "blockIndex": 4,
        "blockHash": "0xf0161747357482ce078d398f55e9413ce4a4e21611b20f5488b74e4d181536bd",
        "txHash": "0x760ac8c147a9ec795a7695f3c3383408890f53fc23e39f43f938f513910a9612",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "26843560317",
        "nonce": "9",
        "blockTimestamp": 1670254442,
        "from": {
          "address": "0xcd661208b0138A9468D5B6E3E119215e5aA14c15"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "9942019140711807"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "21989662",
        "blockIndex": 8,
        "blockHash": "0x9eefeb39b435c625cf659674df2a0d56b85b2efffb677edd8a4365d7fc39dd68",
        "txHash": "0x0e1f96c84ddc07d74a19ee748381048e1876bf8a706e5e8f917897f6761eef51",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "2146729",
        "gasUsed": "1431153",
        "gasPrice": "26000000000",
        "nonce": "4",
        "blockTimestamp": 1667660826,
        "from": {
          "address": "0x55906a1d87f7426497fDBa498B8F5edB1C741cef"
        },
        "to": {
          "address": "0xF9d922c055A3f1759299467dAfaFdf43BE844f7a"
        },
        "method": {
          "callType": "CONTRACT_CALL",
          "methodHash": "0x74a72e41"
        },
        "value": "0"
      },
      "erc20Transfers": [
        {
          "from": {
            "address": "0xF9d922c055A3f1759299467dAfaFdf43BE844f7a"
          },
          "to": {
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "logIndex": 33,
          "value": "30000000000000",
          "erc20Token": {
            "ercType": "ERC-20",
            "address": "0xF9d922c055A3f1759299467dAfaFdf43BE844f7a",
            "name": "Minereum AVAX",
            "symbol": "MNEAV",
            "decimals": 8
          }
        }
      ]
    },
    {
      "nativeTransaction": {
        "blockNumber": "17768295",
        "blockIndex": 3,
        "blockHash": "0x55f934b32644b9c6d53283ac9275747929779e38ad0687d9c8e895a8699986b2",
        "txHash": "0x8138fea77335fd208ec7618a67fdd3a104577e8e89a6d0665407202163ff9d07",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "77829",
        "gasUsed": "51886",
        "gasPrice": "26500000000",
        "nonce": "6",
        "blockTimestamp": 1658716784,
        "from": {
          "address": "0x7e31af176DA39a9986c8f5c7632178B4AcF0c868"
        },
        "to": {
          "address": "0x4cb70De91e6Bb85fB132880D5Af3418477a90083"
        },
        "method": {
          "callType": "CONTRACT_CALL",
          "methodHash": "0xa9059cbb"
        },
        "value": "0"
      },
      "erc20Transfers": [
        {
          "from": {
            "address": "0x7e31af176DA39a9986c8f5c7632178B4AcF0c868"
          },
          "to": {
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "logIndex": 6,
          "value": "50000000000000000",
          "erc20Token": {
            "ercType": "ERC-20",
            "address": "0x4cb70De91e6Bb85fB132880D5Af3418477a90083",
            "name": "Woodcut Token",
            "symbol": "WOOD",
            "decimals": 18
          }
        }
      ]
    },
    {
      "nativeTransaction": {
        "blockNumber": "17328312",
        "blockIndex": 0,
        "blockHash": "0x96c1554115937f2ea11efac5d08c9a844925dace3ff4b62679fd3183fc8c8aa9",
        "txHash": "0xdcc0cf0982aed703d72da1fefd686e97fa549bd3717972a547440a3abc384bfb",
        "txStatus": "1",
        "txType": 0,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "30000000000",
        "nonce": "3",
        "blockTimestamp": 1657827243,
        "from": {
          "address": "0x6ae30413ddA067f8BB2D904d630081784f4c2a3E"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "3694737000000000"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "13923067",
        "blockIndex": 17,
        "blockHash": "0x22c7369d613a8ee600fa8dd0a178c575139150d18d04220633cc682465774536",
        "txHash": "0x9a8822afb1f082f1250ac1876223384fac8370f9dd1f785ce54c3acbcaf7341a",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "72048389636",
        "nonce": "1",
        "blockTimestamp": 1650975303,
        "from": {
          "address": "0xffc83E3777DB33ff4af4A3fB72056fF3bDF02e47"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "31240000000000000"
      }
    },
    {
      "nativeTransaction": {
        "blockNumber": "13922287",
        "blockIndex": 19,
        "blockHash": "0x42c6a341b8d5794b83026cd1aa63606cbeb917b2e58a017b48c8d24b69fe788c",
        "txHash": "0x12681543ad3f41cb2146f959528fbedea3250afbed14f152cf0ec87bce4c69c2",
        "txStatus": "1",
        "txType": 2,
        "gasLimit": "21000",
        "gasUsed": "21000",
        "gasPrice": "69081184341",
        "nonce": "9",
        "blockTimestamp": 1650973723,
        "from": {
          "address": "0xB30228A0FfB21f68a144Dd4f3af703ce975Cf490"
        },
        "to": {
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "method": {
          "callType": "NATIVE_TRANSFER",
          "methodHash": "",
          "methodName": "Native Transfer"
        },
        "value": "33305869282988272"
      }
    }
  ],
  "nextPageToken": "5b7c89d0-1f1b-45d1-a539-57b8e70d034f"
}
```

Congratulations 🎉  You’ve successfully retrieved all transactions for a wallet address on the C-chain using the Data API! With just a few lines of code, you can now access this data easily and integrate it into your projects.


# Get logs for requests made by client
Source: https://developers.avacloud.io/data-api/data-api-usage-metrics/get-logs-for-requests-made-by-client

get /v1/apiLogs
Gets logs for requests made by client over a specified time interval for a specific organization.



# Get usage metrics for the Data API
Source: https://developers.avacloud.io/data-api/data-api-usage-metrics/get-usage-metrics-for-the-data-api

get /v1/apiUsageMetrics
Gets metrics for Data API usage over a specified time interval aggregated at the specified time-duration granularity.



# null
Source: https://developers.avacloud.io/data-api/data-api-usage-metrics/get-usage-metrics-for-the-rpc

get /v1/rpcUsageMetrics
**[Deprecated]**  Gets metrics for public Subnet RPC usage over a specified time interval aggregated at the specified time-duration granularity.

⚠️ **This operation will be removed in a future release.  Please use /v1/subnetRpcUsageMetrics endpoint instead**.



# Get usage metrics for the Subnet RPC
Source: https://developers.avacloud.io/data-api/data-api-usage-metrics/get-usage-metrics-for-the-subnet-rpc

get /v1/subnetRpcUsageMetrics
Gets metrics for public Subnet RPC usage over a specified time interval aggregated at the specified time-duration granularity.



# Data API vs RPC
Source: https://developers.avacloud.io/data-api/data-api-vs-rpc



In the rapidly evolving world of Web3 development, efficiently retrieving token balances for a user's address is a fundamental requirement. Whether you're building DeFi platforms, wallets, analytics tools, or exchanges, displaying accurate token balances is crucial for user engagement and trust. A typical use case involves showing a user's token portfolio in a wallet application, in this case, we have sAvax and USDC.

![title](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/wallet.png)

Developers generally have two options to fetch this data:

1. **Using RPC methods to index blockchain data on their own**
2. **Leveraging an indexer provider like the Data API**

While both methods aim to achieve the same goal, the Data API offers a more efficient, scalable, and developer-friendly solution. This article delves into why using the Data API is better than relying on traditional RPC (Remote Procedure Call) methods.

### What Are RPC methods and their challenges?

Remote Procedure Call (RPC) methods allow developers to interact directly with blockchain nodes. One of their key advantages is that they are standardized and universally understood by blockchain developers across different platforms. With RPC, you can perform tasks such as querying data, submitting transactions, and interacting with smart contracts. These methods are typically low-level and synchronous, meaning they require a deep understanding of the blockchain’s architecture and specific command structures.
You can refer to the [official documentation](https://ethereum.org/en/developers/docs/apis/json-rpc/) to gain a more comprehensive understanding of the JSON-RPC API.

Here’s an example using the `eth_getBalance` method to retrieve the native balance of a wallet:

```bash
curl --location 'https://api.avax.network/ext/bc/C/rpc' \
--header 'Content-Type: application/json' \
--data '{"method":"eth_getBalance","params":["0x8ae323046633A07FB162043f28Cea39FFc23B50A", "latest"],"id":1,"jsonrpc":"2.0"}'
```

This call returns the following response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x284476254bc5d594"
}
```

The balance in this wallet is 2.9016 AVAX. However, despite the wallet holding multiple tokens such as USDC, the `eth_getBalance` method only returns the AVAX amount and it does so in Wei and in hexadecimal format. This is not particularly human-readable, adding to the challenge for developers who need to manually convert the balance to a more understandable format.

#### No direct RPC methods to retrieve token balances

Despite their utility, RPC methods come with significant limitations when it comes to retrieving detailed token and transaction data. Currently, RPC methods do not provide direct solutions for the following:

* **Listing all tokens held by a wallet**: There is no RPC method that provides a complete list of ERC-20 tokens owned by a wallet.
* **Retrieving all transactions for a wallet**: : There is no direct method for fetching all transactions associated with a wallet.
* **Getting ERC-20/721/1155 token balances**:  The `eth_getBalance` method only returns the balance of the wallet’s native token (such as AVAX on Avalanche) and cannot be used to retrieve ERC-20/721/1155 token balances.

To achieve these tasks using RPC methods alone, you would need to:

* **Query every block for transaction logs**: Scan the entire blockchain, which is resource-intensive and impractical.
* **Parse transaction logs**: Identify and extract ERC-20 token transfer events from each transaction.
* **Aggregate data**: Collect and process this data to compute balances and transaction histories.

#### Manual blockchain indexing is difficult and costly

Using RPC methods to fetch token balances involves an arduous process:

1. You must connect to a node and subscribe to new block events.
2. For each block, parse every transaction to identify ERC-20 token transfers involving the user's address.
3. Extract contract addresses and other relevant data from the parsed transactions.
4. Compute balances by processing transfer events.
5. Store the processed data in a database for quick retrieval and aggregation.

#### Why this is difficult:

* **Resource-Intensive**: Requires significant computational power and storage to process and store blockchain data.
* **Time-consuming**: Processing millions of blocks and transactions can take an enormous amount of time.
* **Complexity**: Handling edge cases like contract upgrades, proxy contracts, and non-standard implementations adds layers of complexity.
* **Maintenance**: Keeping the indexed data up-to-date necessitates continuous synchronization with new blocks being added to the blockchain.
* **High Costs**: Associated with servers, databases, and network bandwidth.

### The Data API Advantage

The Data API provides a streamlined, efficient, and scalable solution for fetching token balances. Here's why it's the best choice:
With a single API call, you can retrieve all ERC-20 token balances for a user's address:

```javascript
avaCloudSDK.data.evm.balances.listErc20Balances({
    address: "0xYourAddress"
});
```

Sample Response:

```json
{
  "erc20TokenBalances": [
    {
      "ercType": "ERC-20",
      "chainId": "43114",
      "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
      "name": "USD Coin",
      "symbol": "USDC",
      "decimals": 6,
      "price": {
        "value": 1.00,
        "currencyCode": "usd"
      },
      "balance": "15000000",
      "balanceValue": {
        "currencyCode": "usd",
        "value": 9.6
      },
      "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/e50058c1-2296-4e7e-91ea-83eb03db95ee/8db2a492ce64564c96de87c05a3756fd/43114-0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E.png"
    },
    // Additional tokens...
  ]
}
```

As you can see with a single call the API returns an array of token balances for all the wallet tokens, including:

* **Token metadata**: Contract address, name, symbol, decimals.
* **Balance information**: Token balance in both hexadecimal and decimal formats, Also retrieves balances of native assets like ETH or AVAX.
* **Price data**: Current value in USD or other supported currencies, saving you the effort of integrating another API.
* **Visual assets**: Token logo URI for better user interface integration.

If you’re building a wallet, DeFi app, or any application that requires displaying balances, transaction history, or smart contract interactions, relying solely on RPC methods can be challenging. Just as there’s no direct RPC method to retrieve token balances, there’s also no simple way to fetch all transactions associated with a wallet, especially for ERC-20, ERC-721, or ERC-1155 token transfers.

However, by using the Data API, you can retrieve all token transfers for a given wallet **with a single API call**, making the process much more efficient. This approach simplifies tracking and displaying wallet activity without the need to manually scan the entire blockchain.

Below are two examples that demonstrate the power of the Data API: in the first, it returns all ERC transfers, including ERC-20, ERC-721, and ERC-1155 tokens, and in the second, it shows all internal transactions, such as when one contract interacts with another.

<AccordionGroup>
  <Accordion title="List ERC transfers">
    [Lists ERC transfers](/data-api/evm-transactions/list-erc-transfers) for an ERC-20, ERC-721, or ERC-1155 contract address.

    ```javascript
    import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

    const avaCloudSDK = new AvaCloudSDK({
      apiKey: "<YOUR_API_KEY_HERE>",
      chainId: "43114",
      network: "mainnet",
    });

    async function run() {
      const result = await avaCloudSDK.data.evm.transactions.listTransfers({
        startBlock: 6479329,
        endBlock: 6479330,
        pageSize: 10,
        address: "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      });

      for await (const page of result) {
        // Handle the page
        console.log(page);
      }
    }

    run();
    ```

    Example response

    ```json
    {
      "nextPageToken": "<string>",
      "transfers": [
        {
          "blockNumber": "339",
          "blockTimestamp": 1648672486,
          "blockHash": "0x17533aeb5193378b9ff441d61728e7a2ebaf10f61fd5310759451627dfca2e7c",
          "txHash": "0x3e9303f81be00b4af28515dab7b914bf3dbff209ea10e7071fa24d4af0a112d4",
          "from": {
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg",
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "to": {
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg",
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "logIndex": 123,
          "value": "10000000000000000000",
          "erc20Token": {
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg",
            "ercType": "ERC-20",
            "price": {
              "currencyCode": "usd",
              "value": "42.42"
            }
          }
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="List internal transactions">
    [Returns a list of internal transactions](/data-api/evm-transactions/list-internal-transactions) for an address and chain. Filterable by block range.

    ```javascript
    import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

    const avaCloudSDK = new AvaCloudSDK({
      apiKey: "<YOUR_API_KEY_HERE>",
      chainId: "43114",
      network: "mainnet",
    });

    async function run() {
      const result = await avaCloudSDK.data.evm.transactions.listInternalTransactions({
        startBlock: 6479329,
        endBlock: 6479330,
        pageSize: 10,
        address: "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      });

      for await (const page of result) {
        // Handle the page
        console.log(page);
      }
    }

    run();
    ```

    Example response

    ```json
    {
      "nextPageToken": "<string>",
      "transactions": [
        {
          "blockNumber": "339",
          "blockTimestamp": 1648672486,
          "blockHash": "0x17533aeb5193378b9ff441d61728e7a2ebaf10f61fd5310759451627dfca2e7c",
          "txHash": "0x3e9303f81be00b4af28515dab7b914bf3dbff209ea10e7071fa24d4af0a112d4",
          "from": {
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg",
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "to": {
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg",
            "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "internalTxType": "UNKNOWN",
          "value": "10000000000000000000",
          "isReverted": true,
          "gasUsed": "<string>",
          "gasLimit": "<string>"
        }
      ]
    }
    ```
  </Accordion>
</AccordionGroup>

### Conclusion

Using the Data API over traditional RPC methods for fetching token balances offers significant advantages:

* **Efficiency**: Retrieve all necessary information in a single API call.
* **Simplicity**: Eliminates complex data processing and reduces development time.
* **Scalability**: Handles large volumes of data efficiently, suitable for real-time applications.
* **Comprehensive Data**: Provides enriched information, including token prices and logos.
* **Reliability**: Ensures data accuracy and consistency without the need for extensive error handling.
  For developers building Web3 applications, leveraging the Data API is the smarter choice. It not only simplifies your codebase but also enhances the user experience by providing accurate and timely data.

If you’re building cutting-edge Web3 applications, this API is the key to improving your workflow and performance. Whether you’re developing DeFi solutions, wallets, or analytics platforms, take your project to the next level. [Start today with the Data API](/data-api/getting-started) and experience the difference!


# How to get all ERC20 transfers by wallet
Source: https://developers.avacloud.io/data-api/erc20-transfers



This guide will walk you through the process of listing all ERC-20 transfers associated with a specific wallet address on the DFK L1 network using the Data API.

### Step 1: Set Up AvaCloud

First, ensure that you have set up [AvaCloud](https://app.avacloud.io/) and have access to your API key. If you’re new to Avacloud, create an account and obtain an API key.

### Step 2: Retrieve the Native Balance of an Address

To obtain a list of ERC-20 transfers you can use the [List ERC-20 transfers](/data-api/evm-transactions/list-erc-20-transfers) endpoint. You’ll need to specify the `chainId` and the `address` for which you want to retrieve the balance.

Here’s how you can do it:

<CodeGroup>
  ```javascript AvacloudSDK
  import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

  const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "53935",
    network: "mainnet",
  });

  async function run() {
    const result = await avaCloudSDK.data.evm.transactions.listErc20Transactions({
      pageSize: 10,
      address: "0x1137643FE14b032966a59Acd68EBf3c1271Df316",
    });

    // Handle the result
    console.log(JSON.stringify(result, null, 2));
  }

  run();
  ```

  ```bash cURL
  curl --request GET \
    --url https://glacier-api.avax.network/v1/chains/43114/addresses/0x71C7656EC7ab88b098defB751B7401B5f6d8976F/transactions:listErc20 \
    --header 'x-glacier-api-key: <api-key>'
  ```
</CodeGroup>

Response

```json
{
  "result": {
    "nextPageToken": "f8dba2d2-b128-41ae-be6b-5a6f76ca5141",
    "transactions": [
      {
        "blockNumber": "36952303",
        "blockTimestamp": 1725460283,
        "blockHash": "0xb18c21736207b15efa0bdc1377c9ffde8c95bd20bd8b7422cc5eaefad41375a6",
        "txHash": "0x5d88c29e5d10d60a56f98d44883b6f8a82461dfe4c7b15e4c5726d626c41a484",
        "from": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "to": {
          "address": "0x6ef29103747EdFA66bcb3237D5AE4f773a5B9beE"
        },
        "logIndex": 21,
        "value": "16800000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952300",
        "blockTimestamp": 1725460277,
        "blockHash": "0xf0c3017e0428ae2442fb0162d5ed0bd3c735ab25b5e85e94b0fe3cb97a914ede",
        "txHash": "0xea4aa8e2fa0b78aaf624252b762a32bcf5361ce441a7bc464edfd0bae3302a0e",
        "from": {
          "address": "0x3f04bAD8c90984e16e51656270f82D6C3B73a571"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 83,
        "value": "1350000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952297",
        "blockTimestamp": 1725460271,
        "blockHash": "0x1e9a118d60b931b7968c9bb5fbf615cecf14a1e0c15ab0ee4bdbca69150ef3f9",
        "txHash": "0x21fcc2430fe3d437bbb3147a877552a94a33bd02d29eb23731f26b80674fd78c",
        "from": {
          "address": "0x3f04bAD8c90984e16e51656270f82D6C3B73a571"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 197,
        "value": "1350000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952297",
        "blockTimestamp": 1725460271,
        "blockHash": "0x1e9a118d60b931b7968c9bb5fbf615cecf14a1e0c15ab0ee4bdbca69150ef3f9",
        "txHash": "0x5ec8a1e8ad42e2190633da46c69529ecf4d8c6c85d9df74db641e6f2a8a5e383",
        "from": {
          "address": "0x3f04bAD8c90984e16e51656270f82D6C3B73a571"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 183,
        "value": "1350000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952297",
        "blockTimestamp": 1725460271,
        "blockHash": "0x1e9a118d60b931b7968c9bb5fbf615cecf14a1e0c15ab0ee4bdbca69150ef3f9",
        "txHash": "0x643b4c239820667452fd5c38d2f1f980cbbb8ccd120682e76b21fcd742d43cb3",
        "from": {
          "address": "0x3f04bAD8c90984e16e51656270f82D6C3B73a571"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 167,
        "value": "1350000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952294",
        "blockTimestamp": 1725460263,
        "blockHash": "0xa15acd24ce980ce5ffcf12daf6ce538fd4f9896634b4a3f48c599c77192577cf",
        "txHash": "0x370627ddb71c638305a8cce92ecae69423115668039902f83aa4fd3a25983ee0",
        "from": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "to": {
          "address": "0x6ef29103747EdFA66bcb3237D5AE4f773a5B9beE"
        },
        "logIndex": 246,
        "value": "18000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952294",
        "blockTimestamp": 1725460263,
        "blockHash": "0xa15acd24ce980ce5ffcf12daf6ce538fd4f9896634b4a3f48c599c77192577cf",
        "txHash": "0xe8b58b9a413de06d4dbfebc226e3607f34a5071e7a0a315478a37d5ad76a7026",
        "from": {
          "address": "0xC475ecce788ECBF4b6E78BC501f4B1Ce73c46232"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 38,
        "value": "300000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952294",
        "blockTimestamp": 1725460263,
        "blockHash": "0xa15acd24ce980ce5ffcf12daf6ce538fd4f9896634b4a3f48c599c77192577cf",
        "txHash": "0xe8b58b9a413de06d4dbfebc226e3607f34a5071e7a0a315478a37d5ad76a7026",
        "from": {
          "address": "0xC475ecce788ECBF4b6E78BC501f4B1Ce73c46232"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 22,
        "value": "300000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952294",
        "blockTimestamp": 1725460263,
        "blockHash": "0xa15acd24ce980ce5ffcf12daf6ce538fd4f9896634b4a3f48c599c77192577cf",
        "txHash": "0xe8b58b9a413de06d4dbfebc226e3607f34a5071e7a0a315478a37d5ad76a7026",
        "from": {
          "address": "0xC475ecce788ECBF4b6E78BC501f4B1Ce73c46232"
        },
        "to": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "logIndex": 6,
        "value": "300000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      },
      {
        "blockNumber": "36952292",
        "blockTimestamp": 1725460259,
        "blockHash": "0x2b59f6314f27da325237afd457757cbd48302b7e292cc711f9b8d20cb5befea6",
        "txHash": "0xc6a98299de6cb14b8dccaeb9204fca3c93966f5a6da77d6dd799aa94e72f51ff",
        "from": {
          "address": "0x1137643FE14b032966a59Acd68EBf3c1271Df316"
        },
        "to": {
          "address": "0x063DEB90452247AEcE9Be5F6c076446b3ca01910"
        },
        "logIndex": 19,
        "value": "5000000000000000",
        "erc20Token": {
          "address": "0x04b9dA42306B023f3572e106B11D82aAd9D32EBb",
          "name": "Crystals",
          "symbol": "CRYSTAL",
          "decimals": 18,
          "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/0212db53-26f6-4e56-99a2-05526ce32816/4a62bf9e90f401ea69fcf89496cbe96a/53935-0x04b9dA42306B023f3572e106B11D82aAd9D32EBb.png",
          "ercType": "ERC-20",
          "price": {
            "currencyCode": "usd",
            "value": 0.00719546
          }
        }
      }
    ]
  }
}
```

Congratulations 🎉 You’ve successfully retrieved the list of ERC-20 transfers for a wallet address with just a few lines of code using the Data API!​


# Etna Upgrade
Source: https://developers.avacloud.io/data-api/etna



The **Avalanche9000 (Etna Upgrade)** is focused on reinventing Subnets and providing other UX enhancements. One of the major changes in this upgrade is how users manage subnets and their validators. See [ACP 77](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets).

## Pre-Etna vs. Post-Etna

### Pre-Etna

* A node had to be a **Primary Network Validator** before it could validate a Subnet.
* All validators, delegators, and rewards for permissionless subnets were managed on the **P-Chain**.

### Post-Etna:

The Avalanche network now supports both **Subnets** and **Layer 1 blockchains (L1s)**:

* **Subnets (legacy flow):**
  * Do not pay a continuous fee.
  * Validators must be Primary Network Validators.
* **L1s (new flow):**
  * Pay a continuous fee.
  * Validators do not need to be Primary Network Validators.
  * Can be either permissioned or permissionless, depending on the chain manager.

This shift moves the responsibility of validator management from the P-Chain to the Subnets themselves. Permissionless Subnets have been rebranded as **L1s**, reflecting their true potential as independent Layer 1 blockchains. The P-Chain now handles only the registration of these L1 validators and imposes a subscription fee based on the number of active validators for each L1.

Each L1 manages its validators through a [Validator Manager Smart Contract](https://github.com/ava-labs/teleporter/blob/main/contracts/validator-manager/README.md) deployed on a specific blockchain within that L1, streamlining operations and decentralizing management.

***

## Impact on existing subnets

Existing subnets will continue to operate under the legacy flow unless they choose to convert to an L1 using the `ConvertSubnetToL1Tx` transaction. Validators of these Subnets must remain Primary Network Validators. There is no mandatory action required for existing Subnets; however, they can opt to leverage the new L1 functionalities if desired.

***

## L1 validator registration

To convert a permissioned Subnet into an L1, you need to issue a `ConvertSubnetToL1Tx` transaction, providing the validator manager smart contract address and the blockchain ID where this contract is deployed. This transaction requires an array of initial L1 validators with the following details:

* `nodeID`:  NodeID of the validator being added.
* `weight`:  Weight of the validator being added.
* `balance`: Initial balance for this validator.
* `signer`: The BLS public key and proof-of-possession for the validator.
* `disableOwner`: The P-Chain owner (a set of addresses and threshold) authorized to disable the validator using DisableL1ValidatorTx..
* `remainingBalanceOwner`: The P-Chain owner where any leftover AVAX from the validator’s balance will be sent when the validator is removed from the validator set.

Additional L1 validators can be added later by issuing a `RegisterL1ValidatorTx` and providing the necessary validator details. These L1 validators are assigned a unique `validationID` to identify them across the network. The `validationID` remains valid from the registration of a `NodeID` on a Subnet until it is disabled by setting its weight to `0`.

***

## Weight and balance

Weight and Balance of an L1 validator can be updated by issuing following transactions corresponding to their L1 `validationID`:

* `SetL1ValidatorWeightTx` - Updates the weight of an L1 validator. If the weight is set to `0`, then the validator will be removed and the remaining balance will be returned to `RemainingBalanceOwner`.
* `IncreaseL1ValidatorBalanceTx` - Increases the balance of an L1 validator which will be used as a maintenance fee to the Primary Network.
* `DisableL1ValidatorTx` - Marks the validator as inactive and returning the remaining balance to the `RemainingBalanceOwner`.

***

## Continuous fee mechanism

L1 validators are required to maintain a balance on the P-Chain to cover continuous fees for their participation in the network. The fee is deducted over time from the validator’s balance and is used to compensate for the resources consumed on the Primary Network. Validators should monitor their balance regularly and use the `IncreaseL1ValidatorBalanceTx` to top up their balance as needed to prevent becoming inactive.

### Fee calculation:

* The continuous fee is calculated based on network parameters and the number of active L1 validators.
* The minimum fee rate is **512 nAVAX per second**, which equates to approximately **1.33 AVAX per month** per validator when the number of validators is at or below the target.

### Recommendations for validators:

* Set up alerts or monitoring tools to track balance levels.
* Plan regular intervals for balance top-ups to ensure uninterrupted validation services.
* Remember that any unspent balance can be reclaimed using the `DisableL1ValidatorTx`.

***

## Data API changes

To incorporate Etna-related data, we have made the following changes to the Data API’s Primary Network endpoints:

### 1. List L1 validators

**New endpoint:** [List L1 Validators](/data-api/primary-network/list-l1-validators)

* **Purpose:** Allows listing all or specific L1 validators.
* **Parameters or query changes:**
  * `L1ValidationID`: Get details of a specific L1 validator.
  * `SubnetID`: Filter validators of a particular subnet.
  * `NodeID`: Filter validators associated with a specific `NodeID`.
  * `IncludeInactiveL1Validators`: Include inactive L1 validators in the response.
* **Response Changes:**
  * Returns a list of L1 validators. Refer to the [endpoint documentation](/data-api/primary-network/list-l1-validators) for full details.

***

### 2. List L1 validator transactions

**Updated endpoint:** [List latest transactions on the primary network](/data-api/primary-network-transactions/list-latest-transactions)

* **Changes:**
  * Added a new query parameter `L1ValidationID`.
* **Purpose:**
  * By providing `L1ValidationID`, you receive all transactions linked to the validator’s `validationID`, such as `ConvertSubnetToL1Tx`, `IncreaseL1ValidatorBalanceTx`, or `DisableL1ValidatorTx`.
* **Sorting and filtering:**
  * Transactions can only be sorted in descending order by their `timestamp`.
  * Additional filters include start and end timestamp bounds and transaction types (`txTypes`).
* **Response changes:**
  * Refer to [New Transaction Properties](/data-api/etna#3-new-transaction-properties) for details.

***

### 3. New transaction properties

**Updated endpoints:**

* [Get Transaction](https://developers.avacloud.io/data-api/primary-network-transactions/get-transaction)
* [List Latest Transactions](https://developers.avacloud.io/data-api/primary-network-transactions/list-latest-transactions)
* [List Staking Transactions](https://developers.avacloud.io/data-api/primary-network-transactions/list-staking-transactions)

**Parameters or query changes:**

* None

**Response changes:** <br />
The `PChainTransaction` response type now includes the following new properties:

* `L1ValidatorManagerDetails`:
  * `BlockchainID`: The blockchain ID where the validator manager is deployed.
  * `ContractAddress`: Address of the validator manager smart contract.
* `L1ValidatorDetails`
  * `validationID`: Unique identifier for this L1 validation.
  * `nodeID`: NodeID of the validator.
  * `subnetID`: SubnetID of which this validationID belongs to.
  * `weight`: Weight to be used when participating in validation process.
  * `remainingBalance`: Remaining L1 validator balance in nAVAX until inactive.
  * `balanceChange`: Change in Balance of validator in the current transaction.
* `AmountL1ValidatorBalanceBurned`
  * Asset details and amount of AVAX burned to increase the L1 validator balance

***

### 4. New block properties

**Updated endpoints:**

* [Get Block](https://developers.avacloud.io/data-api/primary-network-blocks/get-block)
* [List Latest Blocks](https://developers.avacloud.io/data-api/primary-network-blocks/list-latest-blocks)
* [List Blocks Proposed By Node](https://developers.avacloud.io/data-api/primary-network-blocks/list-blocks-proposed-by-node)

**Parameters or query changes:**

* None

**Response changes:** <br />
Each P-Chain block will now include properties representing L1 validators state at that block height:

* `ActiveL1Validators`: Total active L1 validators
* `L1ValidatorsAccruedFees`: Total fees accrued by network (in nAVAX) from active L1 validators

***

### 5. New Subnet Properties

**Updated endpoint:**

* [Get Subnet Details By ID](https://developers.avacloud.io/data-api/primary-network/get-subnet-details-by-id)
* [List Subnets](https://developers.avacloud.io/data-api/primary-network/list-subnets)

**Parameters or query changes:**

* None

**Response changes:** <br />
Each Subnet will now have a new property IsL1 to identify whether it has been converted to an L1 or not. For all L1s, there will be a new property:

* `isL1`: Whether the subnet is converted to L1 or not
* `L1ValidatorManagerDetails`: Includes `blockchainID` and contract address of the validator manager.

## Additional Resources

For more detailed information and technical specifications, please refer to the following resources:

* [**ACP-77: Reinventing Subnets**:](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets)
  ACP 77 provides an in-depth explanation of the changes introduced in the Etna Upgrade.
* [**What to Expect After the Etna Upgrade**:](https://academy.avax.network/guide/etna-changes)
  This guide outlines the operational impact on existing network participants expected from the activation of the AvalancheGo "Etna" upgrade.
* [**Subnet & L1 Validators, What's the Difference?**:](https://academy.avax.network/guide/subnet-vs-l1-validators)
  This guide defines the difference between Subnet and L1 validators, differentiating the roles and responsibilities of each.
* [**Validator Manager Smart Contract Documentation**:](https://github.com/ava-labs/teleporter/blob/main/contracts/validator-manager/README.md)
  Validator Manager Smart Contract contains technical details on deploying and interacting with the validator manager.
* [**AvalancheGo Implementation Details**:](https://github.com/ava-labs/avalanchego/releases/tag/v1.12.0-fuji)
  For developers interested in the implementation, refer to the AvalancheGo repository.
* [**Etna DevNet Resources**:](https://github.com/ava-labs/etna-devnet-resources)
  The Etna DevNet is a temporary Avalanche network instance that was created for the purpose of testing and integrating with the changes introduced in the Etna upgrade prior to their activation on the Fuji testnet.

The Etna Upgrade marks a significant milestone in the evolution of the Avalanche network, introducing more flexibility and autonomy for Subnets through the concept of Layer 1 blockchains. By understanding and leveraging these new features, network participants can optimize their operations and contribute to the growth and decentralization of the Avalanche ecosystem.


# Get native token balance
Source: https://developers.avacloud.io/data-api/evm-balances/get-native-token-balance

get /v1/chains/{chainId}/addresses/{address}/balances:getNative
Gets native token balance of a wallet address.

Balance at a given block can be retrieved with the `blockNumber` parameter.



# List collectible (ERC-721/ERC-1155) balances
Source: https://developers.avacloud.io/data-api/evm-balances/list-collectible-erc-721erc-1155-balances

get /v1/chains/{chainId}/addresses/{address}/balances:listCollectibles
Lists ERC-721 and ERC-1155 token balances of a wallet address.

Balance for a specific contract can be retrieved with the `contractAddress` parameter.



# List ERC-1155 balances
Source: https://developers.avacloud.io/data-api/evm-balances/list-erc-1155-balances

get /v1/chains/{chainId}/addresses/{address}/balances:listErc1155
Lists ERC-1155 token balances of a wallet address.

Balance at a given block can be retrieved with the `blockNumber` parameter.

Balance for a specific contract can be retrieved with the `contractAddress` parameter.



# List ERC-20 balances
Source: https://developers.avacloud.io/data-api/evm-balances/list-erc-20-balances

get /v1/chains/{chainId}/addresses/{address}/balances:listErc20
Lists ERC-20 token balances of a wallet address.

Balance at a given block can be retrieved with the `blockNumber` parameter.

Balance for specific contracts can be retrieved with the `contractAddresses` parameter.



# List ERC-721 balances
Source: https://developers.avacloud.io/data-api/evm-balances/list-erc-721-balances

get /v1/chains/{chainId}/addresses/{address}/balances:listErc721
Lists ERC-721 token balances of a wallet address.

Balance for a specific contract can be retrieved with the `contractAddress` parameter.



# Get block
Source: https://developers.avacloud.io/data-api/evm-blocks/get-block

get /v1/chains/{chainId}/blocks/{blockId}
Gets the details of an individual block on the EVM-compatible chain.



# List latest blocks
Source: https://developers.avacloud.io/data-api/evm-blocks/list-latest-blocks

get /v1/chains/{chainId}/blocks
Lists the latest indexed blocks on the EVM-compatible chain sorted in descending order by block timestamp.



# List latest blocks across all supported EVM chains
Source: https://developers.avacloud.io/data-api/evm-blocks/list-latest-blocks-across-all-supported-evm-chains

get /v1/blocks
Lists the most recent blocks from all supported  EVM-compatible chains. The results can be filtered by network.



# Get chain information
Source: https://developers.avacloud.io/data-api/evm-chains/get-chain-information

get /v1/chains/{chainId}
Gets chain information for the EVM-compatible chain if supported by AvaCloud.



# null
Source: https://developers.avacloud.io/data-api/evm-chains/get-chains-for-address

get /v1/chains/address/{address}
**[Deprecated]** Gets a list of all chains where the address was either a sender or receiver in a transaction or ERC transfer. The list is currently updated every 15 minutes.

⚠️ **This operation will be removed in a future release.  Please use /v1/address/:address/chains endpoint instead** .



# List all chains associated with a given address
Source: https://developers.avacloud.io/data-api/evm-chains/list-all-chains-associated-with-a-given-address

get /v1/address/{address}/chains
Lists the chains where the specified address has  participated in transactions or ERC token transfers,  either as a sender or receiver. The data is refreshed every 15  minutes.



# List chains
Source: https://developers.avacloud.io/data-api/evm-chains/list-chains

get /v1/chains
Lists the AvaCloud supported EVM-compatible chains. Filterable by network.



# null
Source: https://developers.avacloud.io/data-api/evm-chains/list-latest-blocks-for-all-supported-evm-chains

get /v1/chains/allBlocks
**[Deprecated]** Lists the latest blocks for all supported EVM chains. Filterable by network.

⚠️ **This operation will be removed in a future release.  Please use /v1/blocks endpoint instead** .



# null
Source: https://developers.avacloud.io/data-api/evm-chains/list-latest-transactions-for-all-supported-evm-chains

get /v1/chains/allTransactions
**[Deprecated]** Lists the latest transactions for all supported EVM chains. Filterable by status.

⚠️ **This operation will be removed in a future release.  Please use /v1/transactions endpoint instead** .



# Get contract metadata
Source: https://developers.avacloud.io/data-api/evm-contracts/get-contract-metadata

get /v1/chains/{chainId}/addresses/{address}
Gets metadata about the contract at the given address.



# Get deployment transaction
Source: https://developers.avacloud.io/data-api/evm-transactions/get-deployment-transaction

get /v1/chains/{chainId}/contracts/{address}/transactions:getDeployment
If the address is a smart contract, returns the transaction in which it was deployed.



# Get transaction
Source: https://developers.avacloud.io/data-api/evm-transactions/get-transaction

get /v1/chains/{chainId}/transactions/{txHash}
Gets the details of a single transaction.



# List deployed contracts
Source: https://developers.avacloud.io/data-api/evm-transactions/list-deployed-contracts

get /v1/chains/{chainId}/contracts/{address}/deployments
Lists all contracts deployed by the given address.



# List ERC-1155 transfers
Source: https://developers.avacloud.io/data-api/evm-transactions/list-erc-1155-transfers

get /v1/chains/{chainId}/addresses/{address}/transactions:listErc1155
Lists ERC-1155 transfers for an address. Filterable by block range.



# List ERC-20 transfers
Source: https://developers.avacloud.io/data-api/evm-transactions/list-erc-20-transfers

get /v1/chains/{chainId}/addresses/{address}/transactions:listErc20
Lists ERC-20 transfers for an address. Filterable by block range.



# List ERC-721 transfers
Source: https://developers.avacloud.io/data-api/evm-transactions/list-erc-721-transfers

get /v1/chains/{chainId}/addresses/{address}/transactions:listErc721
Lists ERC-721 transfers for an address. Filterable by block range.



# List ERC transfers
Source: https://developers.avacloud.io/data-api/evm-transactions/list-erc-transfers

get /v1/chains/{chainId}/tokens/{address}/transfers
Lists ERC transfers for an ERC-20, ERC-721, or ERC-1155 contract address.



# List internal transactions
Source: https://developers.avacloud.io/data-api/evm-transactions/list-internal-transactions

get /v1/chains/{chainId}/addresses/{address}/transactions:listInternals
Returns a list of internal transactions for an address and chain. Filterable by block range.

Note that the internal transactions list only contains `CALL` or `CALLCODE` transactions with a non-zero value and `CREATE`/`CREATE2` transactions. To get a complete list of internal transactions use the `debug_` prefixed RPC methods on an archive node.



# List latest transactions
Source: https://developers.avacloud.io/data-api/evm-transactions/list-latest-transactions

get /v1/chains/{chainId}/transactions
Lists the latest transactions. Filterable by status.



# List native transactions
Source: https://developers.avacloud.io/data-api/evm-transactions/list-native-transactions

get /v1/chains/{chainId}/addresses/{address}/transactions:listNative
Lists native transactions for an address. Filterable by block range.



# List the latest transactions across all supported EVM chains
Source: https://developers.avacloud.io/data-api/evm-transactions/list-the-latest-transactions-across-all-supported-evm-chains

get /v1/transactions
Lists the most recent transactions from all supported EVM-compatible  chains. The results can be filtered based on transaction status.



# List transactions
Source: https://developers.avacloud.io/data-api/evm-transactions/list-transactions

get /v1/chains/{chainId}/addresses/{address}/transactions
Returns a list of transactions where the given wallet address had an on-chain interaction for the given chain. The ERC-20 transfers, ERC-721 transfers, ERC-1155, and internal transactions returned are only those where the input address had an interaction. Specifically, those lists only inlcude entries where the input address was the sender (`from` field) or the receiver (`to` field) for the sub-transaction. Therefore the transactions returned from this list may not be complete representations of the on-chain data. For a complete view of a transaction use the `/chains/:chainId/transactions/:txHash` endpoint.

Filterable by block ranges.



# List transactions for a block
Source: https://developers.avacloud.io/data-api/evm-transactions/list-transactions-for-a-block

get /v1/chains/{chainId}/blocks/{blockId}/transactions
Lists the transactions that occured in a given block.



# Getting Started
Source: https://developers.avacloud.io/data-api/getting-started



<Steps>
  <Step title="Create your account">
    To begin, create your free AvaCloud account by visiting [AvaCloud](https://app.avacloud.io/).

    <Frame>
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/avacloud-login.png" />
    </Frame>
  </Step>

  <Step title="Get an API Key">
    Once the account is created:

    1. Navigating to **Web3 Data API**
    2. Click on **Add API Key**
    3. Set an alias and click on **create**
    4. Copy the the value

    <Frame>
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/avacloud-api-key.png" />
    </Frame>

    <Warning>Always keep your API keys in a secure environment. Never expose them in public repositories, such as GitHub, or share them with unauthorized individuals. Compromised API keys can lead to unauthorized access and potential misuse of your account.</Warning>
  </Step>

  <Step title="Make a query">
    With your API Key you can start making queries, for example to get the latest block on the C-chain(43114):

    ```bash
      curl --location 'https://glacier-api.avax.network/v1/chains/43114/blocks' \
      --header 'accept: application/json' \
      --header 'x-glacier-api-key: <YOUR-API-KEY>' \
    ```

    And you should see something like this:

    ```json
    {
      "blocks": [
        {
          "blockNumber": "49889407",
          "blockTimestamp": 1724990250,
          "blockHash": "0xd34becc82943e3e49048cdd3f75b80a87e44eb3aed6b87cc06867a7c3b9ee213",
          "txCount": 1,
          "baseFee": "25000000000",
          "gasUsed": "53608",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0xf4917efb4628a1d8f4d101b3d15bce9826e62ef2c93c3e16ee898d27cf02f3d4",
          "feesSpent": "1435117553916960",
          "cumulativeTransactions": "500325352"
        },
        {
          "blockNumber": "49889406",
          "blockTimestamp": 1724990248,
          "blockHash": "0xf4917efb4628a1d8f4d101b3d15bce9826e62ef2c93c3e16ee898d27cf02f3d4",
          "txCount": 2,
          "baseFee": "25000000000",
          "gasUsed": "169050",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x2a54f142fa3acee92a839b071bb6c7cca7abc2a797cf4aac68b07f79406ac0cb",
          "feesSpent": "4226250000000000",
          "cumulativeTransactions": "500325351"
        },
        {
          "blockNumber": "49889405",
          "blockTimestamp": 1724990246,
          "blockHash": "0x2a54f142fa3acee92a839b071bb6c7cca7abc2a797cf4aac68b07f79406ac0cb",
          "txCount": 4,
          "baseFee": "25000000000",
          "gasUsed": "618638",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x0cda1bb5c86e790976c9330c9fc26e241a705afbad11a4caa44df1c81058451d",
          "feesSpent": "16763932426044724",
          "cumulativeTransactions": "500325349"
        },
        {
          "blockNumber": "49889404",
          "blockTimestamp": 1724990244,
          "blockHash": "0x0cda1bb5c86e790976c9330c9fc26e241a705afbad11a4caa44df1c81058451d",
          "txCount": 3,
          "baseFee": "25000000000",
          "gasUsed": "254544",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x60e55dd9eacc095c07f50a73e02d81341c406584f7abbf5d10d938776a4c893c",
          "feesSpent": "6984642298020000",
          "cumulativeTransactions": "500325345"
        },
        {
          "blockNumber": "49889403",
          "blockTimestamp": 1724990242,
          "blockHash": "0x60e55dd9eacc095c07f50a73e02d81341c406584f7abbf5d10d938776a4c893c",
          "txCount": 2,
          "baseFee": "25000000000",
          "gasUsed": "65050",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0xa3e9f91f45a85ed00b8ebe8e5e976ed1a1f52612143eddd3de9d2588d05398b8",
          "feesSpent": "1846500000000000",
          "cumulativeTransactions": "500325342"
        },
        {
          "blockNumber": "49889402",
          "blockTimestamp": 1724990240,
          "blockHash": "0xa3e9f91f45a85ed00b8ebe8e5e976ed1a1f52612143eddd3de9d2588d05398b8",
          "txCount": 2,
          "baseFee": "25000000000",
          "gasUsed": "74608",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x670db772edfc2fdae322d55473ba0670690aed6358a067a718492c819d63356a",
          "feesSpent": "1997299851936960",
          "cumulativeTransactions": "500325340"
        },
        {
          "blockNumber": "49889401",
          "blockTimestamp": 1724990238,
          "blockHash": "0x670db772edfc2fdae322d55473ba0670690aed6358a067a718492c819d63356a",
          "txCount": 1,
          "baseFee": "25000000000",
          "gasUsed": "273992",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x75742cf45383ce54823690b9dd2e85a743be819281468163d276f145d077902a",
          "feesSpent": "7334926295195040",
          "cumulativeTransactions": "500325338"
        },
        {
          "blockNumber": "49889400",
          "blockTimestamp": 1724990236,
          "blockHash": "0x75742cf45383ce54823690b9dd2e85a743be819281468163d276f145d077902a",
          "txCount": 1,
          "baseFee": "25000000000",
          "gasUsed": "291509",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0xe5055eae3e1fd2df24b61e9c691f756c97e5619cfc66b69cbcb6025117d1bde7",
          "feesSpent": "7724988500000000",
          "cumulativeTransactions": "500325337"
        },
        {
          "blockNumber": "49889399",
          "blockTimestamp": 1724990234,
          "blockHash": "0xe5055eae3e1fd2df24b61e9c691f756c97e5619cfc66b69cbcb6025117d1bde7",
          "txCount": 8,
          "baseFee": "25000000000",
          "gasUsed": "824335",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0xbcacff928f7dd20cc1522155e7c9b9716997914b53ab94034b813c3f207174ef",
          "feesSpent": "21983004380692400",
          "cumulativeTransactions": "500325336"
        },
        {
          "blockNumber": "49889398",
          "blockTimestamp": 1724990229,
          "blockHash": "0xbcacff928f7dd20cc1522155e7c9b9716997914b53ab94034b813c3f207174ef",
          "txCount": 1,
          "baseFee": "25000000000",
          "gasUsed": "21000",
          "gasLimit": "15000000",
          "gasCost": "0",
          "parentHash": "0x0b686812078429d33e4224d2b48bd26b920db8dbb464e7f135d980759ca7e947",
          "feesSpent": "562182298020000",
          "cumulativeTransactions": "500325328"
        }
      ],
      "nextPageToken": "9f9e1d25-14a9-49f4-8742-fd4bf12f7cd8"
    }
    ```
  </Step>
</Steps>

Congratulations! You’ve successfully set up your account and made your first query to the Data API  🚀🚀🚀


# Get the health of the service
Source: https://developers.avacloud.io/data-api/health-check/get-the-health-of-the-service

get /v1/health-check
Check the health of the service.



# Get an ICM message
Source: https://developers.avacloud.io/data-api/interchain-messaging/get-an-icm-message

get /v1/icm/messages/{messageId}
Gets an ICM message by message ID.



# List ICM messages
Source: https://developers.avacloud.io/data-api/interchain-messaging/list-icm-messages

get /v1/icm/messages
Lists ICM messages. Ordered by timestamp in descending order.



# List ICM messages by address
Source: https://developers.avacloud.io/data-api/interchain-messaging/list-icm-messages-by-address

get /v1/icm/addresses/{address}/messages
Lists ICM messages by address. Ordered by timestamp in descending order.



# How to get the native balance of an address
Source: https://developers.avacloud.io/data-api/native-balance



Checking the balance of a wallet is vital for users who want to manage their digital assets effectively. By reviewing their wallet balance, users can:

* **Track their asset portfolio**: Regularly monitoring the wallet balance keeps users informed about the value of their holdings, enabling them to make informed decisions on buying, selling, or retaining their digital assets.
* **Confirm received transactions**: When expecting digital assets, verifying the wallet balance helps ensure that transactions have been successfully completed and the correct amounts have been received.
* **Plan future transactions**: Knowing the wallet’s balance allows users to prepare for upcoming transactions and verify that they have enough funds to cover fees or other related costs.

This guide will walk you through how to get the native balance associated with a specific wallet address on the C-chain network using the Data API.

### Step 1: Set Up AvaCloud

First, ensure that you have set up [AvaCloud](https://app.avacloud.io/) and have access to your API key. If you’re new to Avacloud, create an account and obtain an API key.

### Step 2: Retrieve the Native Balance of an Address

To obtain the native balance of a wallet address you can use [Get native token balance](/data-api/evm-balances/get-native-token-balance) endpoint. You’ll need to specify the `chainId` and the `address` for which you want to retrieve the balance.

Here’s how you can do it:

<CodeGroup>
  ```javascript AvacloudSDK
  import { AvaCloudSDK } from "@avalabs/avacloud-sdk";

  const avaCloudSDK = new AvaCloudSDK({
    apiKey: "<YOUR_API_KEY_HERE>",
    chainId: "43114",
    network: "mainnet",
  });

  async function run() {
    const result = await avaCloudSDK.data.evm.balances.getNativeBalance({
      blockNumber: "6479329",
      address: "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      currency: "usd",
    });

    // Handle the result
    console.log(JSON.stringify(result, null, 2));
  }

  run();
  ```

  ```bash cURL
  curl --request GET \
     --url https://glacier-api.avax.network/v1/chains/43114/addresses/0x71C7656EC7ab88b098defB751B7401B5f6d8976F/balances:getNative \
    --header 'x-glacier-api-key: <api-key>'
  ```
</CodeGroup>

Response

```json
{
  "nativeTokenBalance": {
    "chainId": "43114",
    "name": "Avalanche",
    "symbol": "AVAX",
    "decimals": 18,
    "price": {
      "currencyCode": "usd",
      "value": 26.32
    },
    "balance": "3316667947990566036",
    "balanceValue": {
      "currencyCode": "usd",
      "value": 87.29
    },
    "logoUri": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg"
  }
}
```

Congratulations 🎉  You’ve successfully retrieved the native balance of a wallet address using just a few lines of code with the Data API!


# Get token details
Source: https://developers.avacloud.io/data-api/nfts/get-token-details

get /v1/chains/{chainId}/nfts/collections/{address}/tokens/{tokenId}
Gets token details for a specific token of an NFT contract.



# List tokens
Source: https://developers.avacloud.io/data-api/nfts/list-tokens

get /v1/chains/{chainId}/nfts/collections/{address}/tokens
Lists tokens for an NFT contract.



# Reindex NFT metadata
Source: https://developers.avacloud.io/data-api/nfts/reindex-nft-metadata

post /v1/chains/{chainId}/nfts/collections/{address}/tokens/{tokenId}:reindex
Triggers reindexing of token metadata for an NFT token. Reindexing can only be called once per hour for each NFT token.



# Create transaction export operation
Source: https://developers.avacloud.io/data-api/operations/create-transaction-export-operation

post /v1/operations/transactions:export
Trigger a transaction export operation with given parameters.

The transaction export operation runs asynchronously in the background. The status of the job can be retrieved from the `/v1/operations/:operationId` endpoint using the `operationId` returned from this endpoint.



# Get operation
Source: https://developers.avacloud.io/data-api/operations/get-operation

get /v1/operations/{operationId}
Gets operation details for the given operation id.



# Overview
Source: https://developers.avacloud.io/data-api/overview



### What is the Data API?

The Data API provides web3 application developers with multi-chain data related to Avalanche's primary network, Avalanche L1s, and Ethereum. With the Data API, you can easily build products that leverage real-time and historical transaction and transfer history, native and token balances, and various types of token metadata.

![Data API](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/data-api.png)

The [Data API](/data-api), along with the [Metrics API](/metrics-api), are the engines behind the [Avalanche Explorer](https://subnets.avax.network/stats/) and the [Core wallet](https://core.app/en/). They are used to display transactions, logs, balances, NFTs, and more. The data and visualizations presented are all powered by these APIs, offering real-time and historical insights that are essential for building sophisticated, data-driven blockchain products.

<Info>The Data API and Glacier API refer to the same API. If you encounter the term “Glacier API” in other documentation, it is referring to the Data API, which was previously known as the Glacier API.​</Info>

### Features

* **Extensive L1 Support**: Gain access to data from over 100+ L1s across both mainnet and testnet. If an L1 is listed on the [Avalanche Explorer](https://subnets.avax.network/), you can query its data using the Data API.
* **Transactions and UTXOs**: easily retrieve details related to transactions, UTXOs, and token transfers from Avalanche EVMs, Ethereum, and Avalanche's Primary Network - the P-Chain, X-Chain and C-Chain.
* **Blocks**: retrieve latest blocks and block details
* **Balances**: fetch balances of native, ERC-20, ERC-721, and ERC-1155 tokens along with relevant metadata.
* **Tokens**: augment your user experience with asset details.
* **Staking**: get staking related data for active and historical validations.

### Supported Chains

Avalanche’s architecture supports a diverse ecosystem of interconnected L1 blockchains, each operating independently while retaining the ability to seamlessly communicate with other L1s within the network. Central to this architecture is the Primary Network—Avalanche’s foundational network layer, which all validators are required to validate prior to [ACP-77](https://github.com/avalanche-foundation/ACPs/blob/main/ACPs/77-reinventing-subnets/README.md). The Primary Network runs three essential blockchains:

* The Contract Chain (C-Chain)
* The Platform Chain (P-Chain)
* The Exchange Chain (X-Chain)

However, with the implementation of [ACP-77](https://github.com/avalanche-foundation/ACPs/blob/main/ACPs/77-reinventing-subnets/README.md), this requirement will change. Subnet Validators will be able to operate independently of the Primary Network, allowing for more flexible and affordable Subnet creation and management.

The **Data API** supports a wide range of L1 blockchains (**over 100**) across both **mainnet** and **testnet**, including popular ones like Beam, DFK, Lamina1, Dexalot, Shrapnel, and Pulsar. In fact, every L1 you see on the [Avalanche Explorer](https://subnets.avax.network/) can be queried through the Data API. This list is continually expanding as we keep adding more L1s. For a full list of supported chains, visit [List chains](/data-api/evm-chains/list-chains).

#### The Contract Chain (C-Chain)

The C-Chain is an implementation of the Ethereum Virtual Machine (EVM). The primary network endpoints only provide information related to C-Chain atomic memory balances and import/export transactions. For additional data, please reference the EVM APIs.

#### The Platform Chain (P-Chain)

The P-Chain is responsible for all validator and L1-level operations. The P-Chain supports the creation of new blockchains and L1s, the addition of validators to L1s, staking operations, and other platform-level operations.

#### The Exchange Chain (X-Chain)

The X-Chain is responsible for operations on digital smart assets known as Avalanche Native Tokens. A smart asset is a representation of a real-world resource (for example, equity, or a bond) with sets of rules that govern its behavior, like "can’t be traded until tomorrow." The X-Chain supports the creation and trade of Avalanche Native Tokens.

| Feature          | Description                                                                                                                                                                                                                                                                                                                                                                              |
| :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Chains**       | Utilize this endpoint to retrieve the Primary Network chains that an address has transaction history associated with.                                                                                                                                                                                                                                                                    |
| **Blocks**       | Blocks are the container for transactions executed on the Primary Network. Retrieve the latest blocks, a specific block by height or hash, or a list of blocks proposed by a specified NodeID on Primary Network chains.                                                                                                                                                                 |
| **Vertices**     | Prior to Avalanche Cortina (v1.10.0), the X-Chain functioned as a DAG with vertices rather than blocks. These endpoints allow developers to retrieve historical data related to that period of chain history. Retrieve the latest vertices, a specific vertex, or a list of vertices at a specific height from the X-Chain.                                                              |
| **Transactions** | Transactions are a user's primary form of interaction with a chain and provide details around their on-chain activity, including staking-related behavior. Retrieve a list of the latest transactions, a specific transaction, a list of active staking transactions for a specified address, or a list of transactions associated with a provided asset id from Primary Network chains. |
| **UTXOs**        | UTXOs are fundamental elements that denote the funds a user has available. Get a list of UTXOs for provided addresses from the Primary Network chains.                                                                                                                                                                                                                                   |
| **Balances**     | User balances are an essential function of the blockchain. Retrieve balances related to the X and P-Chains, as well as atomic memory balances for the C-Chain.                                                                                                                                                                                                                           |
| **Rewards**      | Staking is the process where users lock up their tokens to support a blockchain network and, in return, receive rewards. It is an essential part of proof-of-stake (PoS) consensus mechanisms used by many blockchain networks, including Avalanche. Using the Data API, you can easily access pending and historical rewards associated with a set of addresses.                        |
| **Assets**       | Get asset details corresponding to the given asset id on the X-Chain.                                                                                                                                                                                                                                                                                                                    |

#### EVM

The C-Chain is an instance of the Coreth Virtual Machine, and many Avalanche L1s are instances of the *Subnet-EVM*, which is a Virtual Machine (VM) that defines the L1 Contract Chains. *Subnet-EVM* is a simplified version of *Coreth VM* (C-Chain).

| Feature          | Description                                                                                                                                                                                                                                                                                                   |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Chains**       | There are a number of chains supported by the Data API. These endpoints can be used to understand which chains are included/indexed as part of the API and retrieve information related to a specific chain.                                                                                                  |
| **Blocks**       | Blocks are the container for transactions executed within the EVM. Retrieve the latest blocks or a specific block by height or hash.                                                                                                                                                                          |
| **Transactions** | Transactions are a user's primary form of interaction with a chain and provide details around their on-chain activity. These endpoints can be used to retrieve information related to specific transaction details, internal transactions, contract deployments, specific token standard transfers, and more! |
| **Balances**     | User balances are an essential function of the blockchain. Easily retrieve native token, collectible, and fungible token balances related to an EVM chain with these endpoints.                                                                                                                               |

#### Operations

The Operations API allows users to easily access their on-chain history by creating transaction exports returned in a CSV format. This API supports EVMs as well as non-EVM Primary Network chains.


# Get balances
Source: https://developers.avacloud.io/data-api/primary-network-balances/get-balances

get /v1/networks/{network}/blockchains/{blockchainId}/balances
Gets primary network balances for one of the Primary Network chains for the supplied addresses.

C-Chain balances returned are only the shared atomic memory balance. For EVM balance, use the `/v1/chains/:chainId/addresses/:addressId/balances:getNative` endpoint.



# Get block
Source: https://developers.avacloud.io/data-api/primary-network-blocks/get-block

get /v1/networks/{network}/blockchains/{blockchainId}/blocks/{blockId}
Gets a block by block height or block hash on one of the Primary Network chains.



# List blocks proposed by node
Source: https://developers.avacloud.io/data-api/primary-network-blocks/list-blocks-proposed-by-node

get /v1/networks/{network}/blockchains/{blockchainId}/nodes/{nodeId}/blocks
Lists the latest blocks proposed by a given NodeID on one of the Primary Network chains.



# List latest blocks
Source: https://developers.avacloud.io/data-api/primary-network-blocks/list-latest-blocks

get /v1/networks/{network}/blockchains/{blockchainId}/blocks
Lists latest blocks on one of the Primary Network chains.



# List historical rewards
Source: https://developers.avacloud.io/data-api/primary-network-rewards/list-historical-rewards

get /v1/networks/{network}/rewards
Lists historical rewards on the Primary Network for the supplied addresses.



# List pending rewards
Source: https://developers.avacloud.io/data-api/primary-network-rewards/list-pending-rewards

get /v1/networks/{network}/rewards:listPending
Lists pending rewards on the Primary Network for the supplied addresses.



# Get transaction
Source: https://developers.avacloud.io/data-api/primary-network-transactions/get-transaction

get /v1/networks/{network}/blockchains/{blockchainId}/transactions/{txHash}
Gets the details of a single transaction on one of the Primary Network chains.



# List asset transactions
Source: https://developers.avacloud.io/data-api/primary-network-transactions/list-asset-transactions

get /v1/networks/{network}/blockchains/{blockchainId}/assets/{assetId}/transactions
Lists asset transactions corresponding to the given asset id on the X-Chain.



# List latest transactions
Source: https://developers.avacloud.io/data-api/primary-network-transactions/list-latest-transactions

get /v1/networks/{network}/blockchains/{blockchainId}/transactions
Lists the latest transactions on one of the Primary Network chains.

Transactions are filterable by addresses, txTypes, and timestamps. When querying for latest transactions without an address parameter, filtering by txTypes and timestamps is not supported. An address filter must be provided to utilize txTypes and timestamp filters.

For P-Chain, you can fetch all L1 validators related transactions like ConvertSubnetToL1Tx, IncreaseL1ValidatorBalanceTx etc. using the unique L1 validation ID. These transactions are further filterable by txTypes and timestamps as well.

Given that each transaction may return a large number of UTXO objects, bounded only by the maximum transaction size, the query may return less transactions than the provided page size. The result will contain less results than the page size if the number of utxos contained in the resulting transactions reach a performance threshold.



# List staking transactions
Source: https://developers.avacloud.io/data-api/primary-network-transactions/list-staking-transactions

get /v1/networks/{network}/blockchains/{blockchainId}/transactions:listStaking
Lists active staking transactions on the P-Chain for the supplied addresses.



# List UTXOs
Source: https://developers.avacloud.io/data-api/primary-network-utxos/list-utxos

get /v1/networks/{network}/blockchains/{blockchainId}/utxos
Lists UTXOs on one of the Primary Network chains for the supplied addresses.



# Get vertex
Source: https://developers.avacloud.io/data-api/primary-network-vertices/get-vertex

get /v1/networks/{network}/blockchains/{blockchainId}/vertices/{vertexHash}
Gets a single vertex on the X-Chain.



# List vertices
Source: https://developers.avacloud.io/data-api/primary-network-vertices/list-vertices

get /v1/networks/{network}/blockchains/{blockchainId}/vertices
Lists latest vertices on the X-Chain.



# List vertices by height
Source: https://developers.avacloud.io/data-api/primary-network-vertices/list-vertices-by-height

get /v1/networks/{network}/blockchains/{blockchainId}/vertices:listByHeight
Lists vertices at the given vertex height on the X-Chain.



# Get asset details
Source: https://developers.avacloud.io/data-api/primary-network/get-asset-details

get /v1/networks/{network}/blockchains/{blockchainId}/assets/{assetId}
Gets asset details corresponding to the given asset id on the X-Chain.



# Get chain interactions for addresses
Source: https://developers.avacloud.io/data-api/primary-network/get-chain-interactions-for-addresses

get /v1/networks/{network}/addresses:listChainIds
Returns Primary Network chains that each address has touched in the form of an address mapped array. If an address has had any on-chain interaction for a chain, that chain's chain id will be returned.



# Get network details
Source: https://developers.avacloud.io/data-api/primary-network/get-network-details

get /v1/networks/{network}
Gets network details such as validator and delegator stats.



# Get single validator details
Source: https://developers.avacloud.io/data-api/primary-network/get-single-validator-details

get /v1/networks/{network}/validators/{nodeId}
List validator details for a single validator.  Filterable by validation status.



# Get Subnet details by ID
Source: https://developers.avacloud.io/data-api/primary-network/get-subnet-details-by-id

get /v1/networks/{network}/subnets/{subnetId}
Get details of the Subnet registered on the network.



# List blockchains
Source: https://developers.avacloud.io/data-api/primary-network/list-blockchains

get /v1/networks/{network}/blockchains
Lists all blockchains registered on the network.



# List delegators
Source: https://developers.avacloud.io/data-api/primary-network/list-delegators

get /v1/networks/{network}/delegators
Lists details for delegators.



# List L1 validators
Source: https://developers.avacloud.io/data-api/primary-network/list-l1-validators

get /v1/networks/{network}/l1Validators
Lists details for L1 validators. By default, returns details for all active L1 validators. Filterable by validator node ids, subnet id, and validation id.



# List subnets
Source: https://developers.avacloud.io/data-api/primary-network/list-subnets

get /v1/networks/{network}/subnets
Lists all subnets registered on the network.



# List validators
Source: https://developers.avacloud.io/data-api/primary-network/list-validators

get /v1/networks/{network}/validators
Lists details for validators. By default, returns details for all validators. Filterable by validator node ids and minimum delegation capacity.



# Rate Limits
Source: https://developers.avacloud.io/data-api/rate-limits



Rate limiting is managed through a weighted scoring system, known as Compute Units (CUs). Each API request consumes a specified number of CUs, determined by the complexity of the request. This system is designed to accommodate basic requests while efficiently handling more computationally intensive operations.

## Rate Limit Tiers

The maximum CUs (rate-limiting score) for a user depends on their subscription level and is delineated in the following table:

| Subscription Level | Per Minute Limit (CUs) | Per Day Limit (CUs) |
| :----------------- | :--------------------- | :------------------ |
| Unauthenticated    | 6,000                  | 1,200,000           |
| Free               | 8,000                  | 2,000,000           |
| Base               | 10,000                 | 3,750,000           |
| Growth             | 14,000                 | 11,200,000          |
| Pro                | 20,000                 | 25,000,000          |

To update your subscription level use the [AvaCloud Portal](https://app.avacloud.io/)

<Info> Note: Rate limits apply collectively across both Webhooks and Data APIs, with usage from each counting toward your total CU limit. </Info>

## Rate Limit Categories

The CUs for each category are defined in the following table:

{/* data weights value table start */}

| Weight | CU Value |
| :----- | :------- |
| Free   | 1        |
| Small  | 10       |
| Medium | 20       |
| Large  | 50       |
| XL     | 100      |
| XXL    | 200      |

{/* data weights value table end */}

## Rate Limits for Data API Endpoints

The CUs for each route are defined in the table below:

{/* data execution weights table start */}

| Endpoint                                                                          | Method | Weight | CU Value |
| :-------------------------------------------------------------------------------- | :----- | :----- | :------- |
| `/v1/health-check`                                                                | GET    | Medium | 20       |
| `/v1/address/{address}/chains`                                                    | GET    | Medium | 20       |
| `/v1/transactions`                                                                | GET    | Medium | 20       |
| `/v1/blocks`                                                                      | GET    | Medium | 20       |
| `/v1/chains/{chainId}/nfts/collections/{address}/tokens/{tokenId}:reindex`        | POST   | Small  | 10       |
| `/v1/chains/{chainId}/nfts/collections/{address}/tokens`                          | GET    | Medium | 20       |
| `/v1/chains/{chainId}/nfts/collections/{address}/tokens/{tokenId}`                | GET    | Medium | 20       |
| `/v1/operations/{operationId}`                                                    | GET    | Small  | 10       |
| `/v1/operations/transactions:export`                                              | POST   | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/transactions/{txHash}`         | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/transactions`                  | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/transactions:listStaking`      | GET    | XL     | 100      |
| `/v1/networks/{network}/rewards:listPending`                                      | GET    | XL     | 100      |
| `/v1/networks/{network}/rewards`                                                  | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/utxos`                         | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/balances`                      | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/blocks/{blockId}`              | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/nodes/{nodeId}/blocks`         | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/blocks`                        | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/vertices`                      | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/vertices/{vertexHash}`         | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/vertices:listByHeight`         | GET    | Medium | 20       |
| `/v1/networks/{network}/blockchains/{blockchainId}/assets/{assetId}`              | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains/{blockchainId}/assets/{assetId}/transactions` | GET    | XL     | 100      |
| `/v1/networks/{network}/addresses:listChainIds`                                   | GET    | XL     | 100      |
| `/v1/networks/{network}`                                                          | GET    | XL     | 100      |
| `/v1/networks/{network}/blockchains`                                              | GET    | Medium | 20       |
| `/v1/networks/{network}/subnets`                                                  | GET    | Medium | 20       |
| `/v1/networks/{network}/subnets/{subnetId}`                                       | GET    | Medium | 20       |
| `/v1/networks/{network}/validators`                                               | GET    | Medium | 20       |
| `/v1/networks/{network}/validators/{nodeId}`                                      | GET    | Medium | 20       |
| `/v1/networks/{network}/delegators`                                               | GET    | Medium | 20       |
| `/v1/networks/{network}/l1Validators`                                             | GET    | Medium | 20       |
| `/v1/teleporter/messages/{messageId}`                                             | GET    | Medium | 20       |
| `/v1/teleporter/messages`                                                         | GET    | Medium | 20       |
| `/v1/teleporter/addresses/{address}/messages`                                     | GET    | Medium | 20       |
| `/v1/icm/messages/{messageId}`                                                    | GET    | Medium | 20       |
| `/v1/icm/messages`                                                                | GET    | Medium | 20       |
| `/v1/icm/addresses/{address}/messages`                                            | GET    | Medium | 20       |
| `/v1/apiUsageMetrics`                                                             | GET    | XXL    | 200      |
| `/v1/apiLogs`                                                                     | GET    | XXL    | 200      |
| `/v1/subnetRpcUsageMetrics`                                                       | GET    | XXL    | 200      |
| `/v1/rpcUsageMetrics`                                                             | GET    | XXL    | 200      |
| `/v1/primaryNetworkRpcUsageMetrics`                                               | GET    | XXL    | 200      |
| `/v1/signatureAggregator/{network}/aggregateSignatures`                           | POST   | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/balances:getNative`                     | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/balances:listErc20`                     | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/balances:listErc721`                    | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/balances:listErc1155`                   | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/balances:listCollectibles`              | GET    | Medium | 20       |
| `/v1/chains/{chainId}/blocks`                                                     | GET    | Small  | 10       |
| `/v1/chains/{chainId}/blocks/{blockId}`                                           | GET    | Small  | 10       |
| `/v1/chains/{chainId}/contracts/{address}/transactions:getDeployment`             | GET    | Medium | 20       |
| `/v1/chains/{chainId}/contracts/{address}/deployments`                            | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}`                                        | GET    | Medium | 20       |
| `/v1/chains`                                                                      | GET    | Free   | 1        |
| `/v1/chains/{chainId}`                                                            | GET    | Free   | 1        |
| `/v1/chains/address/{address}`                                                    | GET    | Free   | 1        |
| `/v1/chains/allTransactions`                                                      | GET    | Free   | 1        |
| `/v1/chains/allBlocks`                                                            | GET    | Free   | 1        |
| `/v1/chains/{chainId}/tokens/{address}/transfers`                                 | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions`                           | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions:listNative`                | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions:listErc20`                 | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions:listErc721`                | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions:listErc1155`               | GET    | Medium | 20       |
| `/v1/chains/{chainId}/addresses/{address}/transactions:listInternals`             | GET    | Medium | 20       |
| `/v1/chains/{chainId}/transactions/{txHash}`                                      | GET    | Medium | 20       |
| `/v1/chains/{chainId}/blocks/{blockId}/transactions`                              | GET    | Medium | 20       |
| `/v1/chains/{chainId}/transactions`                                               | GET    | Medium | 20       |

{/* data execution weights table end */}

## Rate Limits for RPC endpoints

The CUs for RPC calls are calculated based on the RPC method(s) within the request. The CUs assigned to each method are defined in the table below:

{/* rpc execution weights table start */}

| Method                                    | Weight | CU Value |
| :---------------------------------------- | :----- | :------- |
| `eth_accounts`                            | Free   | 1        |
| `eth_blockNumber`                         | Small  | 10       |
| `eth_call`                                | Small  | 10       |
| `eth_coinbase`                            | Small  | 10       |
| `eth_chainId`                             | Free   | 1        |
| `eth_gasPrice`                            | Small  | 10       |
| `eth_getBalance`                          | Small  | 10       |
| `eth_getBlockByHash`                      | Small  | 10       |
| `eth_getBlockByNumber`                    | Small  | 10       |
| `eth_getBlockTransactionCountByNumber`    | Medium | 20       |
| `eth_getCode`                             | Medium | 20       |
| `eth_getLogs`                             | XXL    | 200      |
| `eth_getStorageAt`                        | Medium | 20       |
| `eth_getTransactionByBlockNumberAndIndex` | Medium | 20       |
| `eth_getTransactionByHash`                | Small  | 10       |
| `eth_getTransactionCount`                 | Small  | 10       |
| `eth_getTransactionReceipt`               | Small  | 10       |
| `eth_signTransaction`                     | Medium | 20       |
| `eth_sendTransaction`                     | Medium | 20       |
| `eth_sign`                                | Medium | 20       |
| `eth_sendRawTransaction`                  | Small  | 10       |
| `eth_syncing`                             | Free   | 1        |
| `net_listening`                           | Free   | 1        |
| `net_peerCount`                           | Medium | 20       |
| `net_version`                             | Free   | 1        |
| `web3_clientVersion`                      | Small  | 10       |
| `web3_sha3`                               | Small  | 10       |
| `eth_newPendingTransactionFilter`         | Medium | 20       |
| `eth_maxPriorityFeePerGas`                | Small  | 10       |
| `eth_baseFee`                             | Small  | 10       |
| `rpc_modules`                             | Free   | 1        |
| `eth_getChainConfig`                      | Small  | 10       |
| `eth_feeConfig`                           | Small  | 10       |
| `eth_getActivePrecompilesAt`              | Small  | 10       |

{/* rpc execution weights table end */}

<Info> All rate limits, weights, and CU values are subject to change. </Info>


# Aggregate Signatures
Source: https://developers.avacloud.io/data-api/signature-aggregator/aggregate-signatures

post /v1/signatureAggregator/{network}/aggregateSignatures
Aggregates Signatures for a Warp message from Subnet validators.



# Snowflake Datashare
Source: https://developers.avacloud.io/data-api/snowflake



Avalanche Primary Network data (C-chain, P-chain, and X-chain blockchains) can be accessed in a sql-based table format via the [Snowflake Data Marketplace.](https://app.snowflake.com/marketplace)

Explore the blockchain state since the Genesis Block. These tables provide insights on transaction gas fees, DeFi activity, the historical stake of validators on the primary network, AVAX emissions rewarded to past validators/delegators, and fees paid by Avalanche L1 Validators to the primary network.

## Features

Blockchain Data Available:

* **C-chain:**
  * Blocks
  * Transactions
  * Logs
  * Internal Transactions
  * Receipts
  * Messages
* **P-chain:**
  * Blocks
  * Transactions
  * UTXOs
* **X-chain:**
  * Blocks
  * Transactions
  * Vertices before the [X-chain Linearization](https://www.avax.network/blog/cortina-x-chain-linearization) in the Cortina Upgrade
* **Dictionary:** A data dictionary is provided with the listing with column and table descriptions. Example columns include:
  * `c_blocks.blockchash`
  * `c_transactions.transactionfrom`
  * `c_logs.topichex_0`
  * `p_blocks.block_hash`
  * `p_blocks.block_index`
  * `p_blocks.type`
  * `p_transactions.timestamp`
  * `p_transactions.transaction_hash`
  * `utxos.utxo_id`
  * `utxos.address`
  * `vertices.vertex_hash`
  * `vertices.parent_hash`
  * `x_blocks.timestamp`
  * `x_blocks.proposer_id`
  * `x_transactions.transaction_hash`
  * `x_transactions.type`

## Access

Search for the Ava Labs profile on the [Snowflake Data Marketplace](https://app.snowflake.com/marketplace).


# null
Source: https://developers.avacloud.io/data-api/teleporter/get-a-teleporter-message

get /v1/teleporter/messages/{messageId}
**[Deprecated]** Gets a teleporter message by message ID.

⚠️ **This operation will be removed in a future release.  Please use /v1/icm/messages/:messageId endpoint instead** .



# null
Source: https://developers.avacloud.io/data-api/teleporter/list-teleporter-messages

get /v1/teleporter/messages
**[Deprecated]** Lists teleporter messages. Ordered by timestamp in  descending order.

⚠️ **This operation will be removed in a future release.  Please use /v1/icm/messages endpoint instead** .



# null
Source: https://developers.avacloud.io/data-api/teleporter/list-teleporter-messages-address

get /v1/teleporter/addresses/{address}/messages
**[Deprecated]** Lists teleporter messages by address. Ordered by  timestamp in descending order.

⚠️ **This operation will be removed in a future release.  Please use /v1/icm/addresses/:address/messages endpoint instead** .



# Usage Guide
Source: https://developers.avacloud.io/data-api/usage-guide



### Setup and Authentication

In order to utilize your accounts rate limits, you will need to make API requests with an API key. You can generate API Keys from the AvaCloud portal. Once you've created and retrieved that, you will be able to make authenticated queries by passing in your API key in the `x-glacier-api-key` header of your HTTP request.

An example curl request can be found below:

```bash
curl -H "Content-Type: Application/json" -H "x-glacier-api-key: your_api_key" \
  "https://glacier-api.avax.network/v1/chains"
```

### Rate Limits

The Data API has rate limits in place to maintain it's stability and protect from bursts of incoming traffic. The rate limits associated with various plans can be found within AvaCloud.

When you hit your rate limit, the server will respond with a 429 http response code, and response headers to help you determine when you should start to make additional requests. The response headers follow the standards set in the RateLimit header fields for HTTP draft from the Internet Engineering Task Force.

With every response with a valid api key, the server will include the following headers:

* `ratelimit-policy` - The rate limit policy tied to your api key.
* `ratelimit-limit` - The number of requests you can send according to your policy.
* `ratelimit-remaining` - How many request remaining you can send in the period for your policy

For any request after the rate limit has been reached, the server will also respond with these headers:

* `ratelimit-reset`
* `retry-after`
  Both of these headers are set to the number of seconds until your period is over and requests will start succeeding again.

If you start receiving rate limit errors with the 429 response code, we recommend you discontinue sending requests to the server. You should wait to retry requests for the duration specified in the response headers. Alternatively, you can implement an exponential backoff algorithm to prevent continuous errors. Failure to discontinue requests may result in being temporarily blocked from accessing the API.

Error Types
The Data API generates standard error responses along with error codes based on provided requests and parameters.

Typically, response codes within the `2XX` range signifies successful requests, while those within the `4XX` range points to errors originating from the client's side. Meanwhile, response codes within the `5XX` range indicates problems on the server's side.

### Error Types

The Glacier API generates standard error responses along with error codes based on provided requests and parameters.

Typically, response codes within the `2XX` range signifies successful requests, while those within the `4XX` range points to errors originating from the client's side. Meanwhile, response codes within the `5XX` range indicates problems on the server's side.

The error response body is formatted like this:

```json
{
  "message": ["Invalid address format"], // route specific error message
  "error": "Bad Request", // error type
  "statusCode": 400 // http response code
}
```

Let's go through every error code that we can respond with:

| Error Code | Error Type            | Description                                                                                                                                                                                                                   |
| :--------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **400**    | Bad Request           | Bad requests generally mean the client has passed invalid or malformed parameters. Error messages in the response could help in evaluating the error.                                                                         |
| **401**    | Unauthorized          | When a client attempts to access resources that require authorization credentials but the client lacks proper authentication in the request, the server responds with 401.                                                    |
| **403**    | Forbidden             | When a client attempts to access resources with valid credentials but doesn't have the privilege to perform that action, the server responds with 403.                                                                        |
| **404**    | Not Found             | The 404 error is mostly returned when the client requests with either mistyped URL, or the passed resource is moved or deleted, or the resource doesn't exist.                                                                |
| **500**    | Internal Server Error | The 500 error is a generic server-side error that is returned for any uncaught and unexpected issues on the server side. This should be very rare, and you may reach out to us if the problem persists for a longer duration. |
| **502**    | Bad Gateway           | This is an internal error indicating invalid response received by the client-facing proxy or gateway from the upstream server.                                                                                                |
| **503**    | Service Unavailable   | The 503 error is returned for certain routes on a particular Subnet. This indicates an internal problem with our Subnet node, and may not necessarily mean the Subnet is down or affected.                                    |

The above list is not exhaustive of all the errors that you'll receive, but is categorized on the basis of error codes. You may see route-specific errors along with detailed error messages for better evaluating the response.

<Tip>Reach out to our team when you see an error in the `5XX` range for a longer duration. These errors should be very rare, but we try to fix them as soon as possible once detected.</Tip>

### Pagination

When utilizing pagination for endpoints that return lists of data such as transactions, UTXOs, or blocks, our API uses a straightforward mechanism to manage the navigation through large datasets. We divide data into pages and each page is limited with a `pageSize` number of elements as passed in the request. Users can navigate to subsequent pages using the page token received in the `nextPageToken` field. This method ensures efficient retrieval.

Routes with pagination have a following common response format:

```json
{
  "blocks": ["<blocks>"], // This field name will vary by route
  "nextPageToken": "3d22deea-ea64-4d30-8a1e-c2a353b67e90"
}
```

### Page Token Structure

* If there's more data in the dataset for the request, the API will include a UUID-based page token in the response. This token acts as a pointer to the next page of data.
* The UUID page token is generated randomly and uniquely for each pagination scenario, enhancing security and minimizing predictability.
* It's important to note that the page token is only returned when a next page is present. If there's no further data to retrieve, a page token will not be included in the response.
* The generated page token has an expiration window of 24 hours. Beyond this timeframe, the token will no longer be valid for accessing subsequent pages.

### Integration and Usage:

To make use of the pagination system, simply examine the API response. If a UUID page token is present, it indicates the availability of additional data on the next page. You can extract this token and include it in the subsequent request to access the subsequent page of results.

Please note that you must ensure that the subsequent request is made within the 24-hour timeframe after the original token's generation. Beyond this duration, the token will expire, and you will need to initiate a fresh request from the initial page.

By incorporating UUID page tokens, our API offers a secure, efficient, and user-friendly approach to navigating large datasets, streamlining your data retrieval proces

### Swagger API Reference

You can explore the full API definitions and interact with the endpoints in the Swagger documentation at:

<CardGroup cols={1}>
  <Card title="Swagger API Reference" icon="brackets-curly">
    [https://glacier-api.avax.network/api](https://glacier-api.avax.network/api)
  </Card>
</CardGroup>


# Avalanche API Documentation
Source: https://developers.avacloud.io/introduction



export function openSearch() {
    document.getElementById("search-bar-entry").click();
}

<div className="relative w-full flex items-center justify-center" style={{ height: '24rem'}}>
  <div className="absolute inset-0 bg-primary dark:bg-primary-light" style={{opacity: 0.05 }} />

  <div style={{ position: 'absolute', textAlign: 'center', padding: '0 1rem' }}>
    <div
      className="text-gray-900 dark:text-gray-200"
      style={{
     fontWeight: '600',
     fontSize: '28px',
     margin: '0',
    }}
    />

    <div class="flex flex-col items-center justify-center">
      <span class="font-bold text-5xl py-7 text-gray-900 dark:text-white">Avalanche API Documentation</span>
    </div>

    <p
      className="prose prose-gray dark:prose-invert"
      style={{
      marginTop: '1rem',
     fontWeight: '400',
     fontSize: '16px',
     maxWidth: '42rem'
    }}
    >
      Accelerate your development across 100+ Layer 1 blockchains with powerful SDKs, APIs, guides, and tutorials.
    </p>

    <div className="flex items-center justify-center">
      <button
        type="button"
        className="hidden w-full lg:flex items-center text-sm leading-6 rounded-lg py-1.5 pl-2.5 pr-3 shadow-sm text-gray-400 dark:text-white/50 bg-background-light dark:bg-background-dark dark:brightness-[1.1] dark:ring-1 dark:hover:brightness-[1.25] ring-1 ring-gray-400/20 hover:ring-gray-600/25 dark:ring-gray-600/30 dark:hover:ring-gray-500/30 focus:outline-primary"
        id="home-search-entry"
        style={{
      marginTop: '2rem',
      maxWidth: '28rem',
    }}
        onClick={openSearch}
      >
        <svg
          className="h-4 w-4 ml-1.5 mr-3 flex-none bg-gray-500 hover:bg-gray-600 dark:bg-white/50 dark:hover:bg-white/70"
          style={{
       maskImage:
         'url("https://mintlify.b-cdn.net/v6.5.1/solid/magnifying-glass.svg")',
       maskRepeat: 'no-repeat',
       maskPosition: 'center center',
      }}
        />

        Search or ask
      </button>
    </div>
  </div>
</div>

<div className="max-w-6xl mx-auto px-12 mt-3">
  <div class="flex flex-col items-center justify-center">
    <span class="font-bold text-2xl py-7 text-gray-900 dark:text-white">Popular Tutorials</span>

    <div class="search-buttons">
      <a href="data-api/getting-started">Quickstart</a>
      <a href="/data-api/address-transactions">Get transaction history</a>
      <a href="/webhooks-api/push-notifications">Send push notification</a>
      <a href="webhooks-api/erc20-transfers">Track ERC20 transfers</a>
      <a href="/data-api/native-balance">Get Native balance</a>
    </div>
  </div>

  <div class="flex flex-col items-center justify-center mt-6">
    <span class="font-bold text-2xl py-7 text-gray-900 dark:text-white">Discover our suite of APIs</span>
  </div>

  <CardGroup cols={2}>
    <Card title="Data API" icon="database" href="/data-api/">
      Retrieve data from multiple L1s with a few lines of code.
    </Card>

    <Card title="Metrics APIs" icon="chart-line" href="/metrics-api/">
      Data lake-powered service providing aggregated metrics for dApps.
    </Card>

    <Card title="Webhooks API" icon="webhook" href="/webhooks-api/">
      Monitor real-time events on the Avalanche C-Chain and L1s.
    </Card>

    <Card title="Avacloud SDK" icon="code" href="/avacloud-sdk/">
      The Avalanche SDK offers all APIs, allowing developers to build and
      scale dApps with just a few lines of code.
    </Card>
  </CardGroup>
</div>

<div className="footer relative w-full flex-col items-center justify-end p-5">
  <div className="w-full flex items-center justify-center">
    <div className="footer-container flex items-center justify-center flex-wrap border-t border-gray-950/10 dark:border-white/10 p-5">
      <div className="item item-1">
        <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/logo/ava1anche-gray.svg" alt="Avalanche Logo" className="h-5" />
      </div>

      <div id="year" className="text-xs item item-2 flex justify-center">
        Crafted with ❤️ by Ava Labs Data & Tooling Team.
      </div>

      <div className="item item-3 flex flex-col justify-center align-end mt-7 h-8">
        <div class="flex space-x-6 justify-end">
          <a href="https://x.com/AvaxDevelopers" target="_blank">
            <span class="sr-only">x</span>

            <svg
              class="w-5 h-5 bg-gray-400 dark:bg-gray-500 hover:bg-gray-500 dark:hover:bg-gray-400"
              style={{
                              maskImage:
                                  'url("https://mintlify.b-cdn.net/v6.5.1/brands/x-twitter.svg")',
                              maskRepeat: "no-repeat",
                              maskPosition: "center center",
                          }}
            />
          </a>

          <a href="https://github.com/ava-labs" target="_blank">
            <span class="sr-only">github</span>

            <svg
              class="w-5 h-5 bg-gray-400 dark:bg-gray-500 hover:bg-gray-500 dark:hover:bg-gray-400"
              style={{
                              maskImage:
                                  'url("https://mintlify.b-cdn.net/v6.5.1/brands/github.svg")',
                              maskRepeat: "no-repeat",
                              maskPosition: "center center",
                          }}
            />
          </a>

          <a href="https://www.youtube.com/@Avalancheavax" target="_blank">
            <span class="sr-only">youtube</span>

            <svg
              class="w-5 h-5 bg-gray-400 dark:bg-gray-500 hover:bg-gray-500 dark:hover:bg-gray-400"
              style={{
                              maskImage:
                                  'url("https://mintlify.b-cdn.net/v6.5.1/brands/youtube.svg")',
                              maskRepeat: "no-repeat",
                              maskPosition: "center center",
                          }}
            />
          </a>

          <a href="https://discord.gg/avax" target="_blank">
            <span class="sr-only">discord</span>

            <svg
              class="w-5 h-5 bg-gray-400 dark:bg-gray-500 hover:bg-gray-500 dark:hover:bg-gray-400"
              style={{
                              maskImage:
                                  'url("https://mintlify.b-cdn.net/v6.5.1/brands/discord.svg")',
                              maskRepeat: "no-repeat",
                              maskPosition: "center center",
                          }}
            />
          </a>

          <a href="https://medium.com/@avaxdevelopers" target="_blank">
            <span class="sr-only">medium</span>

            <svg
              class="w-5 h-5 bg-gray-400 dark:bg-gray-500 hover:bg-gray-500 dark:hover:bg-gray-400"
              style={{
                              maskImage:
                                  'url("https://mintlify.b-cdn.net/v6.5.1/brands/medium.svg")',
                              maskRepeat: "no-repeat",
                              maskPosition: "center center",
                          }}
            />
          </a>
        </div>

        <div class="text-xs mt-3 flex justify-end pt-2">
          <a href="https://assets.website-files.com/602e8e4411398ca20cfcafd3/63fcbd915c5c221a21881075_API%20Terms%20of%20Service.pdf" target="_blank">
            Terms of Service
          </a>

          <span class="px-2"> | </span>

          <a href="https://www.avalabs.org/privacy-policy" target="_blank">
            Privacy Policy
          </a>
        </div>
      </div>
    </div>
  </div>
</div>


# Get metrics for EVM chains
Source: https://developers.avacloud.io/metrics-api/chain-metrics/get-metrics-for-evm-chains

get /v2/chains/{chainId}/metrics/{metric}
Gets metrics for an EVM chain over a specified time interval aggregated at the specified time-interval granularity.



# Get rolling window metrics for EVM chains
Source: https://developers.avacloud.io/metrics-api/chain-metrics/get-rolling-window-metrics-for-evm-chains

get /v2/chains/{chainId}/rollingWindowMetrics/{metric}
Gets the rolling window metrics for an EVM chain for the last hour, day, month, year, and all time.



# Get staking metrics for a given subnet
Source: https://developers.avacloud.io/metrics-api/chain-metrics/get-staking-metrics-for-a-given-subnet

get /v2/networks/{network}/metrics/{metric}
Gets staking metrics for a given subnet.



# Get teleporter metrics for EVM chains
Source: https://developers.avacloud.io/metrics-api/chain-metrics/get-teleporter-metrics-for-evm-chains

get /v2/chains/{chainId}/teleporterMetrics/{metric}
Gets teleporter metrics for an EVM chain.



# Get a list of supported blockchains
Source: https://developers.avacloud.io/metrics-api/evm-chains/get-a-list-of-supported-blockchains

get /v2/chains
Get a list of Metrics API supported blockchains.



# Get chain information for supported blockchain
Source: https://developers.avacloud.io/metrics-api/evm-chains/get-chain-information-for-supported-blockchain

get /v2/chains/{chainId}
Get chain information for Metrics API supported blockchain.



# Getting Started
Source: https://developers.avacloud.io/metrics-api/getting-started



The Metrics API is designed to be simple and accessible, requiring no authentication to get started. Just choose your endpoint, make your query, and instantly access on-chain data and analytics to power your applications.

The following query retrieves the daily count of active addresses on the Avalanche C-Chain(43114) over the course of one month (from August 1, 2024 12:00:00 AM to August 31, 2024 12:00:00 AM), providing insights into user activity on the chain for each day during that period. With this data you can use JavaScript visualization tools like Chart.js, D3.js, Highcharts, Plotly.js, or Recharts to create interactive and insightful visual representations.

```bash
curl --request GET \
  --url 'https://metrics.avax.network/v2/chains/43114/metrics/activeAddresses?startTimestamp=1722470400&endTimestamp=1725062400&timeInterval=day&pageSize=31'
```

Response:

```json
{
  "results": [
    {
      "value": 37738,
      "timestamp": 1724976000
    },
    {
      "value": 53934,
      "timestamp": 1724889600
    },
    {
      "value": 58992,
      "timestamp": 1724803200
    },
    {
      "value": 73792,
      "timestamp": 1724716800
    },
    {
      "value": 70057,
      "timestamp": 1724630400
    },
    {
      "value": 46452,
      "timestamp": 1724544000
    },
    {
      "value": 46323,
      "timestamp": 1724457600
    },
    {
      "value": 73399,
      "timestamp": 1724371200
    },
    {
      "value": 52661,
      "timestamp": 1724284800
    },
    {
      "value": 52497,
      "timestamp": 1724198400
    },
    {
      "value": 50574,
      "timestamp": 1724112000
    },
    {
      "value": 46999,
      "timestamp": 1724025600
    },
    {
      "value": 45320,
      "timestamp": 1723939200
    },
    {
      "value": 54964,
      "timestamp": 1723852800
    },
    {
      "value": 60251,
      "timestamp": 1723766400
    },
    {
      "value": 48493,
      "timestamp": 1723680000
    },
    {
      "value": 71091,
      "timestamp": 1723593600
    },
    {
      "value": 50456,
      "timestamp": 1723507200
    },
    {
      "value": 46989,
      "timestamp": 1723420800
    },
    {
      "value": 50984,
      "timestamp": 1723334400
    },
    {
      "value": 46988,
      "timestamp": 1723248000
    },
    {
      "value": 66943,
      "timestamp": 1723161600
    },
    {
      "value": 64209,
      "timestamp": 1723075200
    },
    {
      "value": 57478,
      "timestamp": 1722988800
    },
    {
      "value": 80553,
      "timestamp": 1722902400
    },
    {
      "value": 70472,
      "timestamp": 1722816000
    },
    {
      "value": 53678,
      "timestamp": 1722729600
    },
    {
      "value": 70818,
      "timestamp": 1722643200
    },
    {
      "value": 99842,
      "timestamp": 1722556800
    },
    {
      "value": 76515,
      "timestamp": 1722470400
    }
  ]
}
```

Congratulations! You’ve successfully made your first query to the Metrics API. 🚀🚀🚀


# Get the health of the service
Source: https://developers.avacloud.io/metrics-api/health-check/get-the-health-of-the-service

get /v2/health-check
Check the health of the service.



# Get addresses by balance over time
Source: https://developers.avacloud.io/metrics-api/looking-glass/get-addresses-by-balance-over-time

get /v2/chains/{chainId}/contracts/{address}/balances
Get list of addresses and their latest balances that have held more than a certain threshold of a given token during the specified time frame.



# Get addresses by BTCb bridged balance
Source: https://developers.avacloud.io/metrics-api/looking-glass/get-addresses-by-btcb-bridged-balance

get /v2/chains/43114/btcb/bridged:getAddresses
Get list of addresses and their net bridged amounts that have bridged more than a certain threshold.



# Get addresses running validators during a given time frame
Source: https://developers.avacloud.io/metrics-api/looking-glass/get-addresses-running-validators-during-a-given-time-frame

get /v2/subnets/{subnetId}/validators:getAddresses
Get list of addresses and AddValidatorTx timestamps set to receive awards for validation periods during the specified time frame.



# Overview
Source: https://developers.avacloud.io/metrics-api/overview



### What is the Metrics API?

The Metrics API equips web3 developers with a robust suite of tools to access and analyze on-chain activity across Avalanche’s primary network, Avalanche L1s, and other supported EVM chains. This API delivers comprehensive metrics and analytics, enabling you to seamlessly integrate historical data on transactions, gas consumption, throughput, staking, and more into your applications.

The Metrics API, along with the [Data API](/data-api) are the driving force behind every graph you see on the [Avalanche Explorer](https://subnets.avax.network/stats/). From transaction trends to staking insights, the visualizations and data presented are all powered by these APIs, offering real-time and historical insights that are essential for building sophisticated, data-driven blockchain products..

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/avalanche-explorer.png" />
</Frame>

### Features

* **Chain Throughput:** Retrieve detailed metrics on gas consumption, Transactions Per Second (TPS), and gas prices, including rolling windows of data for granular analysis.
* **Cumulative Metrics:** Access cumulative data on addresses, contracts, deployers, and transaction counts, providing insights into network growth over time.
* **Staking Information:** Obtain staking-related data, including the number of validators and delegators, along with their respective weights, across different subnets.
* **Blockchains and Subnets:** Get information about supported blockchains, including EVM Chain IDs, blockchain IDs, and subnet associations, facilitating multi-chain analytics.
* **Composite Queries:** Perform advanced queries by combining different metric types and conditions, enabling detailed and customizable data retrieval.

The Metrics API is designed to provide developers with powerful tools to analyze and monitor on-chain activity across Avalanche’s primary network, Avalanche L1s, and other supported EVM chains. Below is an overview of the key features available:

### Chain Throughput Metrics

* **Gas Consumption** <br />
  Track the average and maximum gas consumption per second, helping to understand network performance and efficiency.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/gas-used.png" />
  </Frame>

* **Transactions Per Second (TPS)** <br />
  Monitor the average and peak TPS to assess the network’s capacity and utilization.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/tps.png" />
  </Frame>

* **Gas Prices** <br />
  Analyze average and maximum gas prices over time to optimize transaction costs and predict fee trends.
  Monitor the average and peak TPS to assess the network’s capacity and utilization.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/gas-price.png" />
  </Frame>

### Cumulative Metrics

* **Address Growth** <br />
  Access the cumulative number of active addresses on a chain, providing insights into network adoption and user activity.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/address-growth.png" />
  </Frame>
* **Contract Deployment** <br />
  Monitor the cumulative number of smart contracts deployed, helping to gauge developer engagement and platform usage.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/contracts-deployed.png" />
  </Frame>
* **Transaction Count** <br />
  Track the cumulative number of transactions, offering a clear view of network activity and transaction volume.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/transactions.png" />
  </Frame>

### Staking Information

* **Validator and Delegator Counts** <br />
  Retrieve the number of active validators and delegators for a given L1, crucial for understanding network security and decentralization.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/validator-count.png" />
  </Frame>
* **Staking Weights** <br />
  Access the total stake weight of validators and delegators, helping to assess the distribution of staked assets across the network.
  <Frame>
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/staking-weight.png" />
  </Frame>

### Rolling Window Analytics

* **Short-Term and Long-Term Metrics:** Perform rolling window analysis on various metrics like gas used, TPS, and gas prices, allowing for both short-term and long-term trend analysis.
* **Customizable Time Frames:** Choose from different time intervals (hourly, daily, monthly) to suit your specific analytical needs.

### Blockchain and L1 Information

* **Chain and L1 Mapping:** Get detailed information about EVM chains and their associated L1s, including chain IDs, blockchain IDs, and subnet IDs, facilitating cross-chain analytics.

### Advanced Composite Queries

* **Custom Metrics Combinations**: Combine multiple metrics and apply logical operators to perform sophisticated queries, enabling deep insights and tailored analytics.
* **Paginated Results:** Handle large datasets efficiently with paginated responses, ensuring seamless data retrieval in your applications.

The Metrics API equips developers with the tools needed to build robust analytics, monitoring, and reporting solutions, leveraging the full power of multi-chain data across the Avalanche ecosystem and beyond.


# Rate Limits
Source: https://developers.avacloud.io/metrics-api/rate-limits



Rate limiting is managed through a weighted scoring system, known as Compute Units (CUs). Each API request consumes a specified number of CUs, determined by the complexity of the request. This system is designed to accommodate basic requests while efficiently handling more computationally intensive operations.

## Rate Limit Tiers

The maximum CUs (rate-limiting score) for a user depends on their subscription level and is delineated in the following table:

| Subscription Level | Per Minute Limit (CUs) | Per Day Limit (CUs) |
| :----------------- | :--------------------- | :------------------ |
| Free               | 8,000                  | 1,200,000           |

> We are working on new subscription tiers with higher rate limits to support even greater request volumes.

## Rate Limit Categories

The CUs for each category are defined in the following table:

{/* metrics weights value table start */}

| Weight | CU Value |
| :----- | :------- |
| Free   | 1        |
| Small  | 20       |
| Medium | 100      |
| Large  | 500      |
| XL     | 1000     |
| XXL    | 3000     |

{/* metrics weights value table end */}

## Rate Limits for Metrics Endpoints

The CUs for each route are defined in the table below:

{/* metrics execution weights table start */}

| Endpoint                                                    | Method | Weight | CU Value |
| :---------------------------------------------------------- | :----- | :----- | :------- |
| `/v2/health-check`                                          | GET    | Free   | 1        |
| `/v2/chains`                                                | GET    | Free   | 1        |
| `/v2/chains/{chainId}`                                      | GET    | Free   | 1        |
| `/v2/chains/{chainId}/metrics/{metric}`                     | GET    | Medium | 100      |
| `/v2/chains/{chainId}/teleporterMetrics/{metric}`           | GET    | Medium | 100      |
| `/v2/chains/{chainId}/rollingWindowMetrics/{metric}`        | GET    | Medium | 100      |
| `/v2/networks/{network}/metrics/{metric}`                   | GET    | Medium | 100      |
| `/v2/chains/{chainId}/contracts/{address}/nfts:listHolders` | GET    | Large  | 500      |
| `/v2/chains/{chainId}/contracts/{address}/balances`         | GET    | XL     | 1000     |
| `/v2/chains/43114/btcb/bridged:getAddresses`                | GET    | Large  | 500      |
| `/v2/subnets/{subnetId}/validators:getAddresses`            | GET    | Large  | 500      |
| `/v2/lookingGlass/compositeQuery`                           | POST   | XXL    | 3000     |

{/* metrics execution weights table end */}

<Info> All rate limits, weights, and CU values are subject to change. </Info>


# Usage Guide
Source: https://developers.avacloud.io/metrics-api/usage-guide



The Metrics API does not require authentication, making it straightforward to integrate into your applications. You can start making API requests without the need for an API key or any authentication headers.

#### Making Requests

You can interact with the Metrics API by sending HTTP GET requests to the provided endpoints. Below is an example of a simple `curl` request.

```bash
curl -H "Content-Type: Application/json" "https://metrics.avax.network/v1/avg_tps/{chainId}"
```

In the above request Replace `chainId` with the specific chain ID you want to query. For example, to retrieve the average transactions per second (TPS) for a specific chain (in this case, chain ID 43114), you can use the following endpoint:

```bash
curl "https://metrics.avax.network/v1/avg_tps/43114"
```

The API will return a JSON response containing the average TPS for the specified chain over a series of timestamps and `lastRun` is a timestamp indicating when the last data point was updated:

```json
{
  "results": [
    {"timestamp": 1724716800, "value": 1.98},
    {"timestamp": 1724630400, "value": 2.17},
    {"timestamp": 1724544000, "value": 1.57},
    {"timestamp": 1724457600, "value": 1.82},
    // Additional data points...
  ],
  "status": 200,
  "lastRun": 1724780812
}
```

### Rate Limits

Even though the Metrics API does not require authentication, it still enforces rate limits to ensure stability and performance. If you exceed these limits, the server will respond with a 429 Too Many Requests HTTP response code.

### Error Types

The API generates standard error responses along with error codes based on provided requests and parameters.

Typically, response codes within the `2XX` range signifies successful requests, while those within the `4XX` range points to errors originating from the client's side. Meanwhile, response codes within the `5XX` range indicates problems on the server's side.

The error response body is formatted like this:

```json
{
  "message": ["Invalid address format"], // route specific error message
  "error": "Bad Request", // error type
  "statusCode": 400 // http response code
}
```

Let's go through every error code that we can respond with:

| Error Code | Error Type            | Description                                                                                                                                                                                                                   |
| ---------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **400**    | Bad Request           | Bad requests generally mean the client has passed invalid or malformed parameters. Error messages in the response could help in evaluating the error.                                                                         |
| **401**    | Unauthorized          | When a client attempts to access resources that require authorization credentials but the client lacks proper authentication in the request, the server responds with 401.                                                    |
| **403**    | Forbidden             | When a client attempts to access resources with valid credentials but doesn't have the privilege to perform that action, the server responds with 403.                                                                        |
| **404**    | Not Found             | The 404 error is mostly returned when the client requests with either mistyped URL, or the passed resource is moved or deleted, or the resource doesn't exist.                                                                |
| **500**    | Internal Server Error | The 500 error is a generic server-side error that is returned for any uncaught and unexpected issues on the server side. This should be very rare, and you may reach out to us if the problem persists for a longer duration. |
| **502**    | Bad Gateway           | This is an internal error indicating invalid response received by the client-facing proxy or gateway from the upstream server.                                                                                                |
| **503**    | Service Unavailable   | The 503 error is returned for certain routes on a particular Subnet. This indicates an internal problem with our Subnet node, and may not necessarily mean the Subnet is down or affected.                                    |

### Pagination

For endpoints that return large datasets, the Metrics API employs pagination to manage the results. When querying for lists of data, you may receive a nextPageToken in the response, which can be used to request the next page of data.

Example response with pagination:

```json
{
  "results": [...],
  "nextPageToken": "3d22deea-ea64-4d30-8a1e-c2a353b67e90"
}
```

To retrieve the next set of results, include the nextPageToken in your subsequent request:

```bash
curl -H "Content-Type: Application/json" \
  "https://metrics.avax.network/v1/avg_tps/{chainId}?pageToken=3d22deea-ea64-4d30-8a1e-c2a353b67e90"
```

### Pagination Details

#### Page Token Structure

The `nextPageToken` is a UUID-based token provided in the response when additional pages of data are available. This token serves as a pointer to the next set of data.

* **UUID Generation**: The `nextPageToken` is generated uniquely for each pagination scenario, ensuring security and ensuring predictability.
* **Expiration**: The token is valid for 24 hours from the time it is generated. After this period, the token will expire, and a new request starting from the initial page will be required.
* **Presence**: The token is only included in the response when there is additional data available. If no more data exists, the token will not be present.

#### Integration and Usage

To use the pagination system effectively:

* Check if the `nextPageToken` is present in the response.
* If present, include this token in the subsequent request to fetch the next page of results.
* Ensure that the follow-up request is made within the 24-hour window after the token was generated to avoid token expiration.

By utilizing the pagination mechanism, you can efficiently manage and navigate through large datasets, ensuring a smooth data retrieval process.

### Swagger API Reference

You can explore the full API definitions and interact with the endpoints in the Swagger documentation at:

<CardGroup cols={1}>
  <Card title="Swagger API Reference" icon="brackets-curly">
    [https://metrics.avax.network/api](https://metrics.avax.network/api)
  </Card>
</CardGroup>


# Track ERC-20 Transfers
Source: https://developers.avacloud.io/webhooks-api/erc20-transfers



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/](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 identify `Transfer` events. The example below illustrates how to set up filtering to receive transfer events.

In this example, we will monitor all the USDT transfers on the C-chain. If we go to any block explorer, select a USDT transaction, and look at `Topic 0` from the transfer event, we can get the signature.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/function-signature.png" />
</Frame>

With the event signature, we can create the webhook as follows:

```bash
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": ["0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"],
       "eventSignatures": [
           "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        ]
   },
   "name": "USDT",
   "description": "USDT"
}'
```

Once the the webhook is created we start receiving the events:

```json
{
  "webhookId": "401da7d9-d6d7-46c8-b431-72ff1e1543f4",
  "eventType": "address_activity",
  "messageId": "bc9732db-2430-4296-afc3-c51267beb14a",
  "event": {
    "transaction": {
      "blockHash": "0x2a47bebed93db4a21cc8339980f004cc67f17d0dff4a368001e450e7be2edaa0",
      "blockNumber": "45396106",
      "from": "0x737F6b0b8A04e8462d0fC7076451298F0dA9a972",
      "gas": "80000",
      "gasPrice": "52000000000",
      "maxFeePerGas": "52000000000",
      "maxPriorityFeePerGas": "2000000000",
      "txHash": "0xfd91150d236ec5c3b1ee325781affad5b0b4d7eb0187c84c220ab115eaa563e8",
      "txStatus": "1",
      "input": "0xa9059cbb00000000000000000000000040e832c3df9562dfae5a86a4849f27f687a9b46b00000000000000000000000000000000000000000000000000000000c68b2a69",
      "nonce": "2",
      "to": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7",
      "transactionIndex": 2,
      "value": "0",
      "type": 2,
      "chainId": "43114",
      "receiptCumulativeGasUsed": "668508",
      "receiptGasUsed": "44038",
      "receiptEffectiveGasPrice": "27000000000",
      "receiptRoot": "0xe5b018c29a77c8a92c4ea2f2d7e58820283041a52e14a0620d90d13b881e1ee3",
      "erc20Transfers": [
        {
          "transactionHash": "0xfd91150d236ec5c3b1ee325781affad5b0b4d7eb0187c84c220ab115eaa563e8",
          "type": "ERC20",
          "from": "0x737F6b0b8A04e8462d0fC7076451298F0dA9a972",
          "to": "0x40E832C3Df9562DfaE5A86A4849F27F687A9B46B",
          "value": "3331009129",
          "blockTimestamp": 1715621840,
          "logIndex": 0,
          "erc20Token": {
            "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
            "name": "TetherToken",
            "symbol": "USDt",
            "decimals": 6,
            "valueWithDecimals": "3331.009129"
          }
        }
      ],
      "erc721Transfers": [],
      "erc1155Transfers": [],
      "internalTransactions": [
        {
          "from": "0x737F6b0b8A04e8462d0fC7076451298F0dA9a972",
          "to": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "44038",
          "gasLimit": "80000",
          "transactionHash": "0xfd91150d236ec5c3b1ee325781affad5b0b4d7eb0187c84c220ab115eaa563e8"
        },
        {
          "from": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
          "to": "0xBA2a995Bd4ab9e605454cCEf88169352cd5F75A6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "15096",
          "gasLimit": "50301",
          "transactionHash": "0xfd91150d236ec5c3b1ee325781affad5b0b4d7eb0187c84c220ab115eaa563e8"
        }
      ],
      "blockTimestamp": 1715621840
    },
    "logs": [
      {
        "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x000000000000000000000000737f6b0b8a04e8462d0fc7076451298f0da9a972",
        "topic2": "0x00000000000000000000000040e832c3df9562dfae5a86a4849f27f687a9b46b",
        "topic3": null,
        "data": "0x00000000000000000000000000000000000000000000000000000000c68b2a69",
        "transactionIndex": 2,
        "logIndex": 19,
        "removed": false
      }
    ]
  }
}
```


# Track ERC-721 Transfers
Source: https://developers.avacloud.io/webhooks-api/erc721-transfers



In this tutorial, we build upon the previous in which we tracked ERC20 transfers. To monitor NFT transfers, we will utilize the event signature. If you wish to receive a notification every time a Dokyo NFT is transferred, you can use an expression similar to the following:

```bash
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:

```json
{
  "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
      }
    ]
  }
}
```


# Ethers vs Webhooks
Source: https://developers.avacloud.io/webhooks-api/ethers-vs-webhooks



Reacting to real-time events from Avalanche smart contracts allows for immediate responses and automation, improving user experience and streamlining application functionality. It ensures that applications stay synchronized with the blockchain state.

This article demonstrates how to monitor smart contract events using Ethers.js and Webhooks. The comparison shows that webhooks are easier and faster to integrate, delivering better uptime and reliability.

## Why webhooks

* Get everything you need in the payload, there is no need for extra requests
* There is no complicated logic to handle disconnections and to re-sync and recover missed blocks or transactions.
* Reduce complexity, cost, and time to market.

Ethers.js Blockchain Listener

```javascript
const ethers = require("ethers");
const ABI = require("./usdc-abi.json");
require("dotenv").config();

const NODE_URL = "wss://api.avax.network/ext/bc/C/ws";

async function getTransfer() {
    try {
        const usdcAddress = "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"; // USDC contract
        const network = new ethers.Network("avalanche", 43114);
        const provider = new ethers.WebSocketProvider(NODE_URL, network);
        const contract = new ethers.Contract(usdcAddress, ABI, provider);

        contract.on("Transfer", (from, to, value, event) => {
            let transferEvent = {
                from: from,
                to: to,
                value: value,
                eventData: event
            };
            console.log("*******");
            console.log(transferEvent);
            console.log(">>>>>Event Data:", transferEvent.eventData);

        });

    } catch (error) {
        console.error("Error:", error.message);
    }
}
```

Output

```json
{
  from: '0xfD93389fc075ff66045361423C2df68119c086Ab',
  to: '0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640',
  value: 9999999999n,
  eventData: ContractEventPayload {
    filter: 'Transfer',
    emitter: Contract {
      target: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      interface: [Interface],
      runner: WebSocketProvider {},
      filters: {},
      fallback: null,
      [Symbol(_ethersInternal_contract)]: {}
    },
    log: EventLog {
      provider: WebSocketProvider {},
      transactionHash: '0x5f90569fd43a894a01c3f85067ad509567498e95efeefc826b97d30b9086d1f9',
      blockHash: '0x8c99e8555249b2460b7e50ef987d126655efb8bd6332512f010941567fa3f0b3',
      blockNumber: 19744421,
      removed: false,
      address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      data: '0x00000000000000000000000000000000000000000000000000000002540be3ff',
      topics: [Array],
      index: 17,
      transactionIndex: 2,
      interface: [Interface],
      fragment: [EventFragment],
      args: [Result]
    },
    args: Result(3) [
      '0xfD93389fc075ff66045361423C2df68119c086Ab',
      '0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640',
      9999999999n
    ],
    fragment: EventFragment {
      type: 'event',
      inputs: [Array],
      name: 'Transfer',
      anonymous: false
    }
  }
}
```

Get undecoded raw data and then you need to call other API endpoints to get more data, for example, to get the current balance you need to make an API call, to get the token decimals you need to make an API call, to get the logo you need to make an API, you get it.

<Tip> **Webhooks offer key advantages over manual parsing** <br />
They provide real-time updates, reduce resource use, and enhance efficiency, allowing users to focus on building around these events rather than parsing data.</Tip>

Listening to the same contract using Webhooks

```json
{
  "webhookId": "c737d18a-fb40-4268-8efe-7154e73df604",
  "eventType": "address_activity",
  "messageId": "e5e2fc96-9aa3-43a1-9969-79f0830fe0ee",
  "event": {
    "transaction": {
      "blockHash": "0xbc6ee8c2213262bc25dc2624bf4268e0583efa173bf9812ae888f15875cf0af1",
      "blockNumber": "45689091",
      "from": "0x3D3Bd891E386bFb248A9edC52cB35889ac003Db8",
      "gas": "66372",
      "gasPrice": "26000000000",
      "maxFeePerGas": "26000000000",
      "maxPriorityFeePerGas": "26000000000",
      "txHash": "0x1d8f3c4f99191aec5e7cc10c58551e04e2f9ceaf5dc311b3828ab5b93435921d",
      "txStatus": "1",
      "input": "0xa9059cbb000000000000000000000000ffb3118124cdaebd9095fa9a479895042018cac20000000000000000000000000000000000000000000000000000000006970300",
      "nonce": "0",
      "to": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7",
      "transactionIndex": 7,
      "value": "0",
      "type": 0,
      "chainId": "43114",
      "receiptCumulativeGasUsed": "651035",
      "receiptGasUsed": "44026",
      "receiptEffectiveGasPrice": "26000000000",
      "receiptRoot": "0x455be081717eed467de449ad5cd8075caf23f2d52acbd0fc4489aff7bedcddbf",
      "erc20Transfers": [
        {
          "transactionHash": "0x1d8f3c4f99191aec5e7cc10c58551e04e2f9ceaf5dc311b3828ab5b93435921d",
          "type": "ERC20",
          "from": "0x3D3Bd891E386bFb248A9edC52cB35889ac003Db8",
          "to": "0xffB3118124cdaEbD9095fA9a479895042018cac2",
          "value": "110560000",
          "blockTimestamp": 1716238687,
          "logIndex": 0,
          "erc20Token": {
            "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
            "name": "TetherToken",
            "symbol": "USDt",
            "decimals": 6,
            "valueWithDecimals": "110.56"
          }
        }
      ],
      "erc721Transfers": [],
      "erc1155Transfers": [],
      "internalTransactions": [
        {
          "from": "0x3D3Bd891E386bFb248A9edC52cB35889ac003Db8",
          "to": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "44026",
          "gasLimit": "66372",
          "transactionHash": "0x1d8f3c4f99191aec5e7cc10c58551e04e2f9ceaf5dc311b3828ab5b93435921d"
        },
        {
          "from": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
          "to": "0xBA2a995Bd4ab9e605454cCEf88169352cd5F75A6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "15096",
          "gasLimit": "36898",
          "transactionHash": "0x1d8f3c4f99191aec5e7cc10c58551e04e2f9ceaf5dc311b3828ab5b93435921d"
        }
      ],
      "blockTimestamp": 1716238687
    },
    "logs": [
      {
        "address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
        "topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "topic1": "0x0000000000000000000000003d3bd891e386bfb248a9edc52cb35889ac003db8",
        "topic2": "0x000000000000000000000000ffb3118124cdaebd9095fa9a479895042018cac2",
        "topic3": null,
        "data": "0x0000000000000000000000000000000000000000000000000000000006970300",
        "transactionIndex": 7,
        "logIndex": 14,
        "removed": false
      }
    ]
  }
}
```

### Listening to native transactions

To monitor native transactions for specific addresses in an Ethereum blockchain, you need to follow these steps:

1. Listen for Every New Block: Set up a listener for new blocks.
2. Go Through All Transactions in Each Block: For each block, iterate through all transactions.
3. Check If from or to Matches Your List of Addresses: Filter the transactions to see if either the sender (from) or the recipient (to) matches your list of addresses.
4. Handle Transactions: Implement logic to handle the transactions that match your criteria.

### How webhooks are better Than Ethers.js

Ethers.js is a good alternative for setting blockchain listeners to monitor smart contract events. However, if you start working with this library, you will quickly notice its limitations.

| Feature                    | Ethers/web3.js | Webhooks |
| :------------------------- | :------------- | :------- |
| Real-time events           | Yes            | Yes      |
| Enriched payload           | No             | Yes      |
| 100% reliability           | No             | Yes      |
| Multiple addresses         | No             | Yes      |
| Listen to wallet addresses | No             | Yes      |

### Resume capabilities

Ethers.js does not natively support resuming operations if the connection is interrupted. When this happens, the blockchain continues to add new blocks, and any blocks that were added during the downtime can be missed. To address this, developers must implement custom code to track the last processed block and manually resume from that point to ensure no data is lost.

In contrast, Webhooks are designed to handle interruptions more gracefully. They typically have built-in mechanisms to ensure that events are not lost, even if the connection is disrupted. When the connection is restored, Webhooks can automatically resume from where they left off, ensuring that no events are missed without requiring additional custom code. This makes Webhooks a more reliable solution for continuous data processing and real-time event handling.


# Getting Started
Source: https://developers.avacloud.io/webhooks-api/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/](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](https://app.avacloud.io/) and click on **Web3 Data API**
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`.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/create-webhook-ui.png" />
</Frame>

4. Click **Create** and go to \`[https://webhook.site/](https://webhook.site/), you should see something like this:

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/webhook-site.png" />
</Frame>

## Managing webhooks using Glacier API

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

1. Navigate to the [Avacloud Dashboard](https://app.avacloud.io/) and click on **Web3 Data API**
2. Click on **Add API Key**
3. Copy your API key and use it to create a webhook. For example:

```bash
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 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/](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:

```javascript
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:

```shell
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:
```

```shell
./ngrok http 8000
```

You should see something like this:

```bash
ngrok                                                                                                                                                                           (Ctrl+C to quit)

Take our ngrok in production survey! https://forms.gle/aXiBFWzEA36DudFn6

Session Status                online
Account                       javier.toledo@avalabs.org (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 we 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:

```json
{
  "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
      }
    ]
  }
}
```


# Monitoring multiple addresses
Source: https://developers.avacloud.io/webhooks-api/multiple



A single webhook can monitor multiple addresses, you don't need to create one webhook per address.

<Note>In the free plan, you add up to 5 addresses per webhook. If you need more than that you can upgrade your plan.</Note>

### Creating the webhook

Let's start by creating a new webhook to monitor all USDC and USDT activity:

```bash
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/4eb31e6c-a088-4dcb-9a5d-e9341624b584",
    "chainId": "43114",
    "eventType": "address_activity",
    "includeInternalTxs": true,
    "includeLogs": true,
    "metadata": {
        "addresses": [
            "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
            "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
            ]
    },
    "name": "Tokens",
    "description": "Track tokens"
}
```

It returns the following:

```json
{
    "id": "401da7d9-d6d7-46c8-b431-72ff1e1543f4",
    "eventType": "address_activity",
    "chainId": "43114",
    "metadata": {
        "addresses": [
            "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
            "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
        ]
    },
    "includeInternalTxs": true,
    "includeLogs": true,
    "url": "https://webhook.site/4eb31e6c-a088-4dcb-9a5d-e9341624b584",
    "status": "active",
    "createdAt": 1715621587726,
    "name": "Tokens",
    "description": "Track tokens"
}
```

### Adding addresses to monitor

With the webhook `id` we can add more addresses. In this case, let's add the contract addresses for JOE and PNG:

```bash
curl --location --request PATCH 'https://glacier-api.avax.network/v1/webhooks/401da7d9-d6d7-46c8-b431-72ff1e1543f4/addresses' \
--header 'x-glacier-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "addresses": [
            "0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd",
            "0x60781C2586D68229fde47564546784ab3fACA982"
  ]
}
```

Following that, we will begin to receive events from the four smart contracts integrated into the webhook: USDC, USDT, JOE, and PNG.

### Deleting addresses

To remove addresses, simply send an array:

```bash
curl --location --request DELETE 'https://glacier-api.avax.network/v1/webhooks/401da7d9-d6d7-46c8-b431-72ff1e1543f4/addresses' \
--header 'x-glacier-api-key: <YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "addresses": [
    "0x735D8f3B6A5d2c96D0405230c50Eaf96794FbB88"
  ]
}
```


# Overview
Source: https://developers.avacloud.io/webhooks-api/overview



### What is the Glacier Webhooks?

With Glacier Webhooks, you can monitor real-time events on the Avalanche C-chain and L1s. For example, you can monitor smart contract events, track NFT transfers, and observe wallet-to-wallet transactions.

![webhooks](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/webhooks.png)

### Key Features:

* **Real-time notifications**: Receive immediate updates on specified on-chain activities without polling.
* **Customizable**: Specify the desired event type to listen for, customizing notifications according to individual requirements.
* **Secure**: Employ shared secrets and signature-based verification to guarantee that notifications originate from a trusted source.
* **Broad Coverage**: Support for C-chain mainnet, testnet, and L1s within the Avalanche ecosystem, ensuring wide-ranging monitoring capabilities.

### Use cases

* **NFT Marketplace Transactions**: Get alerts for NFT minting, transfers, auctions, bids, sales, and other interactions within NFT marketplaces.
* **Wallet Notifications**: Receive alerts when an address performs actions such as sending, receiving, swapping, or burning assets.
* **DeFi Activities**: Receive notifications for various DeFi activities such as liquidity provisioning, yield farming, borrowing, lending, and liquidations.

### What are Webhooks?

A webhook is a communication mechanism to provide applications with real-time information. It delivers data to other applications as it happens, meaning you get data immediately, unlike typical APIs where you would need to poll for data to get it in "real-time". This makes webhooks much more efficient for both providers and consumers. Webhooks work by registering a URL to send notifications once certain events occur.
You can create receiver endpoints in your server in any programming language and those will have an associated URL (e.g. [https://myserver.com/callback](https://myserver.com/callback)). This object contains all the relevant information about what just happened, including the type of event and the data associated with that event.

<Note>
  **Webhooks vs. WebSockets:**\
  The difference between webhooks and WebSockets is that webhooks can only facilitate one-way communication between two services. In contrast, WebSockets can facilitate two-way communication between a user and a service, recognizing events and displaying them to the user as they occur.
</Note>

### Event structure

The Event structure always begins with the following parameters:

```json
{
  "webhookId": "6d1bd383-aa8d-47b5-b793-da6d8a115fde",
  "eventType": "address_activity",
  "messageId": "8e4e7284-852a-478b-b425-27631c8d22d2",
  "event": {
  }
}
```

**Parameters:**

* `webhookId`: Unique identifier for the webhook in your account.
* `eventType`: The event that caused the webhook to be triggered. In the future, there will be multiple types of events, for the time being only the address\_activity event is supported. The address\_activity event gets triggered whenever the specified addresses participate in a token or AVAX transaction.
* `messageId`: Unique identifier per event sent.
* `event`: Event payload. It contains details about the transaction, logs, and traces. By default logs and internal transactions are not included, if you want to include them use `"includeLogs": true`, and `"includeInternalTxs": true`.

### Address Activity webhook

The address activity webhook allows you to track any interaction with an address (any address). Here is an example of this type of event:

```json
{
  "webhookId": "263942d1-74a4-4416-aeb4-948b9b9bb7cc",
  "eventType": "address_activity",
  "messageId": "94df1881-5d93-49d1-a1bd-607830608de2",
  "event": {
    "transaction": {
      "blockHash": "0xbd093536009f7dd785e9a5151d80069a93cc322f8b2df63d373865af4f6ee5be",
      "blockNumber": "44568834",
      "from": "0xf73166f0c75a3DF444fAbdFDC7e5EE4a73fA51C7",
      "gas": "651108",
      "gasPrice": "31466275484",
      "maxFeePerGas": "31466275484",
      "maxPriorityFeePerGas": "31466275484",
      "txHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4",
      "txStatus": "1",
      "input": "0xb80c2f090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e000000000000000000000000000000000000000000000000006ca0c737b131f2000000000000000000000000000000000000000000000000000000000011554e000000000000000000000000000000000000000000000000000000006627dadc0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000006ca0c737b131f2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000be882fb094143b59dc5335d32cecb711570ebdd40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000be882fb094143b59dc5335d32cecb711570ebdd400000000000000000000000000000000000000000000000000000000000000010000000000000000000027100e663593657b064e1bae76d28625df5d0ebd44210000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c7000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e0000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000000000000000000000",
      "nonce": "4",
      "to": "0x1dac23e41fc8ce857e86fd8c1ae5b6121c67d96d",
      "transactionIndex": 0,
      "value": "30576074978046450",
      "type": 0,
      "chainId": "43114",
      "receiptCumulativeGasUsed": "212125",
      "receiptGasUsed": "212125",
      "receiptEffectiveGasPrice": "31466275484",
      "receiptRoot": "0xf355b81f3e76392e1b4926429d6abf8ec24601cc3d36d0916de3113aa80dd674",
      "erc20Transfers": [
        {
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4",
          "type": "ERC20",
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "value": "30576074978046450",
          "blockTimestamp": 1713884373,
          "logIndex": 2,
          "erc20Token": {
            "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "valueWithDecimals": "0.030576074978046448"
          }
        },
        {
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4",
          "type": "ERC20",
          "from": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "to": "0xf73166f0c75a3DF444fAbdFDC7e5EE4a73fA51C7",
          "value": "1195737",
          "blockTimestamp": 1713884373,
          "logIndex": 3,
          "erc20Token": {
            "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
            "name": "USD Coin",
            "symbol": "USDC",
            "decimals": 6,
            "valueWithDecimals": "1.195737"
          }
        },
        {
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4",
          "type": "ERC20",
          "from": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "to": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "value": "30576074978046450",
          "blockTimestamp": 1713884373,
          "logIndex": 4,
          "erc20Token": {
            "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
            "name": "Wrapped AVAX",
            "symbol": "WAVAX",
            "decimals": 18,
            "valueWithDecimals": "0.030576074978046448"
          }
        }
      ],
      "erc721Transfers": [],
      "erc1155Transfers": [],
      "internalTransactions": [
        {
          "from": "0xf73166f0c75a3DF444fAbdFDC7e5EE4a73fA51C7",
          "to": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "internalTxType": "CALL",
          "value": "30576074978046450",
          "gasUsed": "212125",
          "gasLimit": "651108",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xF2781Bb34B6f6Bb9a6B5349b24de91487E653119",
          "internalTxType": "DELEGATECALL",
          "value": "30576074978046450",
          "gasUsed": "176417",
          "gasLimit": "605825",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "9750",
          "gasLimit": "585767",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "to": "0x30DFE0469803BcE76F8F62aC24b18d33D3d6FfE6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "2553",
          "gasLimit": "569571",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "CALL",
          "value": "30576074978046450",
          "gasUsed": "23878",
          "gasLimit": "566542",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "25116",
          "gasLimit": "540114",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "81496",
          "gasLimit": "511279",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "491",
          "gasLimit": "501085",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "to": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "74900",
          "gasLimit": "497032",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "to": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "32063",
          "gasLimit": "463431",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "to": "0x30DFE0469803BcE76F8F62aC24b18d33D3d6FfE6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "31363",
          "gasLimit": "455542",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "2491",
          "gasLimit": "430998",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "to": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "7591",
          "gasLimit": "427775",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xbe882fb094143B59Dc5335D32cEcB711570EbDD4",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "CALL",
          "value": "0",
          "gasUsed": "6016",
          "gasLimit": "419746",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x0E663593657B064e1baE76d28625Df5D0eBd4421",
          "to": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "491",
          "gasLimit": "419670",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "3250",
          "gasLimit": "430493",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "to": "0x30DFE0469803BcE76F8F62aC24b18d33D3d6FfE6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "2553",
          "gasLimit": "423121",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0x1daC23e41Fc8ce857E86fD8C1AE5b6121C67D96d",
          "to": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "internalTxType": "STATICCALL",
          "value": "0",
          "gasUsed": "1250",
          "gasLimit": "426766",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        },
        {
          "from": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
          "to": "0x30DFE0469803BcE76F8F62aC24b18d33D3d6FfE6",
          "internalTxType": "DELEGATECALL",
          "value": "0",
          "gasUsed": "553",
          "gasLimit": "419453",
          "transactionHash": "0xf6a791920652e87ccc91d2f1b20c1505a94452b88f359acdeb5a6fa8205638c4"
        }
      ],
      "blockTimestamp": 1713884373
    }
  }
}
```

<Note>In the free plan webhooks are automatically disabled after delivering 10 consecutive unsuccessful events.</Note>


# Platform Webhooks
Source: https://developers.avacloud.io/webhooks-api/platform-webhooks



### Why Use Avalanche Platform Webhooks?

Avalanche Platform Webhooks enable developers to monitor activities on the P and X chains with the following advantages:

Real-time notifications: Receive updates as events occur.
Reduced overhead: Eliminate the need for constant blockchain polling.
Customizable monitoring: Subscribe to specific events and apply filters tailored to your needs.
Support for multiple sub-events: Track related activities within a single webhook subscription.
These features make webhooks ideal for building responsive applications, such as wallet trackers, staking monitors, or validator management tools.

## Understanding webhook event types

Avalanche Platform Webhooks support two main event types, each with specific **sub-events** you can subscribe to:

* **Address activity**: Tracks balance-related changes and reward distributions for P/X chain addresses.
* **Validator activity**: Monitors validator registration, balance updates, and reward distributions.

### Address activity

Tracks activities for specific addresses on the P or X chains.
![Address activity](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/address_activity.png)

* **Sub-events:**
  * `balance_change:`Triggered whenever a transaction affects the balance of the tracked addresses.
  * `balance_threshold:`Triggered when the balance of a tracked address falls below a specified threshold for a particular balance type. The balance must transition from above the threshold to below it.
  * `reward_distribution:`Triggered when a tracked address receives a reward UTXO (e.g., staking or validator rewards).

### Validator activity

Tracks activities related to validators, identified by `NodeIDs` or `SubnetIDs`.
![Validator activity](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/validator_activity.png)

* **Sub-events:**
  * `validator_registration:`Triggered when a validator registers on a specified subnet or node.
  * `reward_distribution:`Triggered when a validator or delegator receives a reward, monitored by `NodeID` or `SubnetID`.
  * `l1_validator_balance_increased:`Triggered when an L1 validator’s balance increases via a specific transaction.
  * `l1_validator_disabled:`Triggered when an L1 validator is marked inactive (e.g., due to insufficient balance or a disable transaction).
  * `l1_validator_removed:`Triggered when an L1 validator is removed from the validator set.
  * `l1_validator_threshold_reached:`Triggered when an L1 validator’s balance falls below a specified threshold.

**Pro Tip:** You can subscribe to multiple sub-events in a single webhook, reducing the number of subscriptions you need to manage.

## Understanding balance types

On the P and X chains, addresses can hold assets in various states, referred to as balance types. These are essential for configuring events like BALANCE\_THRESHOLD\_PLATFORM. Below is a summary:

* `unlockedUnstaked:`Assets neither locked nor staked; immediately available for transactions.
* `unlockedStaked:`Assets previously staked, now unlocked and available.
* `lockedPlatform:`Unstaked assets locked at the platform level (not immediately usable).
* `lockedStakeable:`Locked assets usable only for staking.
* `lockedStaked:`Staked assets that remain locked post-staking period.
* `pendingStaked:`Assets committed to staking, awaiting the staking period start.
* `atomicMemoryUnlocked:`Unlocked assets in atomic memory (for cross-chain transfers).
* `atomicMemoryLocked:`Locked assets in atomic memory.

Understanding these types helps you set precise thresholds and interpret balance-related webhook data. For detailed definitions, refer to the [API documentation](https://developers.avacloud.io/data-api/primary-network-balances/get-balances#response-balances)

***

## Setting Up a Webhook

To get started, you'll use the **Glacier API** to create your webhook. Authentication is required, so you'll need an API key (the Pro API key supports up to 12 active webhooks).

### Step 1: Prepare Your Tools

You can create a webhook using:

* **curl**: A command-line tool to send HTTP requests.
* **Swagger UI**: A browser-based interface for interacting with the Glacier API.

### Step 2: Create Your Request

Here’s how to set up a webhook using curl:

```bash
curl -X 'POST' \
  'https://glacier-api-dev.avax.network/v1/webhooks' \
  -H 'accept: application/json' \
  -H 'x-glacier-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d 'YOUR_JSON_PAYLOAD'
```

Replace `YOUR_API_KEY` with your Glacier API key.
Replace `YOUR_JSON_PAYLOAD` with the JSON configuration for your webhook (examples below).
Alternatively, use the Glacier Dev Swagger UI:

Open the Swagger UI in your browser.
Click Authorize (top right) and input your API key.
Navigate to the `/v1/webhooks` endpoint, enter your JSON payload, and submit.
Creating a Webhook: Examples
Example 1: Tracking Address Activity (`PLATFORM_ADDRESS_ACTIVITY`)
This webhook monitors balance changes, thresholds, and rewards for a specific address on the P-Chain.

```json
{
  "url": "https://your-webhook-endpoint.com",
  "chainId": "p-chain",
  "eventType": "platform_address_activity",
  "network": "fuji",
  "name": "Address Activity Monitor",
  "description": "Tracks activity for my P-Chain address.",
  "metadata": {
    "keyType": "addresses",
    "keys": ["fuji1aerex08szh4ge5g7sggsddkpdhyzhja9f6v7y0"],
    "subEvents": {
      "addressActivitySubEvents": [
        "balance_change_platform",
        "balance_threshold_platform",
        "reward_distribution"
      ]
    },
    "balanceThresholdFilter": {
      "balanceType": "unlockedUnstaked",
      "balanceThreshold": "5500000000"
    }
  }
}
```

Key Fields Explained

* `url`: Where notifications will be sent.
* `chainId`: The chain to monitor ("p-chain" or "x-chain").
* `eventType`: Set to "platform\_address\_activity".
* `network`: "fuji" (testnet) or "mainnet".
* `metadata.keys`: The address(es) you’re tracking.
* `metadata.subEvents`: The sub-events you want to monitor.
* `metadata.balanceThresholdFilter`: Triggers BALANCE\_THRESHOLD\_PLATFORM if the "unlockedUnstaked" balance falls below 5.5 AVAX (5,500,000,000 nAVAX).

### Example 2: Tracking Validator Activity

This webhook monitors a validator’s NodeID for various events.

```json
{
  "url": "https://your-webhook-endpoint.com",
  "chainId": "p-chain",
  "eventType": "validator_activity",
  "network": "fuji",
  "name": "Validator Monitor",
  "description": "Tracks my validator’s activity.",
  "metadata": {
    "keyType": "nodeId",
    "keys": ["NodeID-H8AkDZHd6Jczcc1v8aVDLb5haQYPkGxqt"],
    "subEvents": {
      "validatorActivitySubEvents": [
        "validator_registration",
        "reward_distribution",
        "l1_validator_balance_increase",
        "l1_validator_balance_threshold",
        "l1_validator_disabled",
        "l1_validator_removed"
      ]
    },
    "subnetIds": ["11111111111111111111111111111111LpoYY"],
    "l1ValidatorFeeBalanceThreshold": "5000000000"
  }
}
```

Key Fields Explained

* `metadata.keyType`: Set to `nodeId` or `subnetId`.
* `metadata.keys`: The `NodeID` to track (only one key allowed).
* `metadata.subnetIds`: Filters events to a specific subnet (optional).
* `metadata.l1ValidatorFeeBalanceThreshold`: Triggers if the L1 validator’s balance drops below 5 AVAX.

### Example 3: Monitor all the validators in the primary network

To monitor all validators on the Primary Network:

```json
{
  "url": "https://your-webhook-endpoint.com",
  "chainId": "p-chain",
  "eventType": "validator_activity",
  "network": "mainnet",
  "name": "Primary Network Validators",
  "description": "Tracks validator registrations and rewards.",
  "metadata": {
    "keyType": "subnetId",
    "keys": ["11111111111111111111111111111111LpoYY"],
    "subEvents": {
      "validatorActivitySubEvents": [
        "validator_registration",
        "reward_distribution",
        "l1_validator_balance_increased",
        "l1_validator_disabled",
        "l1_validator_removed"
      ]
    }
  }
}
```

***

### What Data Will You Receive?

When an event triggers your webhook, you’ll receive a JSON payload with details about the event. Here’s what to expect for each sub-event:

### Address Activity

#### Balance change

This notification describes a successful import of 5 AVAX from the c-chain to the P-chain for the address `fuji1xp395ktf5kqfv9qyv2astt6fhnc4605pqwrf40`.

```json
{
	"webhookId": "c16f9dd6-9e07-49cd-bee2-7770cd797278",
	"eventType": "platform_address_activity",
	"messageId": "5101a28a-da03-479f-a0f9-6499014689bc",
	"event": {
		"eventType": "balance_change",
		"addresses": [
			"fuji1xp395ktf5kqfv9qyv2astt6fhnc4605pqwrf40"
		],
		"timestamp": 1742409843,
		"initialBalance": {
			"balances": {
				"unlockedStaked": [

				],
				"unlockedUnstaked": [

				],
				"lockedStaked": [

				],
				"lockedPlatform": [

				],
				"lockedStakeable": [

				],
				"pendingStaked": [

				],
				"atomicMemoryLocked": [

				],
				"atomicMemoryUnlocked": [
					{
						"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "5000000000",
						"utxoCount": 1,
						"status": "pendingImport",
						"sharedWithChainId": "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp"
					}
				]
			},
			"chainInfo": {
				"chainName": "p-chain",
				"network": "fuji"
			}
		},
		"finalBalance": {
			"balances": {
				"unlockedStaked": [

				],
				"unlockedUnstaked": [
					{
						"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "4999995865",
						"utxoCount": 1
					}
				],
				"lockedStaked": [

				],
				"lockedPlatform": [

				],
				"lockedStakeable": [

				],
				"pendingStaked": [

				],
				"atomicMemoryLocked": [

				],
				"atomicMemoryUnlocked": [

				]
			},
			"chainInfo": {
				"chainName": "p-chain",
				"network": "fuji"
			}
		},
		"tx": {
			"txHash": "2F1b1kWAGFrGQYoVzPS8DzSYhwcix1JgYb9ctDpw4teNp8QiKS",
			"txType": "ImportTx",
			"blockTimestamp": 1742409843,
			"blockNumber": "203660",
			"blockHash": "26Q16Kson46jqWML9zyjwFaHksNk9xx1JojP1DaT9VtjLHBQS",
			"sourceChain": "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp",
			"destinationChain": "11111111111111111111111111111111LpoYY",
			"memo": "0x",
			"consumedUtxos": [
				{
					"addresses": [
						"fuji1xp395ktf5kqfv9qyv2astt6fhnc4605pqwrf40"
					],
					"utxoId": "2KowNALbesyXaTJu2CrXuwGPo3jdEDwCymM9PCSg7v7ZM6PPz5",
					"txHash": "ACeSGBDHqJtmYtyHvsFgKFY7zwJKrwcJuQFdaPsw2yp3PMwEE",
					"outputIndex": 0,
					"blockTimestamp": 1742409832,
					"blockNumber": "38708400",
					"consumingTxHash": "2F1b1kWAGFrGQYoVzPS8DzSYhwcix1JgYb9ctDpw4teNp8QiKS",
					"consumingBlockTimestamp": 1742409843,
					"consumingBlockNumber": "203660",
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"asset": {
						"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "5000000000"
					},
					"utxoType": "TRANSFER",
					"amount": "5000000000",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": false
				}
			],
			"emittedUtxos": [
				{
					"addresses": [
						"fuji1xp395ktf5kqfv9qyv2astt6fhnc4605pqwrf40"
					],
					"utxoId": "2bD3ygVJURRtKPjuwZU9iPcBteRdzez6Fbb3XFxxxv1cDy1UXX",
					"txHash": "2F1b1kWAGFrGQYoVzPS8DzSYhwcix1JgYb9ctDpw4teNp8QiKS",
					"outputIndex": 0,
					"blockTimestamp": 1742409843,
					"blockNumber": "203660",
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"asset": {
						"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "4999995865"
					},
					"utxoType": "TRANSFER",
					"amount": "4999995865",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "11111111111111111111111111111111LpoYY",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": false
				}
			],
			"value": [
				{
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "4999995865"
				}
			],
			"amountBurned": [
				{
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "4135"
				}
			],
			"amountStaked": [
				{
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "0"
				}
			],
			"amountL1ValidatorBalanceBurned": [
				{
					"assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "0"
				}
			]
		}
	}
}
```

Here’s the step-by-step process:

**1 - Before the Transaction:**

* The address had `5,000,000,000 nAVAX` (5 AVAX) in `atomicMemoryUnlocked` with a status of `pendingImport`, indicating AVAX awaiting transfer from the source chain (`yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp`).
* No other balances existed on the P-chain for this address.

**2 - During the Transaction:**

* The `ImportTx` consumed a UTXO of `5,000,000,000 nAVAX` from the source chain.
* A transaction fee of `4,135 nAVAX` was burned (deducted).
* A new UTXO of `4,999,995,865 nAVAX` was created on the P-chain.

**3 - After the Transaction:**

* The `atomicMemoryUnlocked` balance became empty, as the import was completed.
* The `unlockedUnstaked` balance increased to `4,999,995,865 nAVAX` (`≈4.999995865 AVAX`), reflecting the imported amount minus the fee.

***

#### Balance Threshold

```json
 {
  "addresses": ["fuji1aerex08szh4ge5g7sggsddkpdhyzhja9f6v7y0"],
  "timestamp": 1698765432,
  "balanceType": "unlockedUnstaked",
  "threshold": "5500000000",
  "initialBalance": {"unlockedUnstaked": "6000000000"},
  "finalBalance": {"unlockedUnstaked": "5000000000"},
  "tx": {"txId": "def456..."}
}
```

***

#### Reward distribution

```json
{
  "addresses": ["fuji1aerex08szh4ge5g7sggsddkpdhyzhja9f6v7y0"],
  "timestamp": 1698765432,
  "nodeId": "NodeID-xyz",
  "subnetId": "11111111111111111111111111111111LpoYY",
  "amount": "2000000000",
  "rewardType": "delegator",
  "rewardTx": {"txId": "ghi789..."},
  "stakingTx": {"txId": "jkl012..."}
}
```

***

### Validator Activity

#### Validator registration

```json
{
	"webhookId": "2326a049-b6b9-420b-a705-9ad82c9d30fd",
	"eventType": "validator_activity",
	"messageId": "eaf56fa1-4b6b-420e-a770-2238cdf6c187",
	"event": [
		{
			"eventType": "validator_registration",
			"subnetID": "11111111111111111111111111111111LpoYY",
			"nodeID": "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY",
			"weight": "266362466160",
			"startTime": 1742411606,
			"endTime": 1743712376,
			"isL1": false,
			"l1ValidatorInfo": {
				"l1ValidationID": "",
				"subnetID": "",
				"nodeID": "",
				"initialPaygBalance": 0,
				"weight": 0,
				"remainingBalance": 0
			},
			"tx": {
				"txHash": "YFjuceefoCojou1aCJk1C78tuQUUaVDWTm7tPUFzTs8SvmA31",
				"txType": "AddPermissionlessDelegatorTx",
				"blockTimestamp": 1742411606,
				"blockNumber": "20969109",
				"blockHash": "22H83qkCt9vb2XxXJt6wfQNDPSwXL6LRNKAFqBd3fiDwfb5BBU",
				"memo": "0x",
				"rewardAddresses": [
					"avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0"
				],
				"estimatedReward": "642353165",
				"startTimestamp": 1742411606,
				"endTimestamp": 1743712376,
				"nodeId": "NodeID-2iWqUM3VWvrcTLyXi2KgBLVhunMvFW7vY",
				"subnetId": "11111111111111111111111111111111LpoYY",
				"consumedUtxos": [
					{
						"addresses": [
							"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
						],
						"utxoId": "2XyzgCUwvJWtnkj482NVMae8gqzYn3vT8EAqSmkedkQPFGocmg",
						"txHash": "YjDaCv15aXC6LoWnQAQUZjRt4m7t5NnEk5A43qyurKUB42RGQ",
						"outputIndex": 1,
						"blockTimestamp": 1741162122,
						"blockNumber": "20861193",
						"consumingTxHash": "YFjuceefoCojou1aCJk1C78tuQUUaVDWTm7tPUFzTs8SvmA31",
						"consumingBlockTimestamp": 1742411606,
						"consumingBlockNumber": "20969109",
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"asset": {
							"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
							"name": "Avalanche",
							"symbol": "AVAX",
							"denomination": 9,
							"type": "secp256k1",
							"amount": "207417972668"
						},
						"utxoType": "TRANSFER",
						"amount": "207417972668",
						"platformLocktime": 0,
						"threshold": 1,
						"createdOnChainId": "11111111111111111111111111111111LpoYY",
						"consumedOnChainId": "11111111111111111111111111111111LpoYY",
						"staked": true,
						"utxoStartTimestamp": 1741162122,
						"utxoEndTimestamp": 1742411370
					},
					{
						"addresses": [
							"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
						],
						"utxoId": "Gan2uKsqBxHepHvVPhcoM7De3Fc4qWZvKt9WeTxUjBe1SFg8N",
						"txHash": "2w3jtAbcnpF6QW2xJg2YYcyaJAWkyPLMeetff2pewkNY7e8KTq",
						"outputIndex": 1,
						"blockTimestamp": 1741099333,
						"blockNumber": "20859023",
						"consumingTxHash": "YFjuceefoCojou1aCJk1C78tuQUUaVDWTm7tPUFzTs8SvmA31",
						"consumingBlockTimestamp": 1742411606,
						"consumingBlockNumber": "20969109",
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"asset": {
							"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
							"name": "Avalanche",
							"symbol": "AVAX",
							"denomination": 9,
							"type": "secp256k1",
							"amount": "182280054571"
						},
						"utxoType": "TRANSFER",
						"amount": "182280054571",
						"platformLocktime": 0,
						"threshold": 1,
						"createdOnChainId": "11111111111111111111111111111111LpoYY",
						"consumedOnChainId": "11111111111111111111111111111111LpoYY",
						"staked": true,
						"utxoStartTimestamp": 1741099333,
						"utxoEndTimestamp": 1742411569
					}
				],
				"emittedUtxos": [
					{
						"addresses": [
							"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
						],
						"utxoId": "2ufP3GujGFjhCCib8Lb1yHbYmCFgfdbz64DmKPH7n4koHgazvX",
						"txHash": "YFjuceefoCojou1aCJk1C78tuQUUaVDWTm7tPUFzTs8SvmA31",
						"outputIndex": 0,
						"blockTimestamp": 1742411606,
						"blockNumber": "20969109",
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"asset": {
							"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
							"name": "Avalanche",
							"symbol": "AVAX",
							"denomination": 9,
							"type": "secp256k1",
							"amount": "123335549819"
						},
						"utxoType": "TRANSFER",
						"amount": "123335549819",
						"platformLocktime": 0,
						"threshold": 1,
						"createdOnChainId": "11111111111111111111111111111111LpoYY",
						"consumedOnChainId": "11111111111111111111111111111111LpoYY",
						"staked": false
					},
					{
						"addresses": [
							"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
						],
						"utxoId": "2PP1bw5opnJFZKAiYsCMAXvUe2NsUgVVCsceRzt19yqdDmYdS7",
						"txHash": "YFjuceefoCojou1aCJk1C78tuQUUaVDWTm7tPUFzTs8SvmA31",
						"outputIndex": 1,
						"blockTimestamp": 1742411606,
						"blockNumber": "20969109",
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"asset": {
							"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
							"name": "Avalanche",
							"symbol": "AVAX",
							"denomination": 9,
							"type": "secp256k1",
							"amount": "266362466160"
						},
						"utxoType": "TRANSFER",
						"amount": "266362466160",
						"platformLocktime": 0,
						"threshold": 1,
						"createdOnChainId": "11111111111111111111111111111111LpoYY",
						"consumedOnChainId": "11111111111111111111111111111111LpoYY",
						"staked": true,
						"utxoStartTimestamp": 1742411606,
						"utxoEndTimestamp": 1743712376
					}
				],
				"value": [
					{
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "389698015979"
					}
				],
				"amountBurned": [
					{
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "11260"
					}
				],
				"amountStaked": [
					{
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "266362466160"
					}
				],
				"amountL1ValidatorBalanceBurned": [
					{
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "0"
					}
				]
			}
		}
	]
}
```

***

#### Validator reward distribution

This webhook notifies the user that the staking period has concluded and the reward has been successfully distributed, providing all relevant transaction details for verification.

```json
{
"webhookId": "2326a049-b6b9-420b-a705-9ad82c9d30fd",
"eventType": "validator_activity",
"messageId": "6c9034d2-fc2f-4804-a133-9c09f7bfa841",
"event": [
	{
		"eventType": "reward_distribution",
		"nodeID": "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg",
		"subnetID": "11111111111111111111111111111111LpoYY",
		"rewardAddresses": [
			"avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0"
		],
		"amount": "411902301",
		"rewardType": "DELEGATOR",
		"rewardTxHash": "Vqo55peoBeCV1bmiPTmvBiccbEEQ1rWLYLrEbctFJM7tFjTQR",
		"stakingTxHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
		"rewardTx": {
			"txHash": "Vqo55peoBeCV1bmiPTmvBiccbEEQ1rWLYLrEbctFJM7tFjTQR",
			"txType": "RewardValidatorTx",
			"blockTimestamp": 1742411337,
			"blockNumber": "20969100",
			"blockHash": "2k91M4wuEbCZn9q1srfuf6CYCXDnQxfEbYF8YE992t94UYtKy2",
			"memo": "",
			"stakingTxHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
			"rewardAddresses": [
				"avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0"
			],
			"nodeId": "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg",
			"subnetId": "11111111111111111111111111111111LpoYY",
			"consumedUtxos": [

			],
			"emittedUtxos": [

			],
			"value": [

			],
			"amountBurned": [

			],
			"amountStaked": [

			],
			"amountL1ValidatorBalanceBurned": [

			]
		},
		"stakingTx": {
			"txHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
			"txType": "AddPermissionlessDelegatorTx",
			"blockTimestamp": 1741157160,
			"blockNumber": "20861047",
			"blockHash": "25egugU3xQjFt5KGhGr2UjfyzFZGQRobfmapFexS8SguZdzRZs",
			"memo": "0x",
			"rewardAddresses": [
				"avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0"
			],
			"rewardTxHash": "Vqo55peoBeCV1bmiPTmvBiccbEEQ1rWLYLrEbctFJM7tFjTQR",
			"estimatedReward": "420308471",
			"startTimestamp": 1741157160,
			"endTimestamp": 1742411337,
			"nodeId": "NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg",
			"subnetId": "11111111111111111111111111111111LpoYY",
			"consumedUtxos": [
				{
					"addresses": [
						"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
					],
					"utxoId": "vEaQ7Uka6B8zxjmn94rjf7SYm35kQMK1dUDnjC8bj99BZmXwv",
					"txHash": "yuuPamqwhEhzT3RneedAxpxUAjqcPt7oXwcmGuei6sgtYE4p1",
					"outputIndex": 0,
					"blockTimestamp": 1741157158,
					"blockNumber": "20861046",
					"consumingTxHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
					"consumingBlockTimestamp": 1741157160,
					"consumingBlockNumber": "20861047",
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"asset": {
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "225941621334"
					},
					"utxoType": "TRANSFER",
					"amount": "225941621334",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "11111111111111111111111111111111LpoYY",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": false
				}
			],
			"emittedUtxos": [
				{
					"addresses": [
						"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
					],
					"utxoId": "2hDcTcLPeUoXY8ZFnKvyefpJB2fvuDaUxSQj4sL8VXCj6HBoEH",
					"txHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
					"outputIndex": 0,
					"blockTimestamp": 1741157160,
					"blockNumber": "20861047",
					"consumingTxHash": "cJy6qRWmQCYddKEyBanXkWzHUuELqmpeysqoJ6DU9SWZUunDT",
					"consumingBlockTimestamp": 1741157163,
					"consumingBlockNumber": "20861048",
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"asset": {
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "45488915557"
					},
					"utxoType": "TRANSFER",
					"amount": "45488915557",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "11111111111111111111111111111111LpoYY",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": false
				},
				{
					"addresses": [
						"avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"
					],
					"utxoId": "Hr4VkKgfAk4TE9oGv6bg3WHpDm9DBDBouaNcXShEEGZxaW8qh",
					"txHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
					"outputIndex": 1,
					"blockTimestamp": 1741157160,
					"blockNumber": "20861047",
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"asset": {
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "180452697478"
					},
					"utxoType": "TRANSFER",
					"amount": "180452697478",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "11111111111111111111111111111111LpoYY",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": true,
					"utxoStartTimestamp": 1741157160,
					"utxoEndTimestamp": 1742411337
				},
				{
					"addresses": [
						"avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0"
					],
					"utxoId": "oRpWYWPARzQGCNQXF7vDfPGmBhJbtd6qkN4Z16m7dwfFyJYus",
					"txHash": "2gKy9jG2UTDxZmFMGfXqRjr761o2itMnQjkuZqNXtZSh4tFMFm",
					"outputIndex": 2,
					"blockTimestamp": 1742411337,
					"blockNumber": "20969100",
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"asset": {
						"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
						"name": "Avalanche",
						"symbol": "AVAX",
						"denomination": 9,
						"type": "secp256k1",
						"amount": "411902301"
					},
					"utxoType": "TRANSFER",
					"amount": "411902301",
					"platformLocktime": 0,
					"threshold": 1,
					"createdOnChainId": "11111111111111111111111111111111LpoYY",
					"consumedOnChainId": "11111111111111111111111111111111LpoYY",
					"staked": false,
					"rewardType": "DELEGATOR"
				}
			],
			"value": [
				{
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "226353515336"
				}
			],
			"amountBurned": [
				{
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "8299"
				}
			],
			"amountStaked": [
				{
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "180452697478"
				}
			],
			"amountL1ValidatorBalanceBurned": [
				{
					"assetId": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
					"name": "Avalanche",
					"symbol": "AVAX",
					"denomination": 9,
					"type": "secp256k1",
					"amount": "0"
				}
			]
		}
	}
]
}
```

**1 - Staking Initiation:**

* The delegator, with address `avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy`, staked 180.452697478 AVAX with validator `NodeID-CAy5q5U4AnPR35i225a2QXM7ftYvbZEEg` on the Primary Network.
* This occurred via the `AddPermissionlessDelegatorTx` at timestamp `1741157160`, using 225.941621334 AVAX, with 45.488915557 AVAX returned as change and a fee of 0.000008299 AVAX burned.
* The staking period ran from `1741157160` to `1742411337`.

**2 - Reward Distribution:**

* At the end of the staking period (`1742411337`), the `RewardValidatorTx` was processed, distributing a reward of 0.411902301 AVAX to the specified reward address `avax19zfygxaf59stehzedhxjesads0p5jdvfeedal0`.
* This reward was slightly less than the estimated 0.420308471 AVAX, which is typical due to variables like validator uptime and network conditions.

***

#### L1 Validator balance threshod reached

```json
{
  "timestamp": 1698765432,
  "nodeId": "NodeID-H8AkDZHd6Jczcc1v8aVDLb5haQYPkGxqt",
  "subnetId": "11111111111111111111111111111111LpoYY",
  "previousPaygBalance": "6000000000",
  "currentPaygBalance": "4000000000",
  "l1ValidatorInfo": {"feeBalance": "4000000000"}
}
```


# Send Push notification
Source: https://developers.avacloud.io/webhooks-api/push-notifications



In this tutorial, we'll explore how to send push notifications to a user's wallet whenever they receive a transaction containing tokens. It's a handy way to keep users informed about their account activity.

Note: This hypothetical example is not for real-world production use. We're simplifying things here for demonstration purposes, so there's no thorough error handling.

We'll be using [OneSignal](https://onesignal.com) for sending push notifications, but you can also achieve similar functionality with other services like [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) or [AWS Pinpoint](https://aws.amazon.com/pinpoint/).
Now, let's dive into the details!

### Step 1 - OneSignal Setup

The first step is to create a free account in [OneSignal](https://onesignal.com). For this example, we are going to use Web push but it works similarly for mobile.

To get started, the first step is to create a free account on OneSignal. Once you've signed up and logged in, we'll proceed to create a new OneSignal App.

For this example, we'll focus on using Web push notifications, but keep in mind that the process is quite similar for mobile apps.

Create a new OneSignal App and select Web. Once your app is created, you'll be provided with an App ID and API Key. Keep these credentials handy as we'll need them later to integrate OneSignal with our code.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/new-onesignal-app.png" />
</Frame>

Next, click on Configure Your Platform and select Web, select Code Custom, and set the site URL `http://localhost:3000` and enable both toggles for local development.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-web-configuration.png" />
</Frame>

This will generate a code snippet to add to your code. Download the OneSignal SDK files and copy them to the top-level root of your directory.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onsignal-snippet.png" />
</Frame>

### Step 2 - Frontend Setup

In a real-world scenario, your architecture typically involves customers signing up for subscriptions within your Web or Mobile App. To ensure these notifications are sent out, your app needs to register with a push notification provider such as OneSignal.

To maintain privacy and security, we'll be using a hash of the wallet address as the `externalID` instead of directly sharing the addresses with OneSignal. This `externalID` will then be mapped to an address in our database. So, when our backend receives a webhook for a specific address, it can retrieve the corresponding `externalID` and send a push notification accordingly.
![OneSignal Architecture](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-architecture.png)

For the sake of simplicity in our demonstration, we'll present a basic scenario where our frontend app retrieves the wallet address and registers it with OneSignal. Additionally, we'll simulate a database using an array within the code. Download the [sample code](https://github.com/javiertc/webhookdemo) and you'll see `client/inde.html` with this content.

```html
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
  <script src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js" defer></script>
  <script>
    window.OneSignalDeferred = window.OneSignalDeferred || [];
    OneSignalDeferred.push(function(OneSignal) {
      OneSignal.init({
        appId: "a63e0a25-186c-40a7-8fce-9c0fde324400",
        safari_web_id: "web.onesignal.auto.67fef31a-7360-4fd8-9645-1463ac233cef",
        notifyButton: {
          enable: false,
        },
        allowLocalhostAsSecureOrigin: true,
      });
    });

    window.connect = async function() {
      try {
        if (!window.ethereum) {
          throw new Error("Avalanche wallet not detected");
        }
        const accounts = await window.ethereum.request({ method: "eth_requestAccounts" });
        window.web3 = new Web3(window.ethereum);

        //Create externalID based on the address
        const externalID = web3.utils.sha3(accounts[0].toLowerCase()).slice(2);
        console.log("externalID:", externalID);

        OneSignal.login(externalID);
        OneSignal.Notifications.requestPermission();
      } catch (error) {
        console.error("Error connecting to Avalanche wallet:", error.message);
      }
    };
  </script>
</head>
<body>
  <h1>Avalanche push notifications</h1>
  <button onclick="window.connect()">Connect</button>
</body>
</html>
```

Run the project using Nodejs.

```bash
npm install express axios path body-parser dotenv
node app.js
```

Open a Chrome tab and type `http://localhost:3000`, you should see something like this. Then click on Connect and accept receiving push notifications. If you are using MacOS, check in **System Settings** > **Notifications** that you have enabled notifications for the browser.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-connect.png" />
</Frame>

If everything runs correctly your browser should be registered in OneSignal. To check go to **Audience** > **Subscriptions** and verify that your browser is registered.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-subscription.png" />
</Frame>

### Step 3 - Backend Setup

Now, let's configure the backend to manage webhook events and dispatch notifications based on the incoming data. Here's the step-by-step process:

1. **Transaction Initiation:** When someone starts a transaction with your wallet as the destination, the webhooks detect the transaction and generate an event.
2. **Event Triggering:** The backend receives the event triggered by the transaction, containing the destination address.
3. **ExternalID Retrieval:** Using the received address, the backend retrieves the corresponding `externalID` associated with that wallet.
4. **Notification Dispatch:** The final step involves sending a notification through OneSignal, utilizing the retrieved `externalID`.
   ![OneSignal Backend](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-backend.png)

#### 3.1 - Use Ngrok to tunnel the traffic to localhost

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. Glacier 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 3000.
Go to [https://ngrok.com/](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:

To start an HTTP tunnel forwarding to your local port 3000 with Ngrok, run this next:

```bash
./ngrok http 3000
```

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                       javier.toledo@avalabs.org (Plan: Free)
Version                       3.8.0
Region                        United States (us)
Latency                       48ms
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://c902-2600-1700-5220-11a0-813c-d5ac-d72c-f7fd.ngrok-free.app -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              33      0       0.00    0.00    5.02    5.05

HTTP Requests
-------------
```

#### 3.2 - Create the webhook

The webhook can be created using the [Avacloud Dashboard](https://app.avacloud.io/) or Glacier API. For convenience, we are going to use cURL. For that copy the forwarding URL generated by Ngrok and append the `/callbackpath` and our address.

```bash
curl --location 'https://glacier-api-dev.avax.network/v1/webhooks' \
--header 'x-glacier-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
    "url": " https://c902-2600-1700-5220-11a0-813c-d5ac-d72c-f7fd.ngrok-free.app/callback",
    "chainId": "43113",
    "eventType": "address_activity",
    "includeInternalTxs": true,
    "includeLogs": true,
    "metadata": {
        "addresses": ["0x8ae323046633A07FB162043f28Cea39FFc23B50A"]
    },
    "name": "My wallet",
    "description": "My wallet"
}'
```

<Note> Don't forget to add your API Key. If you don't have one go to the [Avacloud Dashboard](https://app.avacloud.io/) and create a new one. </Note>

#### 3.3 - The backend

To run the backend we need to add the environment variables in the root of your project. For that create an `.env` file with the following values:

```
PORT=3000
ONESIGNAL_API_KEY=<YOUR_ONESIGNAL_API_KEY>
APP_ID=<YOUR_ONESIGNAL_APP_ID>
```

<Info> To get the APP ID from OneSignal go to **Settings** > **Keys and IDs** </Info>

Since we are simulating the connection to a database to retrieve the externalID, we need to add the wallet address and the OneSignal externalID to the myDB array.

```javascript
//simulating a DB
const myDB = [
    { name: 'wallet1', address: '0x8ae323046633A07FB162043f28Cea39FFc23B50A', externalID: '9c96e91d40c7a44c763fb55960e12293afbcfaf6228860550b0c1cc09cd40ac3' },
    { name: 'wallet2', address: '0x1f83eC80D755A87B31553f670070bFD897c40CE0', externalID: '0xd39d39c99305c6df2446d5cc3d584dc1eb041d95ac8fb35d4246f1d2176bf330' }
];
```

The code handles a webhook event triggered when a wallet receives a transaction, performs a lookup in the simulated "database" using the receiving address to retrieve the corresponding OneSignal `externalID`, and then sends an instruction to OneSignal to dispatch a notification to the browser, with OneSignal ultimately delivering the web push notification to the browser.

```javascript
require('dotenv').config();
const axios = require('axios');
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');

const app = express();
const port = process.env.PORT || 3000;

//  Serve static website
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, './client')));

//simulating a DB
const myDB = [
    { name: 'wallet1', address: '0x8ae323046633A07FB162043f28Cea39FFc23B50A', externalID: '9c96e91d40c7a44c763fb55960e12293afbcfaf6228860550b0c1cc09cd40ac3' },
    { name: 'wallet2', address: '0x1f83eC80D755A87B31553f670070bFD897c40CE0', externalID: '0xd39d39c99305c6df2446d5cc3d584dc1eb041d95ac8fb35d4246f1d2176bf330' }
];

app.post('/callback', async (req, res) => {
    const { body } = req;
    try {
        res.sendStatus(200);
        handleTransaction(body.event.transaction).catch(error => {
            console.error('Error processing transaction:', error);
        });
    } catch (error) {
        console.error('Error processing transaction:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});

// Handle transaction
async function handleTransaction(transaction) {
    console.log('*****Transaction:', transaction);
    const notifications = [];

    const erc20Transfers = transaction?.erc20Transfers || [];
    for (const transfer of erc20Transfers) {
        const externalID = await getExternalID(transfer.to);
        const { symbol, valueWithDecimals } = transfer.erc20Token;
        notifications.push({
            type: transfer.type,
            sender: transfer.from,
            receiver: transfer.to,
            amount: valueWithDecimals,
            token: symbol,
            externalID
        });
    }

    if (transaction?.networkToken) {
        const { tokenSymbol, valueWithDecimals } = transaction.networkToken;
        const externalID = await getExternalID(transaction.to);
        notifications.push({
            sender: transaction.from,
            receiver: transaction.to,
            amount: valueWithDecimals,
            token: tokenSymbol,
            externalID
        });
    }

    if (notifications.length > 0) {
        sendNotifications(notifications);
    }
}

//connect to DB and return externalID
async function getExternalID(address) {
    const entry = myDB.find(entry => entry.address.toLowerCase() === address.toLowerCase());
    return entry ? entry.externalID : null;
}

// Send notifications
async function sendNotifications(notifications) {
    for (const notification of notifications) {
        try {
            const data = {
                include_aliases: { external_id: [notification.externalID.toLowerCase()] },
                target_channel: 'push',
                isAnyWeb: true,
                contents: { en: `You've received ${notification.amount} ${notification.token}` },
                headings: { en: 'Core wallet' },
                name: 'Notification',
                app_id: process.env.APP_ID
            };
            console.log('data:', data);
            const response = await axios.post('https://onesignal.com/api/v1/notifications', data, {
                headers: {
                    Authorization: `Bearer ${process.env.ONESIGNAL_API_KEY}`,
                    'Content-Type': 'application/json'
                }
            });
            console.log('Notification sent:', response.data);
        } catch (error) {
            console.error('Error sending notification:', error);
            // Optionally, implement retry logic here
        }
    }
}

// Start the server
app.listen(port, () => {
    console.log(`App listening at http://localhost:${port}`);
});
```

You can now start your backend server by running:

```Shell
node app.js
```

Send AVAX from another wallet to the wallet being monitored by the webhook and you should receive a notification with the amount of Avax received. You can try it with any other ERC20 token as well.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/onesignal-notification.png" />
</Frame>

### Conclusion

In this tutorial, we've set up a frontend to connect to the Core wallet and enable push notifications using OneSignal. We've also implemented a backend to handle webhook events and send notifications based on the received data. By integrating the frontend with the backend, users can receive real-time notifications for blockchain events.


# Rate Limits
Source: https://developers.avacloud.io/webhooks-api/rate-limits



Rate limiting is managed through a weighted scoring system, known as Compute Units (CUs). Each API request consumes a specified number of CUs, determined by the complexity of the request. This system is designed to accommodate basic requests while efficiently handling more computationally intensive operations.

## Rate Limit Tiers

The maximum CUs (rate-limiting score) for a user depends on their subscription level and is delineated in the following table:

| Subscription Level | Per Minute Limit (CUs) | Per Day Limit (CUs) |
| :----------------- | :--------------------- | :------------------ |
| Unauthenticated    | 6,000                  | 1,200,000           |
| Free               | 8,000                  | 2,000,000           |
| Base               | 10,000                 | 3,750,000           |
| Growth             | 14,000                 | 11,200,000          |
| Pro                | 20,000                 | 25,000,000          |

To update your subscription level use the [AvaCloud Portal](https://app.avacloud.io/)

<Info> Note: Rate limits apply collectively across both Webhooks and Data APIs, with usage from each counting toward your total CU limit. </Info>

## Rate Limit Categories

The CUs for each category are defined in the following table:

{/* webhooks weights value table start */}

| Weight | CU Value |
| :----- | :------- |
| Free   | 1        |
| Small  | 10       |
| Medium | 20       |
| Large  | 50       |
| XL     | 100      |
| XXL    | 200      |

{/* webhooks weights value table end */}

## Rate Limits for Webhook Endpoints

The CUs for each route are defined in the table below:

{/* webhooks execution weights table start */}

| Endpoint                                    | Method | Weight | CU Value |
| :------------------------------------------ | :----- | :----- | :------- |
| `/v1/webhooks`                              | POST   | Medium | 20       |
| `/v1/webhooks`                              | GET    | Small  | 10       |
| `/v1/webhooks/{id}`                         | GET    | Small  | 10       |
| `/v1/webhooks/{id}`                         | DELETE | Medium | 20       |
| `/v1/webhooks/{id}`                         | PATCH  | Medium | 20       |
| `/v1/webhooks:generateOrRotateSharedSecret` | POST   | Medium | 20       |
| `/v1/webhooks:getSharedSecret`              | GET    | Small  | 10       |
| `/v1/webhooks/{id}/addresses`               | PATCH  | Medium | 20       |
| `/v1/webhooks/{id}/addresses`               | DELETE | Medium | 20       |
| `/v1/webhooks/{id}/addresses`               | GET    | Medium | 20       |

{/* webhooks execution weights table end */}

<Info> All rate limits, weights, and CU values are subject to change. </Info>


# Retry mechanism
Source: https://developers.avacloud.io/webhooks-api/retries



We want to make sure you receive all your webhook messages, even if there are temporary issues. That’s why we’ve set up a retry system to resend messages if they don’t get through the first time.

## How it works

1. **First attempt:** <br />
   When we send a webhook message to your server, we expect an immediate response with a `200` status code. This indicates that you’ve successfully received the message. Your server should return the `200` status code first and then proceed to process the event. Avoid processing the event before returning the `200` response, as this can lead to timeouts and potential webhook deactivation.

2. **If we don't get a `200` response due to:** <br />
   * Your server might be down.
   * There could be network issues.
   * Your server returns an error status code (`400` or higher).

3. **Retrying the message:**

   We'll try sending the message **three more times** if we don't get the right response.
   ![title](https://mintlify.s3.us-west-1.amazonaws.com/avalabs-47ea3976/images/retries.png)
   **Timing between retries:**

   * **First retry:** We'll wait **15 seconds** after the initial attempt before trying again.
   * **Second retry:** If needed, we'll wait another **15 seconds** before the third attempt.
   * **Third retry:** This will be our third and final attempt.

4. **Timeout**: We’ll wait a final 15 seconds after the third retry. If we don’t receive a `200` response, the message will be marked as failed, and we’ll start sending the next event. Starting from the first attempt, your server has up to 1 minute to respond with a `200` status.

### Failure limits before deactivation:

A webhook subscription will be deactivated if the total number of message delivery failures from subscription creation reaches a threshold depending on your plan tier.

* **Free Plan users:**  1 failed message delivery
* **Paid Plan users:** 100 failed message deliveries

### What you can do

**Ensure server availability:**

* Keep your server running smoothly to receive webhook messages without interruption.
* Implement logging for incoming webhook requests and your server's responses to help identify any issues quickly.

### Design for idempotency:

Set up your webhook handler so it can safely process the same message multiple times without causing errors or unwanted effects. This way, if retries occur, they won't negatively impact your system.


# Webhook Signature
Source: https://developers.avacloud.io/webhooks-api/signature



To make your webhooks extra secure, you can verify that they originated from our side by generating an HMAC SHA-256 hash code using your Authentication Token and request body. You can get the signing secret through the AvaCloud portal or Glacier API.

### Find your signing secret

**Using the portal**\
Navigate to the webhook section and click on Generate Signing Secret. Create the secret and copy it to your code.

**Using Glacier API**\
The following endpoint retrieves a shared secret:

```bash
curl --location 'https://glacier-api.avax.network/v1/webhooks:getSharedSecret' \
--header 'x-glacier-api-key: <YOUR_API_KEY>' \
```

### Validate the signature received

Every outbound request will include an authentication signature in the header. This signature is generated by:

1. **Canonicalizing the JSON Payload**: This means arranging the JSON data in a standard format.
2. **Generating a Hash**: Using the HMAC SHA256 hash algorithm to create a hash of the canonicalized JSON payload.

To verify that the signature is from us, follow these steps:

1. Generate the HMAC SHA256 hash of the received JSON payload.
2. Compare this generated hash with the signature in the request header.
   This process, known as verifying the digital signature, ensures the authenticity and integrity of the request.

**Example Request Header**

```
Content-Type: application/json;
x-signature: your-hashed-signature
```

### Example Signature Validation Function

This Node.js code sets up an HTTP server using the Express framework. It listens for POST requests sent to the `/callback` endpoint. Upon receiving a request, it validates the signature of the request against a predefined `signingSecret`. If the signature is valid, it logs match; otherwise, it logs no match. The server responds with a JSON object indicating that the request was received.

<CodeGroup>
  ```JavaScript Node
  const express = require('express');
  const crypto = require('crypto');
  const { canonicalize } = require('json-canonicalize');

  const app = express();
  app.use(express.json({limit: '50mb'}));

  const signingSecret = 'c13cc017c4ed63bcc842c8edfb49df37512280326a32826de3b885340b8a3d53';

  function isValidSignature(signingSecret, signature, payload) {
     const canonicalizedPayload = canonicalize(payload);
     const hmac = crypto.createHmac('sha256', Buffer.from(signingSecret, 'hex'));
     const digest = hmac.update(canonicalizedPayload).digest('base64');
     console.log("signature: ", signature);
     console.log("digest", digest);
     return signature === digest;
  }

  app.post('/callback', express.json({ type: 'application/json' }), (request, response) => {
     const { body, headers } = request;
     const signature = headers['x-signature'];
     // Handle the event
     switch (body.evenType) {
         case 'address_activity':
             console.log("*** Address_activity ***");
             console.log(body);
             if (isValidSignature(signingSecret, signature, body)) {
                 console.log("match");
             } else {
                 console.log("no match");
             }
             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}`));
  ```

  ```python Python
  from flask import Flask, request, jsonify
  import hmac
  import hashlib
  import base64
  import json

  app = Flask(__name__)

  SIGNING_SECRET = 'c13cc017c4ed63bcc842c8edfb49df37512280326a32826de3b885340b8a3d53'

  def canonicalize(payload):
      """Function to canonicalize JSON payload"""
      # In Python, canonicalization can be achieved by using sort_keys=True in json.dumps
      return json.dumps(payload, separators=(',', ':'), sort_keys=True)

  def is_valid_signature(signing_secret, signature, payload):
      canonicalized_payload = canonicalize(payload)
      hmac_obj = hmac.new(bytes.fromhex(signing_secret), canonicalized_payload.encode('utf-8'), hashlib.sha256)
      digest = base64.b64encode(hmac_obj.digest()).decode('utf-8')
      print("signature:", signature)
      print("digest:", digest)
      return signature == digest

  @app.route('/callback', methods=['POST'])
  def callback_handler():
      body = request.json
      signature = request.headers.get('x-signature')

      # Handle the event
      if body.get('eventType') == 'address_activity':
          print("*** Address_activity ***")
          print(body)
          if is_valid_signature(SIGNING_SECRET, signature, body):
              print("match")
          else:
              print("no match")
      else:
          print(f"Unhandled event type {body}")

      # Return a response to acknowledge receipt of the event
      return jsonify({"received": True})

  if __name__ == '__main__':
      PORT = 8000
      print(f"Running on port {PORT}")
      app.run(port=PORT)
  ```

  ```go Go
  package main

  import (
  	"crypto/hmac"
  	"crypto/sha256"
  	"encoding/base64"
  	"encoding/hex"
  	"encoding/json"
  	"fmt"
  	"net/http"
  	"sort"
  	"strings"
  )

  const signingSecret = "c13cc017c4ed63bcc842c8edfb49df37512280326a32826de3b885340b8a3d53"

  // Canonicalize function sorts the JSON keys and produces a canonicalized string
  func Canonicalize(payload map[string]interface{}) (string, error) {
  	var sb strings.Builder
  	var keys []string
  	for k := range payload {
  		keys = append(keys, k)
  	}
  	sort.Strings(keys)
  	sb.WriteString("{")
  	for i, k := range keys {
  		v, err := json.Marshal(payload[k])
  		if err != nil {
  			return "", err
  		}
  		sb.WriteString(fmt.Sprintf("\"%s\":%s", k, v))
  		if i < len(keys)-1 {
  			sb.WriteString(",")
  		}
  	}
  	sb.WriteString("}")
  	return sb.String(), nil
  }

  func isValidSignature(signingSecret, signature string, payload map[string]interface{}) bool {
  	canonicalizedPayload, err := Canonicalize(payload)
  	if err != nil {
  		fmt.Println("Error canonicalizing payload:", err)
  		return false
  	}

  	key, err := hex.DecodeString(signingSecret)
  	if err != nil {
  		fmt.Println("Error decoding signing secret:", err)
  		return false
  	}

  	h := hmac.New(sha256.New, key)
  	h.Write([]byte(canonicalizedPayload))
  	digest := h.Sum(nil)
  	encodedDigest := base64.StdEncoding.EncodeToString(digest)

  	fmt.Println("signature:", signature)
  	fmt.Println("digest:", encodedDigest)

  	return signature == encodedDigest
  }

  func callbackHandler(w http.ResponseWriter, r *http.Request) {
  	var body map[string]interface{}
  	err := json.NewDecoder(r.Body).Decode(&body)
  	if err != nil {
  		fmt.Println("Error decoding body:", err)
  		http.Error(w, "Invalid request body", http.StatusBadRequest)
  		return
  	}

  	signature := r.Header.Get("x-signature")
  	eventType, ok := body["eventType"].(string)
  	if !ok {
  		fmt.Println("Error parsing eventType")
  		http.Error(w, "Invalid event type", http.StatusBadRequest)
  		return
  	}

  	switch eventType {
  	case "address_activity":
  		fmt.Println("*** Address_activity ***")
  		fmt.Println(body)
  		if isValidSignature(signingSecret, signature, body) {
  			fmt.Println("match")
  		} else {
  			fmt.Println("no match")
  		}
  	default:
  		fmt.Printf("Unhandled event type %s\n", eventType)
  	}

  	w.Header().Set("Content-Type", "application/json")
  	json.NewEncoder(w).Encode(map[string]bool{"received": true})
  }

  func main() {
  	http.HandleFunc("/callback", callbackHandler)
  	fmt.Println("Running on port 8000")
  	http.ListenAndServe(":8000", nil)
  }
  ```

  ```rust Rust
  use actix_web::{web, App, HttpServer, HttpResponse, Responder, post};
  use serde::Deserialize;
  use hmac::{Hmac, Mac};
  use sha2::Sha256;
  use base64::encode;
  use std::collections::BTreeMap;

  type HmacSha256 = Hmac<Sha256>;

  const SIGNING_SECRET: &str = "c13cc017c4ed63bcc842c8edfb49df37512280326a32826de3b885340b8a3d53";

  #[derive(Deserialize)]
  struct EventPayload {
      eventType: String,
      // Add other fields as necessary
  }

  // Canonicalize the JSON payload by sorting keys
  fn canonicalize(payload: &BTreeMap<String, serde_json::Value>) -> String {
      serde_json::to_string(payload).unwrap()
  }

  fn is_valid_signature(signing_secret: &str, signature: &str, payload: &BTreeMap<String, serde_json::Value>) -> bool {
      let canonicalized_payload = canonicalize(payload);

      let mut mac = HmacSha256::new_from_slice(signing_secret.as_bytes())
          .expect("HMAC can take key of any size");
      mac.update(canonicalized_payload.as_bytes());

      let result = mac.finalize();
      let digest = encode(result.into_bytes());

      println!("signature: {}", signature);
      println!("digest: {}", digest);

      digest == signature
  }

  #[post("/callback")]
  async fn callback(body: web::Json<BTreeMap<String, serde_json::Value>>, req: web::HttpRequest) -> impl Responder {
      let signature = req.headers().get("x-signature").unwrap().to_str().unwrap();

      if let Some(event_type) = body.get("eventType").and_then(|v| v.as_str()) {
          match event_type {
              "address_activity" => {
                  println!("*** Address_activity ***");
                  println!("{:?}", body);

                  if is_valid_signature(SIGNING_SECRET, signature, &body) {
                      println!("match");
                  } else {
                      println!("no match");
                  }
              }
              _ => {
                  println!("Unhandled event type: {}", event_type);
              }
          }
      } else {
          println!("Error parsing eventType");
          return HttpResponse::BadRequest().finish();
      }

      HttpResponse::Ok().json(serde_json::json!({ "received": true }))
  }

  #[actix_web::main]
  async fn main() -> std::io::Result<()> {
      HttpServer::new(|| {
          App::new()
              .service(callback)
      })
      .bind("0.0.0.0:8000")?
      .run()
      .await
  }
  ```

  ```TypeScript AvaCloud SDK
  import { isValidSignature } from '@avalabs/avacloud-sdk/utils';
  import express from 'express';

  const app = express();
  app.use(express.json());

  const signingSecret = 'your-signing-secret'; // Replace with your signing secret

  app.post('/webhook', (req, res) => {
      const signature = req.headers['x-signature'];
      const payload = req.body;

      if (isValidSignature(signingSecret, signature, payload)) {
          console.log('Valid signature');
          // Process the request
      } else {
          console.log('Invalid signature');
      }

      res.json({ received: true });
  });

  app.listen(8000, () => console.log('Server running on port 8000'));
  ```
</CodeGroup>


# Supported EVM Chains
Source: https://developers.avacloud.io/webhooks-api/supported-chains



### Supported L1s

Webhooks are currently enabled for the following L1s. Additional L1s will be added in the future:

**Mainnet**

| L1       | Chain ID |
| -------- | -------- |
| Beam     | 4337     |
| DFK      | 53935    |
| Dexalot  | 432204   |
| Shrapnel | 2044     |
| Testnet  | Fuji     |

**Testnet**

| L1       | Chain ID |
| -------- | -------- |
| Pulsar   | 431234   |
| Beam     | 13337    |
| Dexalot  | 432201   |
| DFK      | 335      |
| WAGMI    | 11111    |
| Shrapnel | 2038     |

<Note>We will continue expanding this list by adding new L1s.</Note>


# Add addresses to webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/add-addresses-to-webhook

patch /v1/webhooks/{id}/addresses
Add addresses to webhook.



# Create a webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/create-a-webhook

post /v1/webhooks
Create a new webhook.



# Deactivate a webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/deactivate-a-webhook

delete /v1/webhooks/{id}
Deactivates a webhook by ID.



# Generate or rotate a shared secret
Source: https://developers.avacloud.io/webhooks-api/webhooks/generate-a-shared-secret

post /v1/webhooks:generateOrRotateSharedSecret
Generates a new shared secret or rotate an existing one.



# Get a shared secret
Source: https://developers.avacloud.io/webhooks-api/webhooks/get-a-shared-secret

get /v1/webhooks:getSharedSecret
Get a previously generated shared secret.



# Get a webhook by ID
Source: https://developers.avacloud.io/webhooks-api/webhooks/get-a-webhook-by-id

get /v1/webhooks/{id}
Retrieves a webhook by ID.



# List adresses by webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/list-adresses-by-webhook

get /v1/webhooks/{id}/addresses
List adresses by webhook.



# List webhooks
Source: https://developers.avacloud.io/webhooks-api/webhooks/list-webhooks

get /v1/webhooks
Lists webhooks for the user.



# Remove addresses from webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/remove-addresses-from-webhook

delete /v1/webhooks/{id}/addresses
Remove addresses from webhook.



# Update a webhook
Source: https://developers.avacloud.io/webhooks-api/webhooks/update-a-webhook

patch /v1/webhooks/{id}
Updates an existing webhook.



