Starkscan

Agent HTTP quickstart

Give an agent a bounded Starkscan HTTP contract without making it guess base paths, auth, or route scope.

Agent HTTP quickstart

Use this page when you are giving an agent direct Starkscan HTTP access instead of MCP or the CLI.

This page is intentionally narrower than the full API guide. It covers a bounded route set, one canonical base-path shape, and the minimum issue-report contract. Agents and SDK generators should read the host-local OpenAPI file at /starkscan-openapi.yaml before guessing query params or enums.

Canonical setup

Use one base-path pattern only:

export STARKSCAN_API_KEY="YOUR_STARKSCAN_API_KEY"
export STARKSCAN_CHAIN="SN_MAIN"
# Optional: only set this for preview or self-hosted hosts.
# export STARKSCAN_BASE_URL="https://preview.example.com/api"

Hosted requests then always look like:

${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/...

Do not paste full API keys into agent chats, tickets, screenshots, PR comments, or shared prompts. Store the key in an environment variable or secrets manager. Rotate immediately if the full value appears in chat or logs.

Same key, explicit surface labels

Use one Starkscan API key across RPC, REST, SDK, CLI, and hosted MCP. Keep the label attached to the surface so agents do not confuse package release state, route certification, and RPC provider scope.

SurfacePublic labelAgent guidance
REST core APIcertifiedStart here for direct HTTP. The certified launch set is status, block detail, timestamp-to-block, transaction detail, token total supply, and token balance-of.
TypeScript SDKstableUse @starkscan/sdk by default or exact @starkscan/[email protected] for unattended typed integrations.
Agent CLIstableUse @starkscan/cli by default or exact @starkscan/[email protected] for shell workflows, JSON output, and local exports.
Hosted MCPhosted beta / stable launcherUse https://api.starkscan.co/mcp on the API domain or {appBaseUrl}/api/mcp on an app-origin deployment; if STARKSCAN_BASE_URL already ends with /api, do not append another /api. Use @starkscan/mcp by default or exact @starkscan/[email protected] in unattended agent configs; 18 tools are listed: bootstrap, 16 read-only route tools, and one unsigned write-payload builder.
Starkscan RPCauthenticated HTTP betaHosted production is open to Starkscan API-key holders for reads, calls, events, fee, and simulation-envelope workflows; preview/self-hosted deployments may require batch or utility scope unless configured open. Signed transaction submission requires a write-scoped key. Keep existing providers for WebSockets, broad tracing, archive/history, and full-provider replacement.

One-command conformance smoke

Before handing a key to an agent (or after a deploy), sanity-check the host, auth, and reachability with the published CLI and a status call:

npx -y @starkscan/[email protected] doctor
# or a raw check:
curl -i -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/status"

doctor checks the base URL, auth mode, API reachability, and hosted MCP. A 200 with chain status confirms the key and host are wired; send a deliberately bad key to confirm a 401 (see Your first error for the full error/header contract).

JSON-RPC provider beta

For the product-level node URL, server endpoint, and partner migration checklist, start with Starkscan RPC. This section keeps the same contract in a bounded agent-friendly shape.

Use this surface with a Starkscan API key when a client needs Starknet JSON-RPC method names instead of the REST, SDK, CLI, or hosted MCP surfaces. Hosted production authenticated RPC beta access covers read, batch, call, event, fee, and simulation-envelope workflows for Starkscan API-key holders; preview and self-hosted deployments may require batch or utility scope unless configured open. Signed transaction submission requires a write-scoped key.

For higher-capacity access or write-scoped signed-payload submission, use your Starkscan partner or support channel and include:

  • app or workspace name
  • mainnet use case
  • expected requests per second, batch size, and concurrency
  • whether your client can send X-Starkscan-Api-Key headers
  • whether you need nodeUrl compatibility for SDKs/tools that cannot attach headers
  • whether you need write forwarding for already-signed transactions

Starkscan JSON-RPC has current wallet_app_phase1 evidence for read, call, event, fee, and simulation-envelope workflows through the dedicated mainnet gateway path. The signed-write lane also has mainnet boundary certification for already-signed starknet_addInvokeTransaction, starknet_addDeclareTransaction, and starknet_addDeployAccountTransaction requests through the rpc_write lane. Keep existing Alchemy, Infura, Juno, Pathfinder, or other provider paths for WebSockets, broad tracing, archive/history, unrestricted public writes, and full-provider replacement until those lanes have their own certification.

Agents can read the current machine-readable RPC beta contract from GET https://api.starkscan.co/v1/meta/capabilities under rpcProvider, including the spec-version floor, supported block tags, quota classes, write-beta methods, and excluded surfaces. Check rpcProvider.writeBeta.enabled and rpcProvider.writeBeta.status before attempting write methods.

export STARKSCAN_RPC_API_URL="https://api.starkscan.co/v1/SN_MAIN/rpc"
export STARKSCAN_API_KEY="YOUR_STARKSCAN_API_KEY"

Header-auth request:

curl "$STARKSCAN_RPC_API_URL" \
  -H "Content-Type: application/json" \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  --data '{"jsonrpc":"2.0","id":1,"method":"starknet_blockNumber","params":[]}'

starknet.js clients that can attach headers should use the same URL and X-Starkscan-Api-Key. If a client only accepts a bare nodeUrl, use the compatibility URL-token path:

export STARKSCAN_API_KEY="YOUR_STARKSCAN_API_KEY"
export STARKSCAN_RPC_NODE_URL="https://starkscan.co/rpc/v0_10/SN_MAIN/$STARKSCAN_API_KEY"

For preview or self-hosted deployments, replace starkscan.co with that deployment's app host so the URL-token secret is not sent to the wrong origin.

Then pass the URL directly:

import { RpcProvider } from "starknet";

const provider = new RpcProvider({
  nodeUrl: process.env.STARKSCAN_RPC_NODE_URL,
});

Treat this full URL as a secret. Prefer header auth for servers, never paste the URL-token form into chats, tickets, screenshots, PR comments, or source code, and rotate the key if the full URL appears in logs. Use a dedicated Starkscan key per app or environment for this URL. It carries the same RPC scopes as the header-auth key: read and batch for normal authenticated RPC beta traffic, plus write only when the key is explicitly write-scoped for signed-payload submission. Do not reuse an admin or shared key in a URL.

Phase-one methods are read and simulation oriented:

ClassMethods
rpc_read_lightstarknet_chainId, starknet_specVersion, starknet_blockNumber, starknet_blockHashAndNumber, starknet_syncing
rpc_read_statestarknet_call, starknet_getStorageAt, starknet_getClass, starknet_getClassHashAt, starknet_getClassAt, starknet_getNonce
rpc_read_historystarknet_getBlockWithTxHashes, starknet_getBlockWithTxs, starknet_getBlockWithReceipts, starknet_getBlockTransactionCount, starknet_getTransactionByBlockIdAndIndex, starknet_getTransactionByHash, starknet_getTransactionReceipt, starknet_getTransactionStatus, starknet_getStateUpdate, starknet_getEvents
rpc_simulationstarknet_simulateTransactions, starknet_estimateFee, starknet_estimateMessageFee
rpc_writeSigned-payload submission for write-scoped keys: starknet_addInvokeTransaction, starknet_addDeclareTransaction, starknet_addDeployAccountTransaction

Limits that agents should treat as contract:

  • Batch JSON-RPC is supported, capped at 25 items.
  • starknet_blockHashAndNumber is the correct method name. Do not call starknet_getBlockHashAndNumber.
  • starknet_getEvents must use bounded numeric from_block and to_block, chunk_size <= 1000, and a block span of at most 10,000. Starkscan accepts both the named filter shape params: {"filter":{"from_block":{"block_number":N},"to_block":{"block_number":N},"chunk_size":100}} and the direct filter shape params: {"from_block":{"block_number":N},"to_block":{"block_number":N},"chunk_size":100}. Prefer the named filter wrapper in generated clients; do not mix a nested filter object with top-level filter keys.
  • starknet_call token probes must use Starknet entry-point selectors, not EVM-style method IDs or truncated fixtures. For ERC20 decimals, use selector 0x004c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9. For balance reads, prefer the certified REST token/{token}/balance-of/{address} route unless you have verified the exact Starknet balance_of or balanceOf selector for that token.
  • Write forwarding requires an explicit write-scoped key, accepts only already-signed payloads, does not custody or generate private keys, and must not be blindly retried by clients. Keys without write scope, malformed or unsigned write probes, tracing, and WebSocket subscriptions return JSON-RPC errors with explicit quota classes such as rpc_write, rpc_trace, or rpc_ws; they must not return success.
  • JSON-RPC id, result, and upstream error envelopes are preserved. Starkscan metadata stays in headers or error.data.
  • For RPC issue reports, log HTTP status, full JSON-RPC result or error, X-Request-Id, X-Starkscan-Rpc-Class, and X-Ratelimit-* headers. REST routes use X-Starkscan-Route-Class; RPC routes use X-Starkscan-Rpc-Class.

Smoke-test the RPC path with the public JSON-RPC calls shown above: confirm an unauthenticated request is rejected, authenticated starknet_chainId, starknet_specVersion, starknet_blockNumber, and starknet_blockHashAndNumber return results, a known-good starknet_call returns a value, bounded starknet_getEvents returns an event page, malformed write probes return errors or rpc_write rate limits without success, and batch requests stay within the 25-item cap.

Provider-migration readiness is validated before Starkscan JSON-RPC is offered as a migration target. Issue #1781 records current wallet_app_phase1 evidence for the dedicated mainnet gateway path: provider identity, token starknet_call reads, wallet state reads, transaction/receipt/status/events reads, simulation/fee envelope forwarding, the starknet_specVersion floor (at least 0.10.2), and request-id, rpc-class, and rate-limit headers. Issues #1923 and #2301 track the signed-write lane and its mainnet canary evidence.

Wallet/app migration stability

For partner wallet/app migrations that loop exact-token balance-of calls, the launch bar for a bounded wallet fixture is zero unexplained 5xx responses, zero unexpected non-2xx responses, and no missing X-Request-Id or X-Starkscan-Route-Class headers. These bounded workloads are validated before a host is declared migration-ready.

The full Voyager replacement set for a wallet/app migration is three routes: exact-token balance-of, tx/{hash} with inline tokenTransfers, and address/{address}/transactions cursor rows. A migration is ready only when all three return correct shapes with request-id, route-class, and rate-limit headers and no unexplained 5xx or unexpected non-2xx responses.

Wallet/app Voyager migration map

Use this table for a wallet/app Voyager migration. It is intentionally narrow and does not imply full Voyager parity across every Starkscan route.

Voyager needStarkscan routeNotes
exact token balanceGET /v1/{chain}/token/{token}/balance-of/{address}?block_tag=latestCertified for exact-token reads. Use a concrete block number or hash instead of latest when replayable correctness matters.
accounting timestamp to blockGET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=beforeCertified helper for calendar-close workflows. Use the returned block.blockNumber as the balance-of block_tag.
transaction detailGET /v1/{chain}/tx/{tx_hash}Includes tokenTransfers; use this before adding a separate transfer lookup.
transactions to/from a walletGET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor}Cursor-based, not page-number based. Pass nextCursor back unchanged.
transfer-granular wallet rowsGET /v1/{chain}/address/{address}/transfers?direction=any&limit={n}&cursor={nextCursor}Use direction=any, in, or out relative to the wallet. any returns sender or recipient rows and dedupes self-transfers; in and out keep the explicit directional view.
indexed contract metadataGET /v1/{chain}/contract/{address}Indexed-only class/deployment/token metadata. Nullable token fields mean not identified in indexed token metadata.
canonical transaction UI linkhttps://starkscan.co/tx/{tx_hash}Same hash as the API route.
canonical contract/account UI linkhttps://starkscan.co/contract/{address}Use for wallets and contracts shown in support/debug output.

