> ## Documentation Index
> Fetch the complete documentation index at: https://developers.zerion.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a wallet's transaction history

> Fetch and interpret a wallet's onchain transactions across chains with human-readable types, transfer details, and fee breakdowns using Zerion API.

**What you'll build:**

* Fetch and display a wallet's transaction history with human-readable labels
* Filter transactions by type, chain, and date range
* Paginate through the full history

```
[2024-03-15T14:22:31+00:00] trade on ethereum
  via Uniswap
  -0.5 ETH ($1,060.00)
  +1200.0 USDC ($1,200.00)
  Fee: $12.45

[2024-03-14T09:10:05+00:00] receive on optimism
  +500.0 OP ($680.00)
  Fee: $0.02

[2024-03-13T18:45:12+00:00] deposit on ethereum
  via Aave
  -1000.0 USDC ($1,000.00)
  Fee: $8.33
```

**Time:** \~10 minutes

## Prerequisites

* A Zerion API key ([get one here](https://dashboard.zerion.io))
* A wallet address to query

## Steps

<Steps>
  <Step title="Fetch recent transactions">
    Use the [wallet transactions](/api-reference/wallets/get-wallet-transactions) endpoint to get a wallet's history.

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const API_KEY = process.env.ZERION_API_KEY;
      const address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
      const headers = {
        accept: "application/json",
        authorization: `Basic ${btoa(API_KEY + ":")}`,
      };

      const response = await fetch(
        `https://api.zerion.io/v1/wallets/${address}/transactions/?currency=usd&page[size]=10`,
        { headers }
      );
      if (!response.ok) throw new Error(`API error: ${response.status}`);

      const { data } = await response.json();

      for (const tx of data) {
        const { operation_type, mined_at, transfers, fee, application_metadata } =
          tx.attributes;
        const chain = tx.relationships.chain.data.id;

        console.log(`[${mined_at}] ${operation_type} on ${chain}`);
        if (application_metadata?.name) {
          console.log(`  via ${application_metadata.name}`);
        }
        for (const transfer of transfers) {
          const symbol = transfer.fungible_info?.symbol || "NFT";
          console.log(
            `  ${transfer.direction === "out" ? "-" : "+"}${transfer.quantity.float} ${symbol} (${transfer.value != null ? `$${transfer.value.toFixed(2)}` : "N/A"})`
          );
        }
        console.log(`  Fee: ${fee.value != null ? `$${fee.value.toFixed(2)}` : "N/A"}`);
      }
      ```

      ```python Python theme={null}
      import os, requests

      api_key = os.environ["ZERION_API_KEY"]
      address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

      response = requests.get(
          f"https://api.zerion.io/v1/wallets/{address}/transactions/",
          params={"currency": "usd", "page[size]": 10},
          auth=(api_key, ""),
      )

      for tx in response.json()["data"]:
          attrs = tx["attributes"]
          chain = tx["relationships"]["chain"]["data"]["id"]
          app = attrs.get("application_metadata", {})

          print(f"[{attrs['mined_at']}] {attrs['operation_type']} on {chain}")
          if app.get("name"):
              print(f"  via {app['name']}")
          for transfer in attrs["transfers"]:
              symbol = transfer.get("fungible_info", {}).get("symbol", "NFT")
              direction = "-" if transfer["direction"] == "out" else "+"
              val = transfer.get("value")
              print(f"  {direction}{transfer['quantity']['float']} {symbol} ({f'${val:.2f}' if val is not None else 'N/A'})")
          fee_val = attrs["fee"].get("value")
          print(f"  Fee: {f'${fee_val:.2f}' if fee_val is not None else 'N/A'}")
      ```

      ```bash cURL theme={null}
      curl -g -u "YOUR_API_KEY:" \
        "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&page[size]=10"
      ```
    </CodeGroup>

    Each transaction includes:

    * `operation_type` - the high-level action (trade, send, receive, deposit, etc.)
    * `transfers[]` - individual token movements with direction (`in`/`out`/`self`)
    * `fee` - gas fee paid, with USD value
    * `application_metadata` - the DApp involved (e.g., "Uniswap", "Aave")
  </Step>

  <Step title="Filter by operation type">
    To show only specific transaction types, use `filter[operation_types]`.

    ```bash theme={null}
    # Show only trades (swaps)
    curl -g -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&filter[operation_types]=trade"
    ```

    Available operation types:

    | Type | Description |
    | - | - |
    | `send` | Sent tokens to another address |
    | `receive` | Received tokens from another address |
    | `trade` | Swapped tokens (e.g., on a DEX) |
    | `deposit` | Deposited into a DeFi protocol |
    | `withdraw` | Withdrew from a DeFi protocol |
    | `mint` | Minted new tokens |
    | `burn` | Burned tokens |
    | `approve` | Approved token spending |
    | `claim` | Claimed rewards or airdrops |
    | `execute` | Generic smart contract interaction |
    | `deploy` | Deployed a smart contract |
  </Step>

  <Step title="Filter by chain and date range">
    Narrow results to specific chains or time windows. The `filter[min_mined_at]` value is a **Unix timestamp in milliseconds**.

    ```bash theme={null}
    # Ethereum transactions since Feb 26, 2024 (1708905600000 ms)
    curl -g -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&filter[chain_ids]=ethereum&filter[min_mined_at]=1708905600000"
    ```
  </Step>

  <Step title="Paginate through full history">
    Use `links.next` from each response to fetch the next page.

    <CodeGroup>
      ```javascript JavaScript theme={null}
      async function getFullHistory(address) {
        const allTxs = [];
        let url = `https://api.zerion.io/v1/wallets/${address}/transactions/?currency=usd&page[size]=100`;

        while (url) {
          const response = await fetch(url, {
            headers,
          });
          const result = await response.json();
          allTxs.push(...result.data);
          url = result.links.next || null;
        }

        return allTxs;
      }
      ```

      ```python Python theme={null}
      def get_full_history(address):
          all_txs = []
          url = f"https://api.zerion.io/v1/wallets/{address}/transactions/"
          params = {"currency": "usd", "page[size]": 100}

          while url:
              response = requests.get(url, params=params, auth=(api_key, ""))
              result = response.json()
              all_txs.extend(result["data"])
              url = result["links"].get("next")
              params = {}  # params are included in the next URL

          return all_txs
      ```
    </CodeGroup>
  </Step>

  <Step title="Full working example">
    Save as `tx-history.mjs` and run with `node tx-history.mjs`:

    ```javascript theme={null}
    const API_KEY = process.env.ZERION_API_KEY;
    const BASE_URL = "https://api.zerion.io/v1";
    const headers = {
      accept: "application/json",
      authorization: `Basic ${btoa(API_KEY + ":")}`,
    };

    async function getTransactions(address, { types, chains, limit } = {}) {
      const params = new URLSearchParams({ currency: "usd", "page[size]": limit || 20 });
      if (types) params.set("filter[operation_types]", types);
      if (chains) params.set("filter[chain_ids]", chains);

      const res = await fetch(
        `${BASE_URL}/wallets/${address}/transactions/?${params}`,
        { headers }
      );
      return res.json();
    }

    async function displayHistory(address) {
      const { data } = await getTransactions(address, { limit: 10 });

      for (const tx of data) {
        const { operation_type, mined_at, transfers, fee, application_metadata } = tx.attributes;
        const chain = tx.relationships.chain.data.id;

        console.log(`[${mined_at}] ${operation_type} on ${chain}`);
        if (application_metadata?.name) {
          console.log(`  via ${application_metadata.name}`);
        }
        for (const transfer of transfers) {
          const symbol = transfer.fungible_info?.symbol || "NFT";
          const dir = transfer.direction === "out" ? "-" : "+";
          console.log(`  ${dir}${transfer.quantity.float} ${symbol} (${transfer.value != null ? `$${transfer.value.toFixed(2)}` : "N/A"})`);
        }
        console.log(`  Fee: ${fee.value != null ? `$${fee.value.toFixed(2)}` : "N/A"}\n`);
      }
    }

    displayHistory("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045");
    ```
  </Step>
</Steps>

## Next steps

* Use `filter[asset_types]=nft` to show NFT transfers
* Combine with the [DApps endpoint](/api-reference/dapps/get-list-of-dapps) to enrich `application_metadata`
* Build real-time alerts using the [webhook recipe](/recipes/wallet-activity-alerts) instead of polling


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.