Route examples
Exact examples for Starkscan routes that agents most often misread: block reads, search, trace, contract reads, previews, and holdings.
Route examples
Use this page when an agent needs concrete response-shape examples for routes that are easy to misuse.
Start from the published OpenAPI/docs for the host you are targeting. The bounded public route set below is the supported hosted contract. The machine-readable contract is always available at /starkscan-openapi.yaml.
For failure responses (401/400/403/429) and the exact fix for each, see Your first error and Rate limits — they apply to every route below.
Hosted base shape:
${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/...Quick matrix
| Route | Freshest? | Exact? | Paginated? | Expensive? | Best for wallet state? | Best for tx debugging? |
|---|---|---|---|---|---|---|
GET /block/{block_ref} | block snapshot at the referenced height | yes | no | standard | no | yes |
GET /block-at-timestamp | indexed block at or around the timestamp | yes | no | light | yes, as a balance-of helper | no |
GET /block/{number}/txs | block snapshot at the referenced height | yes | cursor-based | standard | no | yes |
GET /search | no | n/a | no | heavy | no | sometimes |
GET /tx/{tx_hash} | stable historical transaction detail | yes | no | standard | no | yes |
GET /tx/{tx_hash}/trace | stable historical trace | n/a | no | heavy | no | yes |
GET /contract/{address}/read | latest by default | exact spot read | no | heavy | sometimes | yes |
GET /token/{token}/balance-of/{address} | exact at requested block tag | yes | no | light | yes, for known token contracts | no |
POST /tx/previews | historical preview snapshot | compact by default | request-bounded batch | heavy | no | sometimes |
GET /address/{address}/transactions | indexed transaction rows | one row per tx | cursor-based | heavy | no | sometimes |
GET /address/{address}/token-holdings | near-latest indexed state | only when exact=true, truncated=false, and completeness.reasonCode="complete" | no | heavy | yes | no |
Block routes
block_ref is a flexible path segment. It accepts:
- a block number
- a block hash
If you need the current head block, read GET /v1/{chain}/status first and then call /block/{block_ref} with the returned block number or block hash.
GET /block/{block_ref}
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/block/8279910?tx_limit=3"Response shape:
{
"chainId": "SN_MAIN",
"blockNumber": 8279910,
"blockHash": "0x03...",
"parentHash": "0x02...",
"timestampIso": "2026-04-10T15:43:12Z",
"txCount": 31,
"rawObjectKey": "s3://...",
"stateRoot": "0x01...",
"sequencerAddress": "0x02...",
"l1DataAvailabilityMode": "BLOB",
"starknetVersion": "0.14.2",
"l1GasPrice": {
"priceInWei": "0x12a05f200",
"priceInFri": "0x4a817c800"
},
"l2GasPrice": {
"priceInWei": "0x0",
"priceInFri": "0x0"
},
"l1DataGasPrice": {
"priceInWei": "0x10",
"priceInFri": "0x20"
},
"transactions": [
{
"txHash": "0x0abc...",
"txIndex": 30,
"txCursor": "8279910:30",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"executionStatus": "SUCCEEDED",
"finalityStatus": "ACCEPTED_ON_L1"
}
]
}Agent rules:
tx_limitonly controls the preview array on the block detail response.- Use the dedicated
/txsroute when you need the full paginated block transaction list. - Use
blockHash, notrawObjectKey, as the public identity of the block. - Header fields such as
stateRoot,sequencerAddress, gas prices, and Starknet version are nullable for older indexed payloads, but present when Starkscan has the canonical block header metadata.
GET /block/{number}/txs
This child route is numeric-only. If you start from a block hash, resolve the canonical blockNumber first with GET /v1/{chain}/block/{block_ref}. If you need the current head block, read GET /v1/{chain}/status first and then call /block/{number}/txs with that numeric block number.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/block/8279910/txs?limit=2"Response shape:
{
"items": [
{
"txHash": "0x0abc...",
"txIndex": 30,
"txCursor": "8279910:30",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"executionStatus": "SUCCEEDED",
"finalityStatus": "ACCEPTED_ON_L1"
}
],
"nextCursor": "29"
}Agent rules:
- Ordering is newest-first within the resolved block: highest
txIndexto lowest. - If you need the current head block, read
GET /v1/{chain}/statusfirst and then use the returned numeric block number here. GET /block/{number}/txsitself always uses the resolved numeric block number, including follow-up pages withcursor.nextCursoris exclusive. Pass it back ascursorunchanged.
Block events and receipts
The bounded hosted route set does not currently publish per-block events or receipts pages.
Use these instead:
GET /v1/{chain}/block/{block_ref}for canonical block metadataGET /v1/{chain}/block/{number}/txsfor the ordered block transaction listGET /v1/{chain}/tx/{tx_hash}for execution and finality metadata on a specific transactionGET /v1/{chain}/tx/{tx_hash}/tracewhen you need deeper execution context- Resolve
blockNumberfirst when you start from a block hash or current head metadata, then use that numeric block number for/txspagination. - If you need logs or token transfers for a transaction, hydrate
GET /tx/{tx_hash}separately.
GET /search
search is identifier-first. It resolves exact hashes, block numbers, and address-like inputs first, then falls back to bounded prefix search.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/search?q=0x1234"Response shape:
{
"blocks": [],
"transactions": [],
"addresses": ["0x0000000000000000000000000000000000000000000000000000000000001234"]
}Agent rules:
qis required.- Results are split into the top-level
blocks,transactions, andaddressesarrays. - This route is not the place to do generic ticker or symbol discovery.
GET /tx/{tx_hash}/trace
This route returns a trace envelope, not a top-level calls array.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/tx/<tx_hash>/trace"Response shape:
{
"chainId": "SN_MAIN",
"txHash": "0x04...",
"trace": {
"functionInvocations": [],
"validateInvocation": null,
"feeTransferInvocation": null,
"stateDiff": null
}
}Agent rules:
- Treat
traceas the root object. - Do not assume every tx has every invocation section populated.
- Use this route for execution debugging, not latest wallet state.
GET /tx/{tx_hash}
Use transaction detail when you need decoded Starkscan fields and raw evidence for one transaction. This is the route agents should hydrate after they find a hash in address/{address}/transactions, search, or a block tx list.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/tx/<tx_hash>"Response shape:
{
"chainId": "SN_MAIN",
"blockNumber": 8279910,
"timestampIso": "2026-04-10T15:43:12Z",
"txIndex": 30,
"txHash": "0x0abc...",
"txCursor": "8279910:30",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"executionStatus": "SUCCEEDED",
"finalityStatus": "ACCEPTED_ON_L1",
"txType": "INVOKE",
"rawObjectKey": "s3://...",
"calldata": ["0x01", "0x02"],
"receipt": null,
"logsTruncated": false,
"logs": [],
"tokenTransfers": [
{
"logIndex": 4,
"transferIndex": 0,
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"amount": "1000000000000000000",
"tokenId": null,
"standard": "erc20"
}
],
"messages": [],
"messagesCoverage": {
"status": "exact",
"source": "starknet_protocol_messages",
"reasonCode": "no_matching_message_rows",
"message": "No Starknet protocol messages were found for this transaction."
},
"bridgeIntent": null
}Agent rules:
- Prefer decoded fields first:
executionStatus,finalityStatus,txType,tokenTransfers,messages, andbridgeIntent. - Use
calldata,receipt, andlogsas audit evidence, not as the first place to infer user-facing token movement. logsTruncated=truemeans returned logs are bounded; it does not mean missing events are false.tokenTransfersis already normalized from receipt evidence. Keepamountas a decimal string and apply token decimals only after resolving metadata fortokenAddress.
GET /contract/{address}/read
This route requires a raw Starknet selector, not a function name.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/contract/<address>/read?selector=<felt_selector>&block_tag=latest"Response shape:
{
"chainId": "SN_MAIN",
"contractAddress": "0x0123...",
"selector": "0x0456...",
"blockTag": "latest",
"result": ["0x417267656e744163636f756e74"]
}Agent rules:
resultis always an array of felts.- Default view tooling may decode a felt to UTF-8, but the API returns raw felt strings.
- Invalid selector, wrong calldata, or non-view misuse is client error territory, not proof that the route is broken.
GET /token/{token}/balance-of/{address}
Use this for the accounting-style question “what was this account’s balance for this exact token contract at this exact block?” It is an on-chain balanceOf read, not an indexed portfolio screen.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/token/<token>/balance-of/<owner>?block_tag=5007537"Response shape:
{
"chainId": "SN_MAIN",
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"ownerAddress": "0x0123...",
"blockTag": "5007537",
"balanceRaw": "909437023198396908352"
}Agent rules:
balanceRawis a base-10 U256 string. Do not parse it as JavaScriptnumber.blockTagechoes the validated caller input:latest,pending, a block number, or a block hash.- For point-in-time accounting, resolve the timestamp to a block first, then pass the numeric block as
block_tag. - Use
address/{address}/token-holdingsonly for wallet screening; usebalance-ofwhen the token contract is already known and exactness matters.
POST /tx/previews
This route is compact by default. Omitted detail must not be confused with empty detail.
Request:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/tx/previews" \
-d '{"hashes":["0xabc"],"includeLogCounts":true}'Response shape:
{
"items": [
{
"chainId": "SN_MAIN",
"blockNumber": 123,
"txIndex": 12,
"txHash": "0xabc",
"txCursor": "123:12",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"executionStatus": "SUCCEEDED",
"finalityStatus": "ACCEPTED_ON_L2",
"txType": "INVOKE",
"transferCount": 1,
"tokenTransfersTruncated": false,
"tokenTransfers": [],
"logCount": 5,
"logsTruncated": false,
"logs": []
}
]
}Agent rules:
tokenTransfersTruncated=truemeanstokenTransfersis capped for that preview — fetch the fullGET /tx/{tx_hash}for the complete set.logsTruncated=truemeanslogsis capped; passincludeLogCounts(orincludeLogs) in the request sologCountis the authoritative total.- Use previews for lightweight batch hydration, not full forensic decoding.
GET /address/{address}/token-holdings
This is the screening route for wallet portfolio state, but only the completeness contract tells you whether the snapshot is authoritative. It is wallet-first indexed state, not the same thing as an on-chain balanceOf spot read.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/address/<owner>/token-holdings"Response shape:
{
"chainId": "SN_MAIN",
"ownerAddress": "0x0abc...",
"items": [
{
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"normalizedTokenAddress": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"indexedBalanceRaw": "909437023198396908352",
"symbol": "STRK",
"name": "Starknet Token",
"decimals": 18
}
],
"exact": false,
"truncated": false,
"completeness": {
"exact": false,
"truncated": false,
"complete": false,
"reasonCode": "degradedFallback",
"reason": "The response is useful for screening but is not complete enough for exact portfolio parity checks.",
"lagBlocks": null,
"capped": false,
"cap": null
}
}Agent rules:
- Treat the snapshot as complete only when
exact=true,truncated=false, andcompleteness.reasonCode="complete". exact=falsewithtruncated=falseis valid. It means incomplete-but-not-capped, not “empty”.- Use
normalizedTokenAddress,symbol,name, anddecimalsfrom the row when present. Do not infer STRK, ETH, USDC, or bridged assets from raw felts. - Compare
balance-ofagainst holdings only when you already know the token contract and the requests are close in time. - Use
GET /token/{token}/balance-of/{address}for exact spot reads on a known token contract.
GET /address/{address}/transactions
Use this route when an agent needs recent wallet transactions as one row per tx. It avoids repeatedly grouping activity rows by txHash.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/address/<owner>/transactions?limit=25"Response shape:
{
"items": [
{
"blockNumber": 8279910,
"timestampIso": "2026-04-10T15:43:12Z",
"txIndex": 30,
"txHash": "0x0abc...",
"kinds": ["token_in", "contract_call"],
"counterparty": "0x0456...",
"txType": "INVOKE",
"executionStatus": "SUCCEEDED",
"finalityStatus": "ACCEPTED_ON_L1",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"primaryMethod": "transfer",
"callCount": 2,
"methodsDiffer": false,
"transferCount": 1,
"topTransferTokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"topTransferAmount": "1000000000000000000",
"topTransferStandard": "erc20"
}
],
"nextCursor": "opaque-cursor-1"
}Agent rules:
- Use
transactionswhen the unit of work is a transaction. - Use
activitywhen the unit of work is a transfer/event-like row. - Pass
nextCursorback unchanged ascursor. - Hydrate
GET /tx/{tx_hash}when you need fulltokenTransfers,calldata, receipt data, messages, or bridge intent for one row.
GET /address/{address}/transfers
Use this route when an agent needs token movement rows that touched one address. It is backed by indexed transfer facts and supports directional filtering without requiring clients to parse transaction calldata.
Request:
curl \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/address/<owner>/transfers?direction=any&limit=25"Response shape:
{
"items": [
{
"blockNumber": 8279910,
"timestampIso": "2026-03-27T10:00:00Z",
"txIndex": 12,
"txHash": "0x0abc...",
"logIndex": 4,
"transferIndex": 0,
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"fromAddress": "0x0123...",
"toAddress": "0x0456...",
"amount": "1000000000000000000",
"rawValue": "1000000000000000000",
"tokenId": null,
"standard": "erc20",
"sourceTier": "finalized",
"actionContext": null
}
],
"nextCursor": "8279910:12:4:0"
}Agent rules:
- Use
direction=anyfor a complete address view,direction=infor received transfers, anddirection=outfor sent transfers. - Treat
amountas a base-10 raw string. Apply token decimals after resolving metadata fortokenAddress. - Page with
nextCursor; do not infer completeness from one page.
When to use which route
| Need | Route |
|---|---|
| typed identifier or token lookup | GET /search |
| execution tree or internal call debugging | GET /tx/{tx_hash}/trace |
| calendar-close block for one exact balance | GET /block-at-timestamp |
| point-in-time balance for one known token contract | GET /token/{token}/balance-of/{address} |
| one selector against one contract | GET /contract/{address}/read |
| ordered lightweight hydration for many tx hashes | POST /tx/previews |
| recent wallet transactions, one row per tx | GET /address/{address}/transactions |
| token movement rows for one wallet, with in/out filters | GET /address/{address}/transfers |
| wallet screening and current portfolio state | GET /address/{address}/token-holdings |
If the question is “what can this deployment do?”, use the host’s published OpenAPI or docs surface first rather than probing unpublished discovery endpoints.