Starkscan

API discovery

Configure a Starkscan client from the REST capabilities contract, OpenRPC discovery, and the API catalog.

API discovery

Start integrations with discovery instead of copying a route list from prose. Starkscan publishes three complementary machine-readable contracts:

ContractUse it for
GET /v1/meta/capabilitiesRuntime-derived REST operations, limits, operating rules, and the authenticated caller's scopes and rate-limit window.
JSON-RPC rpc.discoverThe OpenRPC methods the authenticated RPC caller may invoke.
GET /.well-known/api-catalogRFC 9727 links to the API descriptions, schema, documentation, and status.

The REST capabilities document is caller-specific and always uses Cache-Control: no-store. It never includes an API-key value or identifier. Use caller.scopes and caller.rateLimit for the current REST key, use rpc.discover for the caller-filtered RPC method set, and treat a 403 or 429 plus its response headers as authoritative for that request.

Read the capabilities contract

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

Validate the response against starkscan-meta-capabilities.schema.json. The contract is additive: reject an unknown schemaVersion only when your client cannot safely ignore new fields.

The important blocks are:

  • firstCalls: a bounded bootstrap sequence.
  • documentation: the public OpenAPI URL and JSON-Pointer lookup rule.
  • routeFamilies[].operations[]: runtime-filtered method, external path, OpenAPI path, response rateLimitClass, summary, and openapiOperationRef.
  • rateLimit: the X-Starkscan-Route-Class, X-RateLimit-*, and Retry-After contract. A batch route is a workload class, not a discount.
  • sessionControl: /v1/me/* is a Better Auth session boundary. API keys are deliberately unsupported there.
  • apiKeyLifecycle: revoked or expired keys receive the same generic 401 unauthorized body and WWW-Authenticate: Bearer realm="starkscan", error="invalid_token"; throttling remains 429 with Retry-After.
  • caller: the current auth type, sanitized key class, scopes, and rate-limit window without key identity.
  • rpcProvider, walletInteraction, and operatingRules: provider shape, write gates, cursor/order rules, list-row omissions, and search behavior.
  • tokenHolders: the address-keyed policy registry and immutable-holder route contract. status=available means the registry is usable for the advertised chain, not that a population is certified or an unlisted token is eligible. Use unqualifiedTokenPolicy to recognize the terminal, non-retryable 422; read each holder response for generation freshness, completeness, and certification.

Discover JSON-RPC methods

Call service discovery on the preferred header-auth server endpoint:

curl "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/api/v1/SN_MAIN/rpc" \
  -H "Content-Type: application/json" \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  --data '{"jsonrpc":"2.0","id":1,"method":"rpc.discover","params":[]}'

The result is deterministic for the runtime and caller authorization. Discovery never contacts an upstream provider. Do not cache one caller's result for a different key.

Resolve a REST operation

Choose the smallest operation in routeFamilies[].operations[], fetch documentation.openapiUrl, percent-decode the fragment in openapiOperationRef once, and resolve it as a JSON Pointer. That operation is authoritative for parameters, request bodies, response schemas, examples, and the response rate-limit class.

This avoids learning route shapes from 400 responses or assuming that two keys expose the same operations.

Operating rules that commonly break clients

  • /v1/me/* accepts a signed-in Better Auth session, not X-Starkscan-Api-Key. Programmatic key capabilities live in caller.
  • Transfer lists are newest-first. Treat cursors as opaque and pass them back unchanged.
  • Lightweight transfer rows intentionally omit historicalUsd; fetch the documented detail/enrichment surface when historical pricing is required.
  • Search is identifier-only in the default legacy mode. Opt in with mode=typed for bounded indexed classes, message hashes/related transactions, token name/symbol prefixes (minimum three characters), and reviewed class-family aliases whose classes are indexed. Optional unique comma-separated entity_types limits families. Several exact types may share a hash: offer a choice instead of guessing. Message contexts retain source direction/transaction/index/block and an explicit truncation flag; no bridge pairs are inferred. 503 search_unavailable is not an empty match set. The site uses typed mode with explicit class:, message:, token:, tx:, block:, and contract: scopes. Arbitrary event/function names, NFT IDs and domains are not global matches without their own indexed catalog.
  • Empty and oversized batches are rejected before child dispatch. Read rpcProvider.batch.maxItems and rpcProvider.batch.maxResponseBytes instead of probing larger payloads.

Bootstrap from only a host

Typed search returns at most six suggestions per type and 24 overall, not a complete directory. resultsMayBeTruncated conservatively flags a saturated bound; contextsTruncated means more indexed occurrences may exist beyond a bounded branch, never a precise total. Explicit older-server rejection of typed parameters triggers one q-only compatibility request; other errors do not.

curl "https://starkscan.co/.well-known/api-catalog"

The catalog links to OpenAPI, this guide, the capabilities schema, the authenticated capabilities endpoint, and status. Continue with the Agent HTTP quickstart, Starkscan RPC, or the complete API reference.

On this page