Rate limits
Understand Starkscan route-class budgets, headers, and the correct retry behavior for external API keys.
Understand Starkscan route-class budgets, headers, and the correct retry behavior for external API keys.
Starkscan rate-limits external API keys by route class.
Treat rate limits as part of the HTTP contract, not as a hidden operational detail.
Current hosted external keys use two budget classes. The OpenAPI schema reserves
additional fine-grained class names for self-hosted/internal deployments, but
clients using Starkscan-issued API keys should back off on the class they
actually receive in X-Starkscan-Route-Class.
| Class | Typical use | Example routes |
|---|---|---|
light | cheap host/status and simple lookup reads | GET /v1/{chain}/status, GET /v1/{chain}/block/{block_ref}, GET /v1/{chain}/tx/{tx_hash} |
heavy | indexed lists, wallet/profile reads, exact token reads, traces, search, contract reads, and batch helpers | GET /v1/{chain}/token/{token}/balance-of/{address}, GET /v1/{chain}/token/{token}/total-supply, GET /v1/{chain}/address/{address}/transactions, GET /v1/{chain}/transfers?address={address}, GET /v1/{chain}/tx/{tx_hash}/trace, GET /v1/{chain}/search, GET /v1/{chain}/contract/{address}/read, POST /v1/{chain}/tx/previews |
The exact numeric budget is deployment-controlled. Read the headers instead of hard-coding assumptions into clients.
For wallet/app Voyager migrations, treat the replacement set as:
| Migration route | Expected hosted key class |
|---|---|
GET /v1/{chain}/token/{token}/balance-of/{address} | heavy |
GET /v1/{chain}/tx/{tx_hash} | light |
GET /v1/{chain}/address/{address}/transactions | heavy |
GET /v1/{chain}/transfers?address={address} | heavy |
Starkscan-issued API keys emit these budget headers on budgeted responses:
x-ratelimit-limitx-ratelimit-remainingx-ratelimit-policyX-Starkscan-Route-ClassOn 429 Too Many Requests, Starkscan also emits:
Retry-AfterExample response headers:
x-ratelimit-limit: 30
x-ratelimit-remaining: 0
x-ratelimit-policy: heavy;w=60
X-Starkscan-Route-Class: heavy
retry-after: 12
429 Too Many Requests, stop and honor Retry-After.x-ratelimit-remaining still looks healthy.heavy 429 stop unrelated light probes; keep backoff state per route class.429curl -i \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/contract/<address>/read?selector=<selector>"
Representative response:
HTTP/1.1 429 Too Many Requests
retry-after: 12
x-ratelimit-limit: 30
x-ratelimit-remaining: 0
x-ratelimit-policy: heavy;w=60
X-Starkscan-Route-Class: heavy
content-type: application/json; charset=utf-8
{"code":"rate_limited","message":"Rate limit exceeded; retry shortly","docSlug":"api/rate-limits","requestId":"mzk-..."}
Current public-read rate limiting is process-local fixed-window state:
Do not build client correctness on an assumption that every host behaves like one perfectly global distributed limiter.
heavy 429 should not force an agent to stop cheap light status checks.X-Request-Id on every failure.