Current gaps must stay explicit in client plans: getStorageAt is not part of the certified REST launch set, and Starkscan JSON-RPC is still an authenticated HTTP beta rather than a full-provider replacement. Route tier/package naming remains beta even though the public SDK/CLI/MCP packages are published under the Starkscan scope. Use documented REST routes for the certified REST set; keep existing JSON-RPC providers for WebSockets, broad tracing, archive/history, unscoped writes, and full-provider replacement until those lanes have their own certification.

Smallest safe route set

Start with the smallest route set that answers the task:

JobRoute
health / host reachabilityGET /v1/{chain}/status
latest blocksGET /v1/{chain}/blocks
one blockGET /v1/{chain}/block/{block_ref}
block transaction listGET /v1/{chain}/block/{number}/txs
tx list scanGET /v1/{chain}/txs
one txGET /v1/{chain}/tx/{tx_hash}
one tx traceGET /v1/{chain}/tx/{tx_hash}/trace
compact tx batchPOST /v1/{chain}/tx/previews (advanced utility — needs a utility or batch-scope key)
wallet activityGET /v1/{chain}/address/{address}/activity
wallet transactionsGET /v1/{chain}/address/{address}/transactions
wallet transfer rowsGET /v1/{chain}/address/{address}/transfers
wallet holdingsGET /v1/{chain}/address/{address}/token-holdings
exact token balanceGET /v1/{chain}/token/{token}/balance-of/{address}
token transfer historyGET /v1/{chain}/token/{token}/transfers
indexed contract metadataGET /v1/{chain}/contract/{address}
contract readGET /v1/{chain}/contract/{address}/read
contract selectorsGET /v1/{chain}/contract/{address}/entrypoints
identifier lookupGET /v1/{chain}/search

