Skip to main content
What you’ll build:
  • Fetch a wallet’s total NFT value broken down by chain
  • List NFT collections sorted by floor value
  • Drill into individual NFT positions with metadata
  • Filter by specific collections
NFT value by chain:
  ethereum: $1,820.50
  polygon:  $37.56

Collections:
  Bored Ape Yacht Club:  1 NFT(s) — floor value $1,802.40
  Art Blocks Curated:    2 NFT(s) — floor value $55.11
  Polygon Apes:          3 NFT(s) — floor value $37.56

Individual NFTs:
  Bored Ape #7495 (Bored Ape Yacht Club)  — $1,802.40
  Chromie Squiggle #4821 (Art Blocks)     — $37.55
  Fidenza #479 (Art Blocks)               — $17.56
  Polygon Ape #102 (Polygon Apes)         — $12.52
Time: ~10 minutes

Prerequisites

Steps

1
Get the NFT portfolio overview
2
Start by fetching the wallet’s NFT portfolio to get total NFT value broken down by chain.
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}/nft-portfolio?currency=usd`,
  { headers }
);

const { data } = await response.json();
const byChain = data.attributes.positions_distribution_by_chain;
console.log("NFT value by chain:", byChain);
Python
import os, requests

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

response = requests.get(
    f"https://api.zerion.io/v1/wallets/{address}/nft-portfolio",
    params={"currency": "usd"},
    auth=(api_key, ""),
)

data = response.json()["data"]
by_chain = data["attributes"]["positions_distribution_by_chain"]
print("NFT value by chain:", by_chain)
cURL
curl -u "YOUR_API_KEY:" \
  "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/nft-portfolio?currency=usd"
4
The response includes positions_distribution_by_chain — a map of chain IDs to their total NFT floor value (e.g., ethereum: 1820.50, polygon: 37.56).
5
The API may return a 202 status if the wallet’s NFT data is still being indexed. Poll the endpoint until you receive a 200 response.
6
Fetch NFT collections
7
Get the wallet’s NFT collections grouped by collection, sorted by total floor price.
8
JavaScript
const collectionsRes = await fetch(
  `https://api.zerion.io/v1/wallets/${address}/nft-collections/?currency=usd&sort=-total_floor_price`,
  { headers }
);

const collections = await collectionsRes.json();

for (const collection of collections.data) {
  const { collection_info, nfts_count, total_floor_price } = collection.attributes;
  console.log(
    `${collection_info.name}: ${nfts_count} NFT(s) — floor value ${total_floor_price != null ? `$${total_floor_price.toFixed(2)}` : "N/A"}`
  );
}
Python
collections_response = requests.get(
    f"https://api.zerion.io/v1/wallets/{address}/nft-collections/",
    params={"currency": "usd", "sort": "-total_floor_price"},
    auth=(api_key, ""),
)

for collection in collections_response.json()["data"]:
    attrs = collection["attributes"]
    name = attrs.get("collection_info", {}).get("name", "Unknown")
    count = attrs["nfts_count"]
    floor = attrs.get("total_floor_price")
    print(f"{name}: {count} NFT(s) — floor value {f'${floor:.2f}' if floor is not None else 'N/A'}")
cURL
curl -u "YOUR_API_KEY:" \
  "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/nft-collections/?currency=usd&sort=-total_floor_price"
