Address counterparties
See this ranking on an entity page →
Who does this address actually deal with? The method ranks the addresses one address interacts with most, by successful transactions, counting three surfaces at once: top-level transactions, internal calls and token transfers.
GET https://tracefast.xyz/api/v1/chains/1/entities/{address}/counterparties
| Parameter | In | Type | Notes |
|---|---|---|---|
address | path | string | 0x-prefixed, 40 hex characters, any case |
block | query | integer, optional | The ranking as it stood at the end of this block — everything up to and including it. Absent: the current all-time ranking |
limit | query | integer, optional | 1..100, default 100 |
chains/1 is a literal: the method serves Ethereum mainnet data. Other chain
ids answer 404 chain_not_supported.
Access — an API key on the Intelligence plan or higher (plans), or no key at all: pay per call with x402 at the same path on https://mpp.tracefast.xyz/api/v1, at the price its 402 states. As a tool for AI agents: get_entity_counterparties on the MCP server. Stable — see stability.
Response
200 application/json, trimmed to one row:
{
"data": {
"address": "0x28c6c06298d514db089934071355e5743bf21d60",
"window": { "kind": "all", "asOfBlock": 25893676 },
"corpus": 16301939,
"corpusBasis": "precomputed",
"boundaryTieCount": 0,
"counterparties": [
{
"counterparty": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"succeededTxCount": 3664523,
"interactionTxCount": 3665029,
"sentTxCount": 3665029,
"receivedTxCount": 4,
"firstBlock": 12509940,
"lastBlock": 25893673,
"surfaces": ["external", "token"],
"tokenClasses": ["fungible", "nft"]
}
]
},
"meta": {
"chain": "ethereum",
"timestamp": 1788446231548,
"cached": false,
"docs": "https://docs.tracefast.xyz/api/address-counterparties"
}
}data
| Field | Meaning |
|---|---|
address | the address the ranking is about, lowercase |
window.kind | all — the whole history up to asOfBlock; block — everything up to and including the requested block |
window.asOfBlock | the block the ranking is true as of: for all, the block the current ranking is valid at; for block, the block you asked for |
corpus | how many distinct counterparties the ranking covered — the size of the set this list is the top of. 100 out of 216,770 is a different statement from 100 out of 104 |
corpusBasis | precomputed for the current ranking, at_block for a past one |
boundaryTieCount | how many counterparties are level with the last row served and did not make the list |
counterparties[] | the rows, in ranking order, at most limit of them |
A counterparty row
| Field | Meaning |
|---|---|
counterparty | the address, lowercase |
succeededTxCount | the ranking key: transactions between the two that succeeded |
interactionTxCount | all transactions between the two, attempts included — reverted ones too |
sentTxCount, receivedTxCount | direction, relative to the ranked address |
firstBlock, lastBlock | the first and last block the two interacted in, within the window |
surfaces | where the relation was observed: external (top-level transactions), internal (calls inside transactions), token (token transfers). A surface missing here had no interaction between the two |
surfaceCounts | transactions per listed surface, on the attempts scale. A transaction touching two surfaces counts on both, so these do not add up to the ranking key. Absent when the breakdown was not computed for this address — absence means "not computed", never zero |
tokenClasses | fungible, nft or both; present only when surfaces includes token. It says which classes, not in what proportion |
Ranking, ties and the corpus
Rows are ordered — most successful transactions first, then most recent, then
by address — and they carry no rank number. That is deliberate: at the
hundredth place of a mid-sized address there are typically hundreds of
counterparties with identical counts, and numbering them would invent a
precision the data does not have. boundaryTieCount says how many equals were
left just outside the list, and corpus says how large the set was that these
rows are the top of. Read the two together before calling a list "the
counterparties of an address".
Asking about a past block
?block=N reconstructs the ranking from the full history up to and including
block N. Two answers are refused rather than approximated:
- An address too large to rank at a past block is refused with the bound
stated (
details.reason=peer_count_over_limitorrow_count_over_limit, with the measured value and the maximum). The current ranking — the same call withoutblock— is still available. - A block past the covered history answers
422 block_not_availablewithdetails.maxAvailableBlock, the highest block that can be answered.
Neither case returns a narrowed set that looks like a complete answer.
Errors
Every error is JSON: { "error": { "code": "...", "message": "...", "details": { … } } }
| Status | code | When | details |
|---|---|---|---|
| 400 | bad_request | malformed address; block not positive; limit outside 1..100; an unknown query parameter | reason: limit_out_of_range, limit, maxLimit |
| 400 | bad_request | with block: the address is too large to rank at a past block | reason: peer_count_over_limit, peerCount, maxPeerCount; or reason: row_count_over_limit, rowCount, maxRowCount |
| 422 | block_not_available | block is past the covered history | reason: block_not_available, maxAvailableBlock |
| 404 | chain_not_supported | a chain id other than 1 | — |
| 402 | — | payment required, or payment rejected — see Paying with x402 | — |
Numbers a client has to act on are always in details. Never parse them out of
message, which is written for a human reader.
What to expect
A full response at limit=100 stays under 27 KB.
Related pages
- API — the method list and the response envelope
- Paying with x402 — how a call is paid for
- Address attributes — the sibling method: what an address is
- Accounts & Wallets — the same ranking, read in the app
Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown