Starkscan

Migration skills

Download source-backed SKILL.md artifacts for Voyager migration and accounting point-in-time balances.

Migration skills

Use this page when a client wants an agent to migrate from Voyager-style calls to Starkscan without guessing routes.

The artifacts below are intentionally narrow. They read like executable migration contracts, not generic prompts. Each skill tells the agent which Starkscan routes are certified, beta, experimental, or unsupported, and points back to the published starkscan-openapi.yaml before any code generation.

Downloadable skills

SkillBest forArtifact
Accounting point-in-time balancesAccountants that need one token balance for one account at a calendar close./skills/accounting-point-in-time-balances/SKILL.md
Voyager migrationAdapters that need to replace a bounded Voyager workflow with Starkscan REST routes and keep unsupported/RPC gaps explicit./skills/voyager-migration/SKILL.md

Install the artifact by giving the SKILL.md file to Claude, Codex, Cursor, or any agent runtime that supports portable task instructions. If the runtime does not support skills directly, paste only the relevant sections into the migration task and keep the OpenAPI link attached.

Accounting workflow

The current accounting close workflow is already possible with two Starkscan calls:

  1. Resolve the calendar timestamp to an indexed Starknet block.
  2. Query the certified token balance route at that exact block.
export STARKSCAN_BASE_URL="https://starkscan.co/api"
export STARKSCAN_CHAIN="SN_MAIN"
export STARKSCAN_API_KEY="<api_key>"
export STARKSCAN_TIMESTAMP="2025-12-31T23:59:59Z"
export STARKSCAN_TIMESTAMP_QUERY="2025-12-31T23%3A59%3A59Z"
export STARKSCAN_TOKEN="<token_contract_address>"
export STARKSCAN_ACCOUNT="<account_address>"

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=$STARKSCAN_TIMESTAMP_QUERY&closest=before"

Use the returned block.blockNumber as the block_tag:

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/token/$STARKSCAN_TOKEN/balance-of/$STARKSCAN_ACCOUNT?block_tag=<block.blockNumber>"

For 2025-12-31T23:59:59Z, Starkscan's correctness gate verified block 5007537 against RPC. The helper response also includes previousBlock, nextBlock, and source=indexed_blocks so an accountant can keep the bracket evidence with the report.

Voyager migration matrix

Use this matrix before generating migration code. The state must stay attached to every replaced call so clients know whether they are using a certified REST route, a beta REST route, an experimental RPC provider surface, or no Starkscan replacement yet.

Voyager-style needStarkscan replacementStateMigration note
Health / host reachabilityGET /v1/{chain}/statuscertifiedUse this as the first smoke for every integration.
Exact token balanceGET /v1/{chain}/token/{token}/balance-of/{address}?block_tag={block}certifiedUse exact token and account addresses; pass a concrete block for accounting.
Timestamp to blockGET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=beforecertifiedUse as the helper before exact historical balance checks for one known token/account.
One transactionGET /v1/{chain}/tx/{tx_hash}certifiedUse for transaction detail and support links.
Contract metadataGET /v1/{chain}/contract/{address}betaIndexed-only class/deployment/token metadata. Nullable token fields mean not identified in indexed token metadata.
Wallet transactionsGET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor}betaCursor-based; preserve nextCursor exactly.
Address token transfersGET /v1/{chain}/address/{address}/transfers?direction=any&limit={n}&cursor={nextCursor}betaWallet-first transfer rows across all indexed tokens. Use direction=any, in, or out; any dedupes self-transfers while in and out keep the explicit directional view. Direction, token, block, cursor, and limit filters are applied before pagination.
Token transfer rowsGET /v1/{chain}/token/{token}/transfers?address={address}&limit={n}&cursor={nextCursor}betaUse when the token contract is known. Do not enumerate token contracts client-side for wallet history.
Storage reads, class reads, nonce, calls, fee, simulationStarkscan JSON-RPC provider pilotexperimentalUse the gated JSON-RPC provider path for enrolled wallet/app pilots. REST getStorageAt is not shipped; use JSON-RPC starknet_getStorageAt.
Writes, WebSocket subscriptions, broad Voyager parityNo current-pilot replacementunsupportedKeep the existing provider path until Starkscan RPC formally launches that surface.

Route status

TaskRouteState
Health checkGET /v1/{chain}/statuscertified
Timestamp to blockGET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=beforecertified
Exact token balanceGET /v1/{chain}/token/{token}/balance-of/{address}?block_tag={block}certified
One transactionGET /v1/{chain}/tx/{tx_hash}certified
Contract metadataGET /v1/{chain}/contract/{address}beta
Wallet transactionsGET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor}beta
Address token transfersGET /v1/{chain}/address/{address}/transfers?direction=any&limit={n}&cursor={nextCursor}beta
Token transfer rowsGET /v1/{chain}/token/{token}/transfers?address={address}&limit={n}&cursor={nextCursor}beta
Storage reads / class reads / nonce / calls / fee / simulationStarkscan JSON-RPC provider pilotexperimental