9
Each collection entry includes:
10
  • collection_info.name — the collection name
  • nfts_count — how many NFTs from this collection the wallet holds
  • total_floor_price — combined floor value of the wallet’s positions in this collection
  • min_changed_at / max_changed_at — acquisition timestamps
  • 11
    Fetch individual NFT positions
    12
    Drill into the specific NFT positions held by the wallet, sorted by floor price.
    13
    JavaScript
    const positionsRes = await fetch(
      `https://api.zerion.io/v1/wallets/${address}/nft-positions/?currency=usd&sort=-floor_price`,
      { headers }
    );
    
    const positions = await positionsRes.json();
    
    for (const position of positions.data) {
      const { nft_info, collection_info, value } = position.attributes;
      console.log(
        `${nft_info?.name} (${collection_info?.name}) — ${value != null ? `$${value.toFixed(2)}` : "N/A"}`
      );
    }
    
    Python
    positions_response = requests.get(
        f"https://api.zerion.io/v1/wallets/{address}/nft-positions/",
        params={"currency": "usd", "sort": "-floor_price"},
        auth=(api_key, ""),
    )
    
    for position in positions_response.json()["data"]:
        attrs = position["attributes"]
        nft_name = attrs.get("nft_info", {}).get("name", "Unknown")
        collection_name = attrs.get("collection_info", {}).get("name", "Unknown")
        value = attrs.get("value")
        print(f"{nft_name} ({collection_name}) — {f'${value:.2f}' if value is not None else 'N/A'}")
    
    cURL
    curl -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/nft-positions/?currency=usd&sort=-floor_price"
    
    14
    Using sort=-floor_price orders NFTs by their floor price (highest first). Each position includes:
    15
  • nft_info.name — the NFT’s name or token ID
  • collection_info.name — the collection it belongs to
  • value — estimated USD value based on the collection’s floor price
  • 16
    Filter by collection (optional)
    17
    To show NFTs from a specific collection, use the filter[collection_ids] parameter. Collection IDs are UUIDs found in the relationships.collection.data.id field of each NFT position returned by the endpoints above.
    18
    curl -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/nft-positions/?currency=usd&filter[collection_ids]=bc31571c-d2a8-45e4-8012-37dbbf8b7038"
    
    19
    Full working example
    20
    Save as nft-portfolio.mjs and run with node nft-portfolio.mjs:
    21
    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 fetchWithRetry(url, maxRetries = 10) {
      for (let i = 0; i < maxRetries; i++) {
        const res = await fetch(url, { headers });
        if (res.status === 202) {
          const retryAfter = res.headers.get("Retry-After") || "3";
          console.log(`NFT data still indexing, retrying in ${retryAfter}s... (${i + 1}/${maxRetries})`);
          await new Promise((r) => setTimeout(r, parseInt(retryAfter) * 1000));
          continue;
        }
        if (!res.ok) throw new Error(`API error: ${res.status}`);
        return res.json();
      }
      throw new Error("Timed out waiting for NFT data after " + maxRetries + " retries");
    }
    
    async function displayNFTPortfolio(address) {
      // 1. Portfolio overview
      const portfolio = await fetchWithRetry(
        `${BASE_URL}/wallets/${address}/nft-portfolio?currency=usd`
      );
      const byChain = portfolio.data.attributes.positions_distribution_by_chain;
    
      console.log("=== NFT VALUE BY CHAIN ===");
      for (const [chain, value] of Object.entries(byChain).sort((a, b) => b[1] - a[1])) {
        console.log(`  ${chain}: $${value.toFixed(2)}`);
      }
    
      // 2. Collections
      const collections = await fetchWithRetry(
        `${BASE_URL}/wallets/${address}/nft-collections/?currency=usd&sort=-total_floor_price`
      );
    
      console.log("\n=== COLLECTIONS ===");
      for (const c of collections.data) {
        const { collection_info, nfts_count, total_floor_price } = c.attributes;
        console.log(`  ${collection_info.name}: ${nfts_count} NFT(s) — ${total_floor_price != null ? `$${total_floor_price.toFixed(2)}` : "N/A"}`);
      }
    
      // 3. Individual NFTs
      const positions = await fetchWithRetry(
        `${BASE_URL}/wallets/${address}/nft-positions/?currency=usd&sort=-floor_price`
      );
    
      console.log("\n=== INDIVIDUAL NFTs ===");
      for (const pos of positions.data) {
        const { nft_info, collection_info, value } = pos.attributes;
        console.log(`  ${nft_info?.name} (${collection_info?.name}) — ${value != null ? `$${value.toFixed(2)}` : "N/A"}`);
      }
    }
    
    displayNFTPortfolio("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045");
    

    Next steps

    • Use pagination to handle wallets with large NFT collections
    • Include the nft_collections relationship in the include parameter to get full collection metadata in one request
    • Combine with the transactions endpoint to track NFT purchase and sale history