Stay on this set unless you already know you need a published advanced utility.

First working checks

1. Verify the host and key

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/status"

2. Verify one tx detail and one tx trace

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/tx/<tx_hash>"

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/tx/<tx_hash>/trace"

3. Verify one block path

Use block/{block_ref} when the agent starts from a block number or block hash:

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/block/<block_number_or_hash>?tx_limit=3"

Use child routes when the task needs canonical block contents. If you start from a block hash, resolve blockNumber first with GET /v1/{chain}/block/{block_ref}. The block response also includes nullable header metadata such as stateRoot, sequencerAddress, gas prices, L1 data availability mode, and Starknet version when indexed from the canonical block payload. If you need the current head block, read GET /v1/{chain}/status first and then call the block route with the returned number or hash:

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/block/<block_number>/txs?limit=25"

If you need per-transaction execution or receipt context for a block, walk the txs page and then read GET /v1/{chain}/tx/{tx_hash} or GET /v1/{chain}/tx/{tx_hash}/trace per transaction.

4. Verify one wallet-state path

Use token-holdings for wallet screening:

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/address/<owner>/token-holdings"

Use balance-of only when you already know the exact token contract:

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=latest"

For reproducible balance checks, pass a concrete block number or hash instead of latest.

For accounting close, resolve the timestamp first, then pass the returned block number into balance-of:

