Skip to main content
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

Steps

1
Fetch recent transactions
2
Use the wallet transactions endpoint to get a wallet’s history.
3
JavaScript
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
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'}")
cURL
curl -u "YOUR_API_KEY:" \
  "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&page[size]=10"
4
Each transaction includes:
5
  • 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”)
  • 6
    Filter by operation type
    7
    To show only specific transaction types, use filter[operation_types].
    8
    # Show only trades (swaps)
    curl -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&filter[operation_types]=trade"
    
    9
    Available operation types:
    10
    TypeDescriptionsendSent tokens to another addressreceiveReceived tokens from another addresstradeSwapped tokens (e.g., on a DEX)depositDeposited into a DeFi protocolwithdrawWithdrew from a DeFi protocolmintMinted new tokensburnBurned tokensapproveApproved token spendingclaimClaimed rewards or airdropsexecuteGeneric smart contract interactiondeployDeployed a smart contract
    11
    Filter by chain and date range
    12
    Narrow results to specific chains or time windows. The filter[min_mined_at] value is a Unix timestamp in milliseconds.
    13
    # Ethereum transactions since Feb 26, 2024 (1708905600000 ms)
    curl -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&filter[chain_ids]=ethereum&filter[min_mined_at]=1708905600000"
    
    14
    Paginate through full history
    15
    Use links.next from each response to fetch the next page.
    16
    JavaScript
    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
    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
    
    17
    Full working example
    18
    Save as tx-history.mjs and run with node tx-history.mjs:
    19
    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");
    

    Next steps

    • Use filter[asset_types]=nft to show NFT transfers
    • Combine with the DApps endpoint to enrich application_metadata
    • Build real-time alerts using the webhook recipe instead of polling