Events emitted by a contract
Open the contract's events on its entity page →
The event logs a contract emitted, newest first, each with its topics and data and, where the signature is known, the decoded event and its arguments.
GET https://tracefast.xyz/api/v1/chains/1/contracts/{address}/events
| Parameter | In | Type | Notes |
|---|---|---|---|
address | path | string | the emitting contract, 0x-prefixed, 40 hex characters, any case |
limit | query | integer, optional | 1..100, default 25 |
cursor | query | string, optional | nextCursor of the previous page, passed back unchanged |
topic0 | query | string, optional | one event signature hash to narrow to, 0x + 64 hex characters |
fromBlock | query | integer, optional | inclusive lower block bound |
toBlock | query | integer, optional | inclusive upper block bound |
Access — an API key on the Investigation 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_contract_events 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
- Logs emitted by this address. For a proxy that is the proxy's address — events are emitted in the proxy's context even when the code runs in the implementation.
- A decoding is a best match.
decodeStatussays how far to trustdecoded:ambiguousmeans several known signatures share the event hash and the most likely one was used.topicsanddataare always the raw truth. topic0on a very active contract needs a block window. Narrowing by signature searches the contract's whole history; when it is too long, the request is refused with the window it needs instead of running for minutes. Paging withouttopic0is never refused for size.
What event logs, topics and data are: ethereum.org — transactions and logs.
Response
200 application/json, WETH with ?limit=2:
{
"data": {
"chainId": 1,
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"events": [
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockNumber": 25947346,
"txIndex": 463,
"logIndex": 897,
"logIndexInTx": 4,
"txHash": "0x044042e873b184589a94b801c843fc8324c367dac010f0891ad73999d534c964",
"timestamp": 1789047611,
"topics": [
"0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65",
"0x0000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad"
],
"data": "0x00000000000000000000000000000000000000000000000000008ee3bc62320c",
"decoded": {
"name": "Withdrawal",
"args": [
{ "name": "src", "type": "address", "value": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", "indexed": true },
{ "name": "wad", "type": "uint256", "value": "157108769272332", "indexed": false }
],
"candidateCount": 3
},
"decodeStatus": "ambiguous"
},
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockNumber": 25947346,
"txIndex": 463,
"logIndex": 895,
"logIndexInTx": 2,
"txHash": "0x044042e873b184589a94b801c843fc8324c367dac010f0891ad73999d534c964",
"timestamp": 1789047611,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"0x0000000000000000000000006f9beaac7d042a50008db301833abbe92e4f3a8f"
],
"data": "0x00000000000000000000000000000000000000000000000000429616e07b51c4",
"decoded": {
"name": "Transfer",
"args": [
{ "name": "from", "type": "address", "value": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", "indexed": true },
{ "name": "to", "type": "address", "value": "0x6f9beaac7d042a50008db301833abbe92e4f3a8f", "indexed": true },
{ "name": "value", "type": "uint256", "value": "18742373462528452", "indexed": false }
],
"candidateCount": 3
},
"decodeStatus": "ambiguous"
}
],
"nextCursor": "AVsyNTk0NzM0Niw4OTVdFmjLXLqITHfbq9YxtrR5rA"
},
"meta": {
"chain": "ethereum",
"timestamp": 1789047628626,
"cached": false,
"docs": "https://docs.tracefast.xyz/api/contract-events"
}
}data
| Field | Meaning |
|---|---|
chainId | 1 — Ethereum mainnet |
address | the contract, lowercase |
events[] | this page, newest first |
nextCursor | the cursor of the next page. Absent on the last page |
An event
| Field | Meaning |
|---|---|
address | the contract that emitted the log |
blockNumber | the block the log is in |
txIndex | the transaction's index within the block |
logIndex | the log's index within the block |
logIndexInTx | the log's index within its transaction — the emission order |
txHash | the transaction that emitted the log |
timestamp | the block's time, Unix seconds |
topics[] | the topics in order; topics[0] is the event signature hash |
data | the non-indexed data, 0x-prefixed hex |
decodeStatus | verified (one known signature, decoded), partial, ambiguous (several signatures share the hash; decoded is the best candidate), inferred, abi_missing (signature unknown), failed (known, but the data did not decode) |
decoded | the decoded event: name, args[] in declaration order, and candidateCount — how many known signatures share the hash. Absent when the signature is unknown or the data does not decode |
A decoded argument
| Field | Meaning |
|---|---|
name | the argument's name |
type | its Solidity type, for example address or uint256 |
indexed | true when it came from a topic, false when from data |
value | addresses as 0x strings, integers as decimal strings, bytes as 0x hex, booleans as booleans |
An indexed dynamic argument — a string, bytes or an array — is only its hash on
chain, so its value is { "hash": "0x…", "dynamic": true } rather than the
original.
Pagination
Keyset paging, newest first: pass nextCursor back as cursor, with the same
topic0, fromBlock and toBlock, until nextCursor is absent. A cursor
used with other filters is refused with 400 invalid_cursor — restart from the
first page. A page holds at most limit events and may hold fewer while
nextCursor is still present: a page is bounded by size when logs carry large
data, and a log is never cut. See pagination.
Errors
| Status | code | When | details |
|---|---|---|---|
| 400 | bad_request | topic0 is not 0x + 64 hex characters | reason: topic0_invalid |
| 400 | bad_request | limit outside 1..100 | reason: limit_out_of_range, limit, maxLimit: 100 |
| 400 | bad_request | fromBlock is above toBlock | reason: block_window_inverted, fromBlock, toBlock |
| 400 | bad_request | topic0 on a contract with too many logs to filter without a window — pass fromBlock/toBlock spanning at most maxSpanBlocks | reason: filter_needs_block_window, filters, rowCount, maxUnboundedRowCount, spanBlocks, maxSpanBlocks |
| 400 | invalid_cursor | the cursor is not valid for this request — restart from the first page | — |
For USDT, topic0 without a window is refused with maxSpanBlocks: 50400 —
about a week of blocks — and the message: "filtering this contract by topic0
needs a block window of at most 50400 blocks (requested span 25925128). Pass
fromBlock/toBlock. Paging without filters is unaffected." Read the bound from
details on every refusal; it is not a constant.
Malformed input, unknown parameters and the key check's 401/403/429 are the same for every method — see conventions and API keys.
Related pages
- Event logs of a transaction — the same logs, by transaction
- One contract — what emitted them
- Implementations of a proxy contract — the code behind a proxy's events
- Contracts on the entity page — events, read in the app
Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown