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.