Current gaps must stay visible in migration plans. A standalone REST storage route, write/WSS provider traffic, strict signed simulation certification, and broad Voyager parity are not certified launch surfaces. If an agent asks for a route that is not listed here or in the OpenAPI artifact, it should answer unsupported instead of inventing an endpoint.

Contract Metadata Example

Use this when a Voyager workflow needs indexed deployment/class/token identity for a known address. This route is beta and indexed-only; it does not probe ABI or RPC on the request path.

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/contract/0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
{
  "chainId": "SN_MAIN",
  "address": "0x40337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a",
  "classHash": "0x30b8...",
  "deployedAtBlock": 9795720,
  "deployedAtTx": "0x...",
  "createdOnIso": "2026-05-18T00:00:00.000Z",
  "deployedByAddress": "0x...",
  "isAccount": false,
  "isToken": null,
  "tokenKind": null,
  "alias": null,
  "metadataCompleteness": true,
  "source": "indexed_read_model"
}

Token fields are either identified together (isToken: true, non-null tokenKind) or absent together (isToken: null, tokenKind: null, alias: null).

Agent rules

  • Use X-Starkscan-Api-Key; do not paste the full key into chats, screenshots, tickets, or generated reports.
  • Use closest=before for "as of this instant" accounting semantics.
  • Use exact token contract addresses. Do not rely on symbols such as USDC when correctness matters.
  • Use a concrete block number or block hash for replayable balance checks. Do not use latest for historical accounting close.
  • Treat the certified accounting workflow as one known token contract, one account, and one timestamp. Do not infer a historical portfolio from it.
  • Preserve returned cursors exactly. Do not construct pagination cursors client-side.
  • Log X-Request-Id, X-Starkscan-Route-Class, rate-limit headers, HTTP status, and latency for support.
  • Read /starkscan-openapi.yaml before generating SDK code or adding a route to a migration matrix.

Smoke before handoff

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/status"

BLOCK_RESPONSE="$(curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=2025-12-31T23%3A59%3A59Z&closest=before")"

printf '%s\n' "$BLOCK_RESPONSE"
BLOCK_NUMBER="$(printf '%s' "$BLOCK_RESPONSE" | python3 -c 'import json, sys; print(json.load(sys.stdin)["block"]["blockNumber"])')"

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/token/$STARKSCAN_TOKEN/balance-of/$STARKSCAN_ACCOUNT?block_tag=$BLOCK_NUMBER"

TypeScript and CLI smoke

Use the TypeScript SDK for the certified balance route after the timestamp helper resolves the block:

import { createStarkscanClient } from "@starkscan/sdk";

const baseUrl = process.env.STARKSCAN_BASE_URL ?? "https://starkscan.co/api";
const chainId = process.env.STARKSCAN_CHAIN ?? "SN_MAIN";
const apiKey = process.env.STARKSCAN_API_KEY;
const token = process.env.STARKSCAN_TOKEN;
const account = process.env.STARKSCAN_ACCOUNT;
const timestamp = "2025-12-31T23:59:59Z";

if (!apiKey || !token || !account) {
  throw new Error("STARKSCAN_API_KEY, STARKSCAN_TOKEN, and STARKSCAN_ACCOUNT are required");
}

const blockResponse = await fetch(
  `${baseUrl}/v1/${chainId}/block-at-timestamp?timestamp=${encodeURIComponent(timestamp)}&closest=before`,
  { headers: { "X-Starkscan-Api-Key": apiKey } },
);
const { block } = (await blockResponse.json()) as { block: { blockNumber: number } };

const starkscan = createStarkscanClient({ apiKey, baseUrl, chainId });
const balance = await starkscan.tokenBalanceOf(token, account, String(block.blockNumber));

console.log({ blockNumber: block.blockNumber, balance });

Use the CLI for a package-level smoke after the block number is known:

npx -y @starkscan/cli@alpha \
  --base-url "$STARKSCAN_BASE_URL" \
  --chain "$STARKSCAN_CHAIN" \
  --api-key "$STARKSCAN_API_KEY" \
  doctor

npx -y @starkscan/cli@alpha \
  --base-url "$STARKSCAN_BASE_URL" \
  --chain "$STARKSCAN_CHAIN" \
  --api-key "$STARKSCAN_API_KEY" \
  --output-format json \
  token-balance-of "$STARKSCAN_ACCOUNT" "$STARKSCAN_TOKEN" \
  --block-tag "$BLOCK_NUMBER"

Builder policy

The safe builder behavior is constrained:

  1. Read the requested Voyager call or accounting task.
  2. Match it against this page, the downloadable skills, and OpenAPI.
  3. Emit a SKILL.md, curl commands, TypeScript SDK notes, Python smoke, and a route-state table only for matched routes.
  4. Mark everything else unsupported, beta, or experimental with the reason.

This prevents a migration agent from converting "missing docs" into fake Starkscan routes.

On this page