Skip to content

Wallet Data Walkthrough ​

Pull native balances, ERC-20 holdings, NFT positions, transfer history, approvals, swaps, and a wallet-level PnL — all from one address path.

The wallet surface lives under GET /v1/wallets/{address}/... and is the most-used part of the API. This guide walks through the five endpoints you will hit most often, with real request and response shapes, then points at the rest.

Endpoint map ​

EndpointReturnsTypical use
GET /v1/wallets/{address}/native-balanceNative gas-token balance at tipQuick "is this wallet active?" check
GET /v1/wallets/{address}/balancesNative + ERC-20 balances, USD valuationPortfolio dashboards
GET /v1/wallets/{address}/native-transfersPaginated native (ETH/BNB/MATIC/…) transfersCash-flow / accounting feeds
GET /v1/wallets/{address}/erc20-transfersPaginated ERC-20 transfersToken activity, tax exports
GET /v1/wallets/{address}/transfersCombined feed (native + ERC-20 + NFTs)One-call wallet history
GET /v1/wallets/{address}/nft-transfersPaginated NFT (ERC-721/1155) transfersNFT lifecycle, mints, sales
GET /v1/wallets/{address}/nftsCurrent NFT holdingsNFT portfolio views
GET /v1/wallets/{address}/approvalsOutstanding ERC-20 / NFT approvalsRisk dashboards ("revoke.cash" style)
GET /v1/wallets/{address}/defi-positionsOpen Lido / Aave V3 / Compound V3 / Uniswap V3 positionsDeFi exposure (see DeFi guide)
GET /v1/wallets/{address}/swapsDecoded DEX swaps (Uniswap, Sushi, Curve, …)PnL attribution, slippage analysis
GET /v1/wallets/{address}/pnlRealised + unrealised PnL roll-upTax / performance reports
GET /v1/wallets/{address}/net-worthTotal USD value across chainsSingle-number portfolio summary
GET /v1/wallets/{address}/detailsMetadata: contract / EOA, first/last seen, tx countAddress fingerprinting
GET /v1/wallets/{address}/interactionsCounterparties grouped by frequencyGraph / cluster analysis
GET /v1/wallets/{address}/domainsENS / Unstoppable / SNS name resolutionDisplay names

All endpoints accept an optional chain query parameter (slug — see Chain IDs). Omit it to query Ethereum mainnet by default; pass ?chain=all (on supported endpoints) to fan out across every indexed chain.

Example 1 — current portfolio value ​

Get every token balance for an address on Ethereum, with USD valuation.

bash
curl 'https://api.cryptachain.com/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?chain=ethereum' \
  -H "X-API-Key: $CRYPTACHAIN_API_KEY"
python
import os, requests

r = requests.get(
    "https://api.cryptachain.com/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances",
    params={"chain": "ethereum"},
    headers={"X-API-Key": os.environ["CRYPTACHAIN_API_KEY"]},
)
data = r.json()
print(f"Total: ${data['total_usd']:,.2f} across {len(data['balances'])} assets")
typescript
const r = await fetch(
  'https://api.cryptachain.com/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?chain=ethereum',
  { headers: { 'X-API-Key': process.env.CRYPTACHAIN_API_KEY! } },
);
const data = await r.json();
console.log(`Total: $${data.total_usd.toFixed(2)} across ${data.balances.length} assets`);

Response (truncated):