curl \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=2025-12-31T23:59:59Z&closest=before"

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=<blockNumber>"

Use closest=before for "as of this instant" semantics. The response includes the selected block plus inclusive previous/next indexed bounds so accountants can verify that the selected block brackets the requested timestamp.

Contract caveats agents must obey

  • block_ref accepts a block number or block hash.
  • Token and contract read block_tag accepts latest, pending, a block number, or a block hash. Use an exact block for correctness comparisons.
  • Timestamp-to-block resolution accepts Unix seconds or RFC3339 timestamps with timezone. Do not send timezone-less calendar strings.
  • If you need the current head block, read GET /v1/{chain}/status first and then reuse the returned block number or hash.
  • For block/{number}/txs, use a numeric block number. If you started from a block hash, resolve blockNumber first.
  • Pass returned nextCursor values back unchanged. Do not build block cursors yourself.
  • GET /v1/{chain}/search?q=... is identifier-first search. It is not ticker or symbol search.
  • Treat token-holdings as complete only when exact=true, truncated=false, and completeness.reasonCode="complete".
  • Read normalizedTokenAddress, symbol, name, and decimals from holdings rows when present; do not infer token identity from raw felts.
  • Use GET /v1/{chain}/address/{address}/transactions when the agent wants one row per tx.
  • Use GET /v1/{chain}/address/{address}/transfers when a migration adapter needs transfer-granular wallet rows from the public transfer index; do not treat UI activity copy as a public API route.
  • GET /v1/{chain}/contract/{address}/read requires a raw Starknet selector, not a function name.
  • GET /v1/{chain}/contract/{address}/entrypoints is broader than read; for read, prefer selectors with stateMutability=view and pass required calldata.
  • POST /v1/{chain}/tx/previews expects {"hashes":[...]}.
  • tx/previews is compact by default. Ask for includeLogCounts=true or includeLogs=true before you infer that logCount=0 or logs=[] means “no logs”.

If the agent still needs concrete route shapes, use Route examples before guessing response semantics.

Error contract

StatusMeaningClient action
401key missing or invalidstop and fix auth
403valid key, wrong scope or route tierstop and fix key tier
429rate limit hit for the current route classhonor Retry-After and back off
503temporary unavailabilityretry with backoff and honor Retry-After when present

Error responses use a JSON envelope:

{
  "code": "rate_limited",
  "message": "Rate limit exceeded; retry shortly",
  "docSlug": "api/rate-limits",
  "requestId": "mzk-..."
}

For route-class budgets and headers, see Rate limits. Agents should log X-Starkscan-Route-Class, Retry-After, and X-Request-Id when present.

Bug report template

When an agent reports a Starkscan issue, include:

  • exact base URL and chain
  • exact route and query string
  • request body for POST routes
  • auth mode used (X-Starkscan-Api-Key)
  • response status
  • response body snippet
  • X-Request-Id
  • X-Starkscan-Route-Class
  • relevant rate-limit headers if present
  • expected result
  • actual result

Copy-paste template:

Host:
Chain:
Route:
Query params:
Request body:
Auth mode:
Status:
X-Request-Id:
X-Starkscan-Route-Class:
Rate-limit headers:
Response snippet:
Expected:
Actual:

Use another surface when

  • use MCP when the client already speaks tool-calling
  • use the CLI when the workflow is terminal-first
  • use the full API guide when you need the broader public contract

On this page