Starkscan

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

RouteFreshest?Exact?Paginated?Expensive?Best for wallet state?Best for tx debugging?
GET /block/{block_ref}block snapshot at the referenced heightyesnostandardnoyes
GET /block-at-timestampindexed block at or around the timestampyesnolightyes, as a balance-of helperno
GET /block/{number}/txsblock snapshot at the referenced heightyescursor-basedstandardnoyes
GET /searchnon/anoheavynosometimes
GET /tx/{tx_hash}stable historical transaction detailyesnostandardnoyes
GET /tx/{tx_hash}/tracestable historical tracen/anoheavynoyes
GET /contract/{address}/readlatest by defaultexact spot readnoheavysometimesyes
GET /token/{token}/balance-of/{address}exact at requested block tagyesnolightyes, for known token contractsno
POST /tx/previewshistorical preview snapshotcompact by defaultrequest-bounded batchheavynosometimes
GET /address/{address}/transactionsindexed transaction rowsone row per txcursor-basedheavynosometimes
GET /address/{address}/token-holdingsnear-latest indexed stateonly when exact=true, truncated=false, and completeness.reasonCode="complete"noheavyyesno

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_limit only controls the preview array on the block detail response.
  • Use the dedicated /txs route when you need the full paginated block transaction list.
  • Use blockHash, not rawObjectKey, 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 txIndex to lowest.
  • If you need the current head block, read GET /v1/{chain}/status first and then use the returned numeric block number here.
  • GET /block/{number}/txs itself always uses the resolved numeric block number, including follow-up pages with cursor.
  • nextCursor is exclusive. Pass it back as cursor unchanged.

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 metadata
  • GET /v1/{chain}/block/{number}/txs for the ordered block transaction list
  • GET /v1/{chain}/tx/{tx_hash} for execution and finality metadata on a specific transaction
  • GET /v1/{chain}/tx/{tx_hash}/trace when you need deeper execution context
  • Resolve blockNumber first when you start from a block hash or current head metadata, then use that numeric block number for /txs pagination.
  • If you need logs or token transfers for a transaction, hydrate GET /tx/{tx_hash} separately.

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:

  • q is required.
  • Results are split into the top-level blocks, transactions, and addresses arrays.
  • 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 trace as 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, and bridgeIntent.
  • Use calldata, receipt, and logs as audit evidence, not as the first place to infer user-facing token movement.
  • logsTruncated=true means returned logs are bounded; it does not mean missing events are false.
  • tokenTransfers is already normalized from receipt evidence. Keep amount as a decimal string and apply token decimals only after resolving metadata for tokenAddress.

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:

  • result is 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:

  • balanceRaw is a base-10 U256 string. Do not parse it as JavaScript number.
  • blockTag echoes 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-holdings only for wallet screening; use balance-of when 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=true means tokenTransfers is capped for that preview — fetch the full GET /tx/{tx_hash} for the complete set.
  • logsTruncated=true means logs is capped; pass includeLogCounts (or includeLogs) in the request so logCount is 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, and completeness.reasonCode="complete".
  • exact=false with truncated=false is valid. It means incomplete-but-not-capped, not “empty”.
  • Use normalizedTokenAddress, symbol, name, and decimals from the row when present. Do not infer STRK, ETH, USDC, or bridged assets from raw felts.
  • Compare balance-of against 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 transactions when the unit of work is a transaction.
  • Use activity when the unit of work is a transfer/event-like row.
  • Pass nextCursor back unchanged as cursor.
  • Hydrate GET /tx/{tx_hash} when you need full tokenTransfers, 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=any for a complete address view, direction=in for received transfers, and direction=out for sent transfers.
  • Treat amount as a base-10 raw string. Apply token decimals after resolving metadata for tokenAddress.
  • Page with nextCursor; do not infer completeness from one page.

When to use which route

NeedRoute
typed identifier or token lookupGET /search
execution tree or internal call debuggingGET /tx/{tx_hash}/trace
calendar-close block for one exact balanceGET /block-at-timestamp
point-in-time balance for one known token contractGET /token/{token}/balance-of/{address}
one selector against one contractGET /contract/{address}/read
ordered lightweight hydration for many tx hashesPOST /tx/previews
recent wallet transactions, one row per txGET /address/{address}/transactions
token movement rows for one wallet, with in/out filtersGET /address/{address}/transfers
wallet screening and current portfolio stateGET /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.

On this page