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.
| Surface | Public label | Agent guidance |
|---|---|---|
| REST core API | certified | Start 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 SDK | stable | Use @starkscan/sdk by default or exact @starkscan/[email protected] for unattended typed integrations. |
| Agent CLI | stable | Use @starkscan/cli by default or exact @starkscan/[email protected] for shell workflows, JSON output, and local exports. |
| Hosted MCP | hosted beta / stable launcher | Use 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 RPC | authenticated HTTP beta | Hosted 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-Keyheaders - whether you need
nodeUrlcompatibility 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:
| Class | Methods |
|---|---|
rpc_read_light | starknet_chainId, starknet_specVersion, starknet_blockNumber, starknet_blockHashAndNumber, starknet_syncing |
rpc_read_state | starknet_call, starknet_getStorageAt, starknet_getClass, starknet_getClassHashAt, starknet_getClassAt, starknet_getNonce |
rpc_read_history | starknet_getBlockWithTxHashes, starknet_getBlockWithTxs, starknet_getBlockWithReceipts, starknet_getBlockTransactionCount, starknet_getTransactionByBlockIdAndIndex, starknet_getTransactionByHash, starknet_getTransactionReceipt, starknet_getTransactionStatus, starknet_getStateUpdate, starknet_getEvents |
rpc_simulation | starknet_simulateTransactions, starknet_estimateFee, starknet_estimateMessageFee |
rpc_write | Signed-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_blockHashAndNumberis the correct method name. Do not callstarknet_getBlockHashAndNumber.starknet_getEventsmust use bounded numericfrom_blockandto_block,chunk_size <= 1000, and a block span of at most 10,000. Starkscan accepts both the named filter shapeparams: {"filter":{"from_block":{"block_number":N},"to_block":{"block_number":N},"chunk_size":100}}and the direct filter shapeparams: {"from_block":{"block_number":N},"to_block":{"block_number":N},"chunk_size":100}. Prefer the namedfilterwrapper in generated clients; do not mix a nestedfilterobject with top-level filter keys.starknet_calltoken probes must use Starknet entry-point selectors, not EVM-style method IDs or truncated fixtures. For ERC20decimals, use selector0x004c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9. For balance reads, prefer the certified RESTtoken/{token}/balance-of/{address}route unless you have verified the exact Starknetbalance_oforbalanceOfselector 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 asrpc_write,rpc_trace, orrpc_ws; they must not return success. - JSON-RPC
id,result, and upstreamerrorenvelopes are preserved. Starkscan metadata stays in headers orerror.data. - For RPC issue reports, log HTTP status, full JSON-RPC
resultorerror,X-Request-Id,X-Starkscan-Rpc-Class, andX-Ratelimit-*headers. REST routes useX-Starkscan-Route-Class; RPC routes useX-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 need | Starkscan route | Notes |
|---|---|---|
| exact token balance | GET /v1/{chain}/token/{token}/balance-of/{address}?block_tag=latest | Certified for exact-token reads. Use a concrete block number or hash instead of latest when replayable correctness matters. |
| accounting timestamp to block | GET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=before | Certified helper for calendar-close workflows. Use the returned block.blockNumber as the balance-of block_tag. |
| transaction detail | GET /v1/{chain}/tx/{tx_hash} | Includes tokenTransfers; use this before adding a separate transfer lookup. |
| transactions to/from a wallet | GET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor} | Cursor-based, not page-number based. Pass nextCursor back unchanged. |
| transfer-granular wallet rows | GET /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 metadata | GET /v1/{chain}/contract/{address} | Indexed-only class/deployment/token metadata. Nullable token fields mean not identified in indexed token metadata. |
| canonical transaction UI link | https://starkscan.co/tx/{tx_hash} | Same hash as the API route. |
| canonical contract/account UI link | https://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:
| Job | Route |
|---|---|
| health / host reachability | GET /v1/{chain}/status |
| latest blocks | GET /v1/{chain}/blocks |
| one block | GET /v1/{chain}/block/{block_ref} |
| block transaction list | GET /v1/{chain}/block/{number}/txs |
| tx list scan | GET /v1/{chain}/txs |
| one tx | GET /v1/{chain}/tx/{tx_hash} |
| one tx trace | GET /v1/{chain}/tx/{tx_hash}/trace |
| compact tx batch | POST /v1/{chain}/tx/previews (advanced utility — needs a utility or batch-scope key) |
| wallet activity | GET /v1/{chain}/address/{address}/activity |
| wallet transactions | GET /v1/{chain}/address/{address}/transactions |
| wallet transfer rows | GET /v1/{chain}/address/{address}/transfers |
| wallet holdings | GET /v1/{chain}/address/{address}/token-holdings |
| exact token balance | GET /v1/{chain}/token/{token}/balance-of/{address} |
| token transfer history | GET /v1/{chain}/token/{token}/transfers |
| indexed contract metadata | GET /v1/{chain}/contract/{address} |
| contract read | GET /v1/{chain}/contract/{address}/read |
| contract selectors | GET /v1/{chain}/contract/{address}/entrypoints |
| identifier lookup | GET /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_refaccepts a block number or block hash.- Token and contract read
block_tagacceptslatest,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}/statusfirst 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, resolveblockNumberfirst. - Pass returned
nextCursorvalues 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-holdingsas complete only whenexact=true,truncated=false, andcompleteness.reasonCode="complete". - Read
normalizedTokenAddress,symbol,name, anddecimalsfrom holdings rows when present; do not infer token identity from raw felts. - Use
GET /v1/{chain}/address/{address}/transactionswhen the agent wants one row per tx. - Use
GET /v1/{chain}/address/{address}/transferswhen a migration adapter needs transfer-granular wallet rows from the public transfer index; do not treat UIactivitycopy as a public API route. GET /v1/{chain}/contract/{address}/readrequires a raw Starknetselector, not a function name.GET /v1/{chain}/contract/{address}/entrypointsis broader thanread; forread, prefer selectors withstateMutability=viewand pass required calldata.POST /v1/{chain}/tx/previewsexpects{"hashes":[...]}.tx/previewsis compact by default. Ask forincludeLogCounts=trueorincludeLogs=truebefore you infer thatlogCount=0orlogs=[]means “no logs”.
If the agent still needs concrete route shapes, use Route examples before guessing response semantics.
Error contract
| Status | Meaning | Client action |
|---|---|---|
401 | key missing or invalid | stop and fix auth |
403 | valid key, wrong scope or route tier | stop and fix key tier |
429 | rate limit hit for the current route class | honor Retry-After and back off |
503 | temporary unavailability | retry 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
POSTroutes - auth mode used (
X-Starkscan-Api-Key) - response status
- response body snippet
X-Request-IdX-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: