A wallet address, an exchange API and a CSV file are not competing ways to import the same truth.
They are windows into different ledgers.
The cleanest portfolio record starts by asking two questions for every account and period: Where did this activity actually happen, and which source can prove it without duplicating another source?
The answer is usually a map, not one universal import method.
Build an account-by-period source map
Consider a portfolio with four histories:
| Account / period | Primary source | Why | Secondary evidence |
|---|---|---|---|
| Active exchange, 2025–present | Read-only API | Internal trades, fees, deposits and withdrawals can update continuously | Official CSV only for a documented API gap |
| Closed exchange, 2021–2024 | Original CSV / statement | The account may no longer expose a working API | Blockchain transfers to cross-check deposits and withdrawals |
| Ethereum self-custody wallet | Public address | On-chain transactions and balances are independently verifiable | Manual classification for unsupported protocol activity |
| Bitcoin hardware wallet | xpub or complete address set | One wallet can derive many addresses | Exchange records for off-chain acquisition history |
This prevents a common mistake: importing everything through every available route and hoping duplicate detection can reconstruct which records describe the same economic event.
Public addresses prove chain activity, not acquisition history
For transparent self-custody activity, the blockchain is the primary ledger.
An Ethereum address can show balances, token transfers and contract interactions recorded on that chain. It cannot tell you what an asset cost on an exchange before it arrived, whether a transfer was income, or whether the sender and recipient belong to the same person.
For Bitcoin-style wallets, one address may cover only a fraction of the wallet. An extended public key can allow watch-only software to derive a broader branch of addresses without signing authority. That improves coverage and increases privacy exposure because more of the wallet’s transaction graph becomes linkable.
Use the least revealing public data that still covers the wallet you need to reconstruct.
An exchange API proves what the exchange exposes
A dedicated read-only API is usually the natural source for an active exchange account because many trades never appear individually on-chain. The blockchain may show one deposit and one withdrawal while the internal account contains hundreds of fills, conversions, fees or reward records.
The important caveat is scope.
A successful API connection proves that the endpoint responded. It does not prove that every historical product, migrated account or old transaction is available through that endpoint.
When an API is incomplete, document the missing period or product before adding another source. Do not simply layer a full-history CSV on top of the same wallet.
A CSV is a snapshot with one important advantage: it can outlive the connection
A CSV or official statement is fixed evidence for a defined account and period. That makes it useful for closed exchanges, unsupported products and periods an API no longer returns.
Keep the untouched original. If the file has to be reformatted for a tracker, preserve the source file separately from the working copy.
The fixed nature of a CSV is also its weakness. New activity does not appear automatically, export windows can omit records and formats can change between years.
A CSV is therefore not “manual and inferior.” It is durable evidence whose coverage must be stated explicitly.
The duplicate problem begins when source scopes overlap
Koinly’s current documentation makes the limitation concrete: its duplicate detection is designed around exact matches, and mixing API data with CSV data can still create duplicates when timestamps, fees, aggregation or other fields differ. Koinly therefore recommends using one import method per wallet where possible.
That is a useful general rule even outside Koinly.
Two records can describe the same economic event without being textually identical:
- an API can report several order fills while a CSV reports one aggregated trade;
- one source can include a fee inside the amount while another reports it separately;
- timestamps can differ by timezone or precision;
- an exchange withdrawal can appear once in the exchange ledger and again as an on-chain receipt;
- asset identifiers can differ between ticker symbols and contract addresses.
The safest fix is source ownership: one primary source for each account and period, then narrowly scoped secondary evidence for a known gap.
Use a source ledger when the history gets complicated
For each import, record:
| Field | Example |
|---|---|
| Account | Exchange A spot account |
| Period | 2023-01-01 to 2024-12-31 |
| Primary source | Official trade-history CSV |
| Coverage | Spot trades + fees; excludes earn product |
| Secondary source | Earn CSV for same account, non-overlapping product scope |
| Original preserved | Yes |
| Known gap | January 2023 fiat deposit statement missing |
This sounds bureaucratic until a dashboard total is wrong. Then the source ledger tells you where to look.
Do not choose the “most accurate” method in the abstract
The most accurate source depends on the event.
Self-custody transfer: use the chain record.
Exchange-internal trade: use the exchange ledger or official statement.
Old account with no API: use the preserved file or statement.
Unsupported DeFi action: use chain evidence plus documented protocol interpretation.
Manual correction: use it only when a primary fact exists but the software cannot represent it automatically.
Accuracy comes from matching evidence to the event, not from preferring automation or manual files as a category.
Privacy and spending authority are separate questions
A public address normally cannot spend, but it can reveal a financial history. An xpub can reveal a larger wallet graph. A read-only API should not trade or withdraw when configured correctly, but it may expose detailed account activity. A CSV cannot move funds, but the file can contain years of sensitive financial records.
“No spending permission” is a security property. It is not a privacy guarantee.
Before creating an exchange key, follow the read-only API key security guide.
The final reconciliation is simple to describe
- List every account, including empty and closed ones.
- Split history into periods when source coverage changed.
- Name one primary source for each account-period.
- Add secondary evidence only for a documented missing period or product.
- Reconcile opening and ending quantities.
- Trace transfers between accounts you own.
- Preserve original files and export the normalised ledger.
- Record unresolved gaps instead of forcing the final number to look clean.
The best import architecture is not “API,” “CSV” or “wallet address.” It is a continuous evidence chain with no unexplained gaps and no duplicated ownership of the same event.
For the broader data-model problem, read What Portfolio Trackers Know, Guess and Miss. If the final balance is already wrong, use the balance-reconciliation guide.








