Skip to content
TraceFast Docs

Relation history of an address

Open the USDC contract in TraceFast →

Every relation interval an address has held, oldest first, with the block window of each. Read from either side:

  • direction=subject (default) — what the address pointed at: every implementation a proxy has used, every delegation target of an account;
  • direction=object — who pointed at the address: every proxy that has used an implementation.
GET https://tracefast.xyz/api/v1/chains/1/entities/{address}/relations/history
ParameterInTypeNotes
addresspathstring0x-prefixed, 40 hex characters, any case
directionquerystring, optionalsubject (default) or object
attributeIdquerystring, optionalone relation id, e.g. relation:eip7702_delegates_to — only that relation's intervals
limitqueryinteger, optional1..500, default 100
cursorquerystring, optionalnextCursor of the previous page, unchanged

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_relation_history on the MCP server. Stable — see stability.

chains/1 is a literal: other chain ids answer 404 chain_not_supported. An unknown parameter is refused rather than ignored.

What it covers, and what it does not

  • Only the relation ids in coveredFamilies. An empty or short timeline says nothing about relations outside that list.
  • Paged, oldest first. A page holds up to limit intervals; truncated: true and nextCursor say there is more. total counts the whole timeline on the subject side only. On the object side one implementation can be pointed at by millions of proxies, so that side is not counted and has no total — page through it, or stop at the oldest part you need.
  • One relation at a time, if you want. attributeId narrows the timeline to one relation id — relation:eip7702_delegates_to gives every EIP-7702 delegation an account signed — and total then counts only that id. The id is checked for form, not against a list: an id outside coveredFamilies answers its intervals without total, and an empty list then says nothing about that relation. For an id in coveredFamilies, total: 0 is a real zero.
  • Absence means "not proven", never "false".

Response

200 application/json for the USDC proxy, here with ?limit=5:

{
  "data": {
    "chainId": 1,
    "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    "direction": "subject",
    "intervals": [
      { "attributeId": "relation:was_implementation_of", "counterpart": "0x0882477e7895bdc5cea7cb1552ed914ab157fe56", "startBlock": 6082465, "endBlock": 10743414 },
      { "attributeId": "relation:was_implementation_of", "counterpart": "0xb7277a6e95992041568d9391d09d0122023778a2", "startBlock": 10743414, "endBlock": 12317814 },
      { "attributeId": "relation:was_implementation_of", "counterpart": "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", "startBlock": 12317814, "endBlock": 18963716 },
      { "attributeId": "relation:was_implementation_of", "counterpart": "0x43506849d7c04f9138d1a2050bbf3a0c054402dd", "startBlock": 18963716 }
    ],
    "coveredFamilies": [
      "relation:was_implementation_of",
      "relation:eip7702_delegates_to",
      "relation:proxy_reads_beacon",
      "relation:proxy_administered_by",
      "relation:freeze_membership"
    ],
    "truncated": false,
    "total": 4
  },
  "meta": {
    "chain": "ethereum",
    "timestamp": 1789047687107,
    "cached": false,
    "asOfBlock": 25924843,
    "docs": "https://docs.tracefast.xyz/api/address-relation-history"
  }
}

Four implementations since the proxy was deployed, each upgrade closing one interval at the block where the next one opens. The last interval has no endBlock: it is the implementation in use now.

data

FieldMeaning
chainId1, Ethereum mainnet
addressthe address, lowercase
directionthe side the address is read on, echoed
intervals[]ascending by startBlock, then by relation id
coveredFamiliesthe relation ids the history is built for
truncatedtrue when the timeline continues past this page — exactly when nextCursor is present
nextCursorcursor for the next page. Absent on the last page
totalhow many intervals the address holds as the subject — the length of the whole timeline, or of the one relation attributeId names. Absent under direction=object, which is not counted, and when attributeId is outside coveredFamilies

An interval

FieldMeaning
attributeIdthe relation id, relation:name
counterpartthe other end, lowercase: the object when the address is the subject, the subject when it is the object
startBlockthe first block the relation held at
endBlockthe last block it held at. Absent when the interval was still open at the end of the covered history
valuethe relation's value over the interval, for relations that carry one; absent otherwise

A relation can hold for a single block — an EIP-7702 delegation set and replaced in the same block, for example. Such an interval has startBlock equal to endBlock. It is real history; do not drop it.

Pagination

Keyset pagination: pass nextCursor back as cursor, with the same address, direction and attributeId, until the response carries no nextCursor. A cursor is valid only for this method, this address, this direction and this attributeId — a cursor issued without the filter does not open a filtered timeline, and the other way round; anything else answers 400 invalid_cursor — restart from the first page. See pagination.

Errors

StatuscodeWhendetails
400bad_requestdirection is not subject or objectreason: direction_invalid, direction
400bad_requestlimit outside 1..500reason: limit_out_of_range, limit, maxLimit: 500
400bad_requestattributeId is empty or not a short identifier of letters, digits and :_.-reason: attribute_id_invalid
400invalid_cursorthe cursor was not issued for this address, direction and attributeId—

Malformed input, unknown parameters and the key check's 401/403/429 are the same for every method — see conventions and API keys.


Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown