- Fetch a wallet’s total PnL (realized, unrealized, fees, external flows)
- Batch-query PnL for up to 100 tokens in one call, with per-token breakdowns
- Compare the same token’s performance across different chains
- Use time-range filters for period-specific PnL
- Handle edge cases (503 bootstrap, airdrops)
Prerequisites
- A Zerion API key (get one here)
- Node.js 18+ (for native
fetch) or any HTTP client
How PnL is calculated
Zerion uses FIFO (First In, First Out) - earliest purchases are matched against earliest sales. This is the most common standard for tax reporting.Response fields
When you add token filters (
fungible_ids or fungible_implementations), the response also includes a breakdown object with per-token stats like average_buy_price, average_sell_price, and gain percentages.
The resource type in the response is
wallet_pnl (not pnl).Steps
Edge cases & operational notes
503 + Retry-After (cold wallets)
503 + Retry-After (cold wallets)
For wallets that haven’t been queried before, or wallets with long transaction histories, the first request may return a
503 with a Retry-After header while PnL is being bootstrapped. This is non-billable. Retry after the indicated delay (usually a few seconds). Once bootstrapped, subsequent requests are fast (under 200 ms for basic PnL queries without a breakdown; building a breakdown adds 150–300 ms depending on the number of tokens). Snapshots are retained for ~1 month; after that, a re-bootstrap may be triggered.Excluded tokens
Excluded tokens
Tokens without reliable price data are omitted from breakdown calculations rather than erroring. They simply won’t appear in the
breakdown object.Airdrop cost basis
Airdrop cost basis
Tokens received as “pure mints” (from the zero address or a token contract with no payment beyond gas) are assigned zero cost basis. However, many airdrops are actually distributed from a non-zero address, which causes them to be misclassified as purchases at the market price at the time of receipt. Keep this in mind when reviewing cost basis data for airdropped tokens.
Base asset format
Base asset format
Native chain tokens use
chain: with an empty address after the colon: ethereum: for ETH, base: for Base ETH, polygon: for MATIC, solana: for SOL.Supported currencies
Supported currencies
16 options via the
currency param: usd, eur, gbp, btc, eth, krw, jpy, aud, cad, inr, nzd, try, zar, cny, chf, rub.Batch limits
Batch limits
Max 100 tokens per request for either
fungible_ids or fungible_implementations. For larger portfolios, paginate with multiple calls.Next steps
- Combine with wallet positions to fetch current holdings, then batch those token IDs into PnL for a complete dashboard
- Add balance charts to visualize portfolio value over time alongside PnL
- Set up webhooks to trigger PnL recalculations when new transactions land