Skip to content

Investigation workflow

GET /v1/meta
POST /v1/tron/resolve {"positional": ["<address 1>", "<address 2>", "..."]}
POST /v1/tron/topk {"positional": ["<address>"], "flags": {"dir": "in", "k": 50, "time-start": 1682899200, "time-end": 1685577600}}
POST /v1/tron/neighbors {"positional": ["<address>"], "flags": {"dir": "out", "last": 20, "token": "usdt"}}
POST /v1/tron/trace {"positional": ["<source>"], "flags": {"hops": 4, "start-block": 51000000, "amount": 250000}}
POST /v1/tron/reach {"positional": ["<seed>"], "flags": {"dir": "out", "target-labels": "cex,exchange", "min-edge": 1000}}
POST /v1/tron/annotate {"positional": ["<edge_id>", "<edge_id>"]}
  1. meta: coverage, limits and budget.
  2. resolve every case address at once (up to 1,000). An address that resolves to null has no covered transfers up to max_block; that does not prove it never transacted.
  3. topk: the main counterparties per direction and token.
  4. neighbors with last: the latest transfers, a cheap look before heavier queries.
  5. trace (“where did it go?”) or reach (“does it meet a labelled entity?”).
  6. annotate the edges you cite, to get their block and position.
POST /v1/bitcoin/addr {"positional": ["1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF"]}
POST /v1/bitcoin/cluster {"positional": ["1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF"], "flags": {"members": 20}}
POST /v1/bitcoin/trace {"positional": ["1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF"], "flags": {"node": "cluster", "hops": 4, "top": 100}}

Every call names its network: /v1/bitcoin/..., /v1/ethereum/..., /v1/tron/... or /v1/zcash/.... Never guess it from the address format: Tron and Ethereum both accept 0x-hex and bare 40-hex addresses, and a numeric id means a different address on each network.

Numeric ids from resolve are valid for one network and one dataset version. Do not store them; re-resolve from the address when in doubt.

  • Batch. Many addresses with the same question go in one targets array: up to 200 per topk or neighbors request, 50 per reach. One request, one rate-limit token.
  • Skip labels when you do not need them. no-labels on neighbors, topk, addr and tx makes small queries much faster.
  • Look before scanning. neighbors with last is light; topk is heavy.
  • Narrow early. Use time windows, a shallow reach ({"hops": 2}), and saved answers instead of re-runs. Send one call at a time.

A guard error means the address is too busy for the query as asked. Narrow it rather than resending:

  • Tron and Ethereum topk: the window holds too many transfers. An Ethereum exchange hot wallet fits only a window of days or weeks. Narrow time-start and time-end; find the window with neighbors and last first.
  • Tron and Ethereum trace: the source has too much history to total. Pass amount (the amount you follow) and a start-block near the incident.
  • Bitcoin and Zcash neighbors and topk: the cap counts the node’s whole history, so a block window does not help. Use {"node": "addr"} or a single member address. A Zcash shielded pool is usually over the cap: query the address with {"counterparty": "z:sapling"} instead.

deadline is the same signal from the clock. Never resend a guard, deadline or resource error unchanged.

Answers identify a transaction by its block and its position in the block (tx_index), not by hash.

Tron. neighbors rows carry block and tx_index. For trace edges, annotate the edge ids (up to 1,000 per call) to get block, tx_index, from, to and the amount. Then look the hash up on TronGrid:

GET https://api.trongrid.io/wallet/getblockbynum?num=<block>
→ transactions[<tx_index>].txID

Bitcoin. tx with {"positional": ["<block>", "<tx_index>"]} shows every input and output. For the hash, use any Esplora explorer:

GET /block-height/<block> → <block hash>
GET /block/<block hash>/txid/<tx_index>

Bitcoin trace edges carry block but not tx_index. Run neighbors on the sending node with {"dir": "out", "from-block": <block>, "to-block": <block>} and match the row.

Ethereum. neighbors rows carry block and tx_index; annotate with {"positional": ["<block>", "<tx_index>"]} gives the signer and the time. For the hash, ask any node (the block number in hex) or open the block page of an explorer:

eth_getBlockByNumber(<block>, false) → transactions[<tx_index>]

Ethereum trace edges carry block but not tx_index: match them by block, sender and receiver (eth_getBlockByNumber(<block>, true); for a token, its Transfer logs in that block).

Zcash. tx with {"positional": ["<block>", "<tx_index>"]} as on Bitcoin. For the hash, a node’s getblock(<height>, 1).tx[<tx_index>].

A public explorer learns what you look up. Follow your organisation’s rules for outside lookups.

© 2026 Hansung Onchain Data LabTermsPrivacyGet access