Law Enforcement Off-Ramp Tracing
When investigating a wallet (whether it belongs to a scam recipient, a ransomware payee, or any subject under court-authorized investigation), the first artifact you usually need is a list of regulated exchanges that the wallet sent crypto to, with enough on-chain proof to subpoena each exchange for the recipient's KYC.
This guide shows how to produce that packet in one API call using
GET /wallets/{blockchainId}/{address}/entity-exposure.
What you getβ
For each labeled off-ramp the wallet has used, the response includes:
| Field | What it gives you |
|---|---|
entityName | Exchange / service display name (Binance, Kraken, KuCoin, β¦) |
addresses[] | The hot / deposit addresses on the exchange that received funds |
value | Total value off-ramped (native units, e.g. XRP / BTC) |
transactionCount | Number of distinct deposit transactions |
tx_hashes[] | On-chain hashes for those deposits, verifiable on any block explorer |
destinationTags[] | XRPL destination tags identifying which sub-account at the exchange received the funds (this is what the exchange uses to map a deposit to a specific user) |
minHop / maxHop | How far down the chain the off-ramp was reached |
Together, those fields form a complete, machine-readable, subpoena-grade packet, with no follow-up scraping needed.
Requestβ
curl -s 'https://platform.chainara.io/api/v2/wallets/1/rK5iZaTQiYnEBm9Urr6czVd7jaP84rDXgo/entity-exposure?timeRange=all&maxDepth=2&direction=out&transactionLimit=5000' \
-H 'X-API-Key: ck_live_β¦'
Recommended params for this use case:
| Param | Value | Why |
|---|---|---|
timeRange | all | Captures the wallet's entire off-ramp history, not just recent activity |
direction | out | The investigation is "where did this wallet's money go". Drop inbound to keep the response focused |
maxDepth | 2 (up to 4) | 2 catches a single laundering hop. Bump to 3 or 4 if you suspect heavier mixing (slower scan) |
transactionLimit | 5000 | Maximum hashes returned per entity. Set to 0 for unbounded (use sparingly: large wallets can return thousands of hashes) |
fraudLimit / sharedHubLimit / entityLimit | 5000 (max) | Cap the number of fraud / shared-hub / entity rows. Defaults are 200. The full counts are always reported in summary.*Total fields so you can detect truncation. For comprehensive subpoena packets, set these high. |
minValue | omit | Default 0.01 ignores dust. Don't raise this; small layering deposits are exactly what you want to see |
Response (abridged)β
{
"success": true,
"data": {
"blockchain": { "id": 1, "name": "XRPL", "symbol": "XRP" },
"wallet": { "address": "rK5iZaTQiYnEBm9Urr6czVd7jaP84rDXgo" },
"scan": {
"timeRange": "all",
"maxDepth": 2,
"direction": "out",
"scannedAt": "2026-04-30T20:13:00.000Z",
"nodesScanned": 359,
"linksScanned": 370
},
"summary": {
"outboundEntitiesCount": 10,
"totalOutflowToEntities": 117740.27
},
"outboundEntities": [
{
"entityName": "Binance",
"entityType": "exchange",
"addresses": ["rNxp4h8apvRis6mJf9Sh8C6iRxfrDWN7AV"],
"value": 51228.18,
"transactionCount": 9,
"minHop": 1,
"maxHop": 2,
"tx_hashes": [
"75906AEA40B1C2997220044F962BA87915175EDC19CC690DAAC4568E99AB41EA",
"5630B34C5976746F367440AA7503E8A39DEBB9FD311F86984B061129D01C4238"
],
"destinationTags": ["312623151", "312626004", "312634500", "460674891"]
},
{
"entityName": "KuCoin",
"entityType": "exchange",
"addresses": ["rNFugeoj3ZN8Wv6xhuLegUBBPXKCyWLRkB"],
"value": 28313.07,
"transactionCount": 17,
"minHop": 1,
"maxHop": 2,
"tx_hashes": ["DC9088AA9DD0990FEDAA5F658562C4C867A31E0B7D602611FD05EDD152C005AD"],
"destinationTags": ["2094460229", "2096619350"]
}
]
}
}
Building the subpoena packetβ
For each entry in outboundEntities, you have everything one subpoena
template needs:
entityNameβ who you serve (e.g. Binance Holdings Ltd.)addresses[]β the exchange-controlled receiving addressestx_hashes[]β public proof of each transfer (any block explorer can verify)destinationTags[]β the per-customer routing tag the exchange uses to map deposits to a specific account / KYC record
A typical line in the subpoena packet looks like:
"Subject wallet
rK5iZaTQβ¦sent 4,621.70 XRP to your hot walletrNxp4h8aβ¦in transaction75906AEAβ¦99AB41EAwith destination tag312623151. Please provide the customer account associated with that tag, including KYC records, deposit history, and any linked withdrawal addresses."
Multi-hop tracingβ
When maxDepth > 1, the BFS follows funds through intermediaries and
credits the terminal exchange in the chain. For a path
subject β A β exchange, the exchange row's tx_hashes contain the
hop-2 hashes (the deposit into the exchange), even though the subject
wallet didn't pay the exchange directly.
If you also want the intermediate hop hashes (for asset-tracing across the relay), call the endpoint twice and diff:
# Direct only
curl 'β¦/entity-exposure?direction=out&maxDepth=1' -H 'X-API-Key: β¦' > direct.json
# Through one intermediary
curl 'β¦/entity-exposure?direction=out&maxDepth=2' -H 'X-API-Key: β¦' > one_hop.json
# Hashes in one_hop but not direct = intermediate transfers worth tracing
Inbound tracing (where did the money come from?)β
Flip direction=in to find which exchanges funded the wallet, useful
for victim identification. Same response shape; inboundEntities is
populated instead of outboundEntities.
What counts as "fraud"β
The fraudConnections[].categories array tells you which evidence
sources flagged the address. All of these are FACTS, not heuristics:
| Category | Source |
|---|---|
blacklisted | Curated blacklist table or suspicious_wallets.is_blacklisted=true |
fraud_reported | Internal fraud_reports (Chainara-verified intel + community submissions) |
external_report | Third-party victim reports synced from sources like ChainAbuse, BitcoinAbuse β independent corroboration. Suppressed on labeled known entities (Binance, Coinbase, etc.) unless another fraud signal also fires, since reports against an exchange's hot wallet are typically about other actors using the same address, not the scanned wallet's relationship with the exchange. |
mixer | Address is a known mixer / tumbler service |
high_risk | (Opt-in via highRiskThreshold) heuristic risk-score flag |
The evidence[] strings cite the specific source for each category, e.g.
"2 external victim reports (ChainAbuse, BitcoinAbuse)". Use these
verbatim in subpoena documentation as the basis for your investigative
predicate.
Performance & cachingβ
| Cold | Warm | |
|---|---|---|
| First call against a wallet | 30β90s (multi-hop BFS over full history) | n/a |
| Subsequent calls (same params) | ~50ms, served from server-side cache (5-minute TTL) |
Repeated calls with different transactionLimit or direction
hit the same underlying scan; only the aggregation step re-runs.
Schema referenceβ
See the full request/response schema in the
API Explorer page for getWalletEntityExposure.