json
{
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "chain": "ethereum",
  "balances": [
    { "asset": "ETH",  "balance": "1234.567890123456789", "balance_usd": 4815162.34, "type": "native" },
    { "asset": "USDC", "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "balance": "50000.000000", "balance_usd": 50000.00, "type": "erc20" }
  ],
  "total_usd": 4865162.34,
  "block_number": 21950000,
  "timestamp": "2026-04-04T14:30:00Z"
}

Add ?includeSpam=true to receive suspected airdrop / spam tokens (filtered out by default — see the spam detection section below).

Example 2 — full ERC-20 history for a tax export ​

Pull every USDC transfer for an address in a date range, with USD valuation at the time of each transfer.

bash
curl 'https://api.cryptachain.com/v1/wallets/0xd8dA.../erc20-transfers' \
  --data-urlencode 'chain=ethereum' \
  --data-urlencode 'contractAddress=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' \
  --data-urlencode 'fromDate=2026-01-01T00:00:00Z' \
  --data-urlencode 'toDate=2026-03-31T23:59:59Z' \
  --data-urlencode 'limit=1000' \
  -G \
  -H "X-API-Key: $CRYPTACHAIN_API_KEY"

Response shape (one transfer):

json
{
  "txHash": "0xabc...",
  "blockNumber": 21950100,
  "timestamp": "2026-04-04T14:35:00Z",
  "from": "0xd8dA...",
  "to":   "0x1234...",
  "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  "tokenSymbol": "USDC",
  "tokenDecimals": 6,
  "value": "50000.000000",
  "direction": "out"
}

The response includes a cursor token; pass it back as ?cursor=... to walk through every page. See Batch processing for the full pagination loop and rate-limit-aware retry pattern.

Date range is capped at 365 days

fromDate / toDate must span ≤ 365 days. For longer windows, walk the range in 12-month chunks. The cursor inside a single window is unbounded.

Example 3 — combined native + token feed (one call) ​

If you want all activity, not just one asset class, use /transfers instead of the per-type variants. It returns native, ERC-20, and NFT transfers in a single chronological stream.

bash
curl 'https://api.cryptachain.com/v1/wallets/0xd8dA.../transfers?chain=ethereum&limit=5&includePrices=true' \
  -H "X-API-Key: $CRYPTACHAIN_API_KEY"

Each row carries direction ("in" / "out") relative to the queried address — there's no need to compare from / to yourself. Setting includePrices=true adds price_usd and value_usd columns, valued at the block timestamp. The default currency=USD can be swapped for any of the 36 supported currencies.

Trade-off: the combined endpoint is convenient but slightly slower (~50ms vs ~30ms for the per-asset-class variants), because three indexes are scanned. For high-throughput exports, prefer the per-type endpoints.

Spam and airdrop filtering ​

By default, /balances, /erc20-transfers, and /transfers filter out tokens that the spam detector flags as airdrop spam (homoglyph names, suspicious URLs in the symbol, "claim reward" patterns, contracts that have never received a non-airdrop transfer). To bypass the filter, pass ?includeSpam=true.

This is opt-in for a reason: most users do not want to see thousands of $1 worth of garbage tokens in a portfolio view. If you are building a security tool or block-explorer, set it to true.

DeFi positions ​

For non-trivial positions — LP shares, lending collateral, staking — use /defi-positions, which decodes the underlying protocol state (Lido stETH shares, Aave V3 supply / borrow, Compound V3 markets, Uniswap V3 NFTs). See the DeFi guide for the full response shape and supported protocols.

Multi-chain queries ​

Most endpoints accept chain= as a slug (ethereum, polygon, bsc, …). Some — like /balances and /net-worth — also accept chain=all to fan out across every indexed chain in parallel. This is slower (the response is gated by the slowest chain), but saves you N round-trips for portfolio dashboards.

Common pitfalls ​

Address case

For EVM chains, addresses are stored lowercase in the index. The API accepts mixed-case (EIP-55) input and normalises it; you can pass 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 or 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 — both match. For Bitcoin / Solana / TRON, addresses are case-sensitive — passing the wrong case will return 400 INVALID_ADDRESS.

Tip-of-chain vs historical balance

/native-balance and /balances return the current balance. To get a balance at a historical block, use the transfer history and sum debits/credits yourself, or contact us about the per-block snapshot endpoint (Enterprise tier).

Try it live ​

The /playground lets you call any of the wallet endpoints with your own API key. Filter the operations list by tag Wallets to scope down.

Next steps ​

CryptaChain API — built by CryptaCount Luxembourg S.a r.l.