API keys
Create secret API keys, authenticate server-side requests, and understand errors, rate limits, billing, rotation, and IP allowlists.
The Scanner API lets your own servers run the same scans, traces, and lookups you use in the dashboard. You authenticate with a secret API key that you create yourself.
Who gets access
API access is included on the Scale and Enterprise plans. Access is checked on every request against your current plan:
- An active Scale or Enterprise plan works while its billing period is current. A renewal has up to 3 days after the period ends to go through.
- A cancelled plan keeps working until the end of the period you paid for.
- When the plan lapses, or you move to a plan without API access, your keys are paused and return
API_PLAN_REQUIRED. They start working again as soon as the plan does. You can still view and revoke paused keys.
See the pricing page for plans.
Create a key
- Open API in your dashboard.
- Select Create key, give it a name (for example the service or environment that will use it), and optionally add an IP allowlist.
- Copy the key and store it in your secret manager.
Keys look like sk_live_ followed by 43 letters and numbers. The full key is shown once, right after you create or roll it. Scanner stores only a hash, so nobody can show it to you again. If you lose it, roll the key.
Each account can have up to 5 active keys. A key that is in its 24-hour rotation grace period doesn't count toward the limit.
Authenticate
Send the key in a header on every request. Either form works:
curl -X POST "https://api.scanner.net/scan" \
-H "Authorization: Bearer $SCANNER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"WALLET_ADDRESS","depth":0}'curl "https://api.scanner.net/v1/whoami" \
-H "x-api-key: $SCANNER_API_KEY"Send one credential per request. A request that carries more than one (for example both an Authorization and an x-api-key header, or a secret key together with an embed key) is rejected with 400 INVALID_INPUT.
Two rules are enforced, not just recommended:
- Never put a key in a URL. A request with a secret key in the query string or path is rejected with
API_KEY_IN_URL, because URLs end up in logs, proxies, and browser history. If that happens, roll the key. - Never use a key in a browser. Requests a browser makes (an
Originheader together with theSec-Fetch-Mode: corsornavigateorSec-Fetch-Siteheaders browsers add) are rejected withAPI_KEY_BROWSER_NOT_ALLOWED. Call the API from your backend and pass results to your frontend. For a browser widget, use the Embed API instead.
Server-side HTTP clients that send an Origin header of their own, without the browser Sec-Fetch-* headers, are accepted.
Endpoints
Keys work on the scanning and lookup endpoints, on both Solana and Robinhood Chain:
- wallet and token scans (
/scan,/contracts,/rh/scan,/rh/contracts) - funding chains and cross-chain traces (
/funding-chain,/cross-chain) - AI analysis of a Solana wallet scan (
/analyze, 1 scan per analysis) - the explorer (
/explorer,/rh/explorer) - address detection, identities, and wallet holdings (
/detect,/identities,/holdings) - the wallet finder (
/wallet-finder,/rh/wallet-finder) - alpha traders, KOL wallets, and bundles (
/alpha,/kol,/bundles)
Account, billing, and admin endpoints are not available with a key and return API_KEY_ROUTE_NOT_ALLOWED. Indexer access is separate and is not covered by these keys.
Check a key
Two endpoints report on the key itself. Neither spends scans, but both count toward the key's rate limit.
GET /v1/whoamireturns the account and key the request authenticated as, the plan, and the effective requests-per-minute limit for that key.GET /v1/usagereturns your remaining scans, the effective per-minute limit, and daily request counts grouped by endpoint and status class. It covers the last 30 days by default; pass?days=for anything from 1 to 90.
curl "https://api.scanner.net/v1/usage?days=7" \
-H "Authorization: Bearer $SCANNER_API_KEY"Errors
Every error has the same shape:
{ "error": "Invalid API key", "code": "API_KEY_INVALID", "requestId": "..." }| Status | Code | Meaning |
|---|---|---|
| 400 | API_KEY_IN_URL | The key was sent in a URL. Send it in a header, and roll the key. |
| 400 | INVALID_INPUT | The request carried more than one credential. Send a single key in a single header. |
| 401 | API_KEY_INVALID | The key doesn't exist. Check for typos or whitespace. |
| 401 | API_KEY_REVOKED | The key was revoked, or its rotation grace period ended. |
| 403 | API_KEY_BROWSER_NOT_ALLOWED | The request came from a browser (Origin plus browser Sec-Fetch-* headers). Call the API from a server. |
| 403 | API_KEY_ROUTE_NOT_ALLOWED | This endpoint isn't available with an API key. |
| 403 | API_KEY_IP_NOT_ALLOWED | The request IP isn't on the key's allowlist. |
| 403 | API_PLAN_REQUIRED | Your plan doesn't include API access. The body includes upgradeUrl. |
| 403 | FORBIDDEN | API access has been switched off for your account. Contact support. |
| 402 | INSUFFICIENT_CREDITS | Not enough scans left on your account for this request. |
| 429 | API_KEY_RATE_LIMITED | The key's per-minute limit was reached. Wait for Retry-After seconds. |
| 429 | RATE_LIMITED | Too many invalid keys from your IP address (30 per minute). Wait for Retry-After seconds. |
| 503 | INTERNAL_ERROR | Key verification is briefly unavailable. Retry after a short delay. |
Rate limits
Limits apply per minute and are shared across all Scanner servers. Two buckets are checked on every request: one for the key, and one for the whole account.
| Plan | Requests per minute |
|---|---|
| Scale | 120 |
| Enterprise | 600 by default, adjustable per contract |
The account bucket uses the same number, so this is the ceiling for the account as a whole. Five keys on a Scale plan share those 120 requests a minute, they do not get 120 each. X-RateLimit-Limit reports the lower of the two buckets for the key that made the request.
Every successful response includes X-RateLimit-Limit and X-RateLimit-Remaining. The window is rolling, so X-RateLimit-Remaining is an estimate when several requests with the same key arrive at once. A 429 also includes Retry-After with the number of seconds until a request fits in the window again. Back off and retry after that time rather than retrying immediately.
Billing
API requests spend scans from your plan's allowance exactly like the dashboard: a Quick scan spends 1, Deep 2, Max 4, and a token scan 1. The full table is on the Deep Scan page. Cached results are free, failed scans refund automatically, and lookups that are free in the dashboard are free through the API.
The API page shows requests and scans spent per day and per key for the last 30 days. Usage can take up to a minute to appear.
Rotation
Roll a key from the dashboard to replace it with a new secret. The new key keeps the old key's name and IP allowlist. You choose what happens to the old key:
- Keep old key working for 24 hours. Use this for routine rotation: deploy the new key, and the old one stops on its own after 24 hours.
- Revoke old key now. Use this when a key has leaked. The old key stops working immediately.
Revoke stops a single key immediately. Revoke all stops every key on the account at once. Revoking or rolling a key, and plan changes, take effect on every server as soon as they are saved. If the servers briefly lose contact with each other, a change can take up to 5 seconds to reach all of them.
Creating, rolling, revoking, and revoking all keys each send an email to your account address with the key name, time, and IP address, so you'll know if someone else made the change. Renames and allowlist edits are recorded in the key activity list without an email, and accounts that signed in with a wallet and have no email address get the activity list alone.
IP allowlist
Add an allowlist to a key to accept requests only from your servers. Enter one IPv4 or IPv6 address, or CIDR range, per line, for example 203.0.113.10 or 198.51.100.0/24. Leave it empty to accept any IP. Requests from other addresses get API_KEY_IP_NOT_ALLOWED.
- A key's allowlist holds at most 50 entries.
- A
/0range is rejected. It would match every address, which is the same as having no allowlist. - A single address is stored as a
/32(IPv4) or/128(IPv6) range. - Ranges are stored by their network address, so
10.0.0.5/8is saved as10.0.0.0/8. Check the saved list if you entered a range with host bits set.
Activity list
The activity list on the API page records key changes and blocked attempts: requests from an IP outside the allowlist, use of a revoked key, and use of a key while the plan doesn't include API access. Blocked attempts are recorded at most once every 10 minutes per key for each kind, so an entry tells you it happened, not how often. Use the per-day usage to judge volume.
Security practices
- Store keys in a secret manager or environment variables, never in source control.
- Use a separate key per service or environment, so you can roll one without touching the rest.
- Add an IP allowlist when your servers have fixed egress addresses.
- Roll keys on a schedule, and immediately when someone with access leaves.
- Check the activity list on the API page for blocked attempts, such as a revoked key still being used.
- If a key leaks, roll it with Revoke old key now, then check usage for requests you don't recognize.