API Keys & Rate Limits

Authenticate API requests to raise your rate limits, and handle throttling gracefully.

The public REST API works anonymously, but authenticated requests get a higher, dedicated rate limit. This page covers key creation, request authentication, and 429 handling.


Rate limit tiers

TierHow to authenticateLimit (per IP or key)
AnonymousNone~10 requests/second, shared across your IP
API keyAuthorization: Bearer <key> header~50 requests/second, dedicated to your key
EaaS / self-hostedInstance-level configurationConfigurable per instance

Limits are applied per second with a small burst allowance. Exceeding them returns 429 Too Many Requests.

Create an API key

  1. Sign in at xdcscan.io.
  2. Open Account β†’ API keys and create a key.
  3. Store it securely β€” it is shown only once.

Or create one programmatically with the Account API:

curl -X POST https://xdcscan.io/account/api/v1/user/api-keys -H "Authorization: Bearer YOUR_SESSION_TOKEN" -H "Content-Type: application/json" -d '{"name": "production-backend"}'

Authenticate requests

Send the key as a bearer token. The same key works on both the REST API and the Account API:

curl https://xdcscan.io/api/v2/stats -H "Authorization: Bearer $OPENSCAN_API_KEY"

Handling 429 responses

When throttled, the API returns 429 with a Retry-After header (seconds to wait). Back off and retry rather than hammering the endpoint:

async function apiWithRetry(path, attempts = 5) {
for (let i = 0; i < attempts; i++) {
  const res = await fetch("https://xdcscan.io" + path, {
    headers: {
      Authorization: "Bearer " + process.env.OPENSCAN_API_KEY,
    },
  });
  if (res.status !== 429) return res.json();

  const retryAfter = Number(res.headers.get("Retry-After") || 2 ** i);
  await new Promise((r) => setTimeout(r, retryAfter * 1000));

}
throw new Error("Rate limited after " + attempts + " attempts");
}

Best practices

  • Cache aggressively. Chain stats and token metadata change slowly; cache them for 10–60 seconds instead of refetching per user request.
  • Paginate, don’t poll. When syncing history, walk next_page_params to completion and resume later from the newest known item instead of re-fetching everything.
  • Keep keys server-side. Never embed an API key in frontend code that ships to browsers β€” proxy requests through your backend.
  • Rotate keys. Create a new key, deploy it, then revoke the old one. Keys can be revoked any time from Account β†’ API keys.
  • One key per service. Separate keys make usage attribution and revocation easier.

Security notes

  • Keys grant read access to public chain data plus your account features (watchlists, private tags). Treat them like passwords.
  • If a key leaks, revoke it immediately via the Account API: DELETE /account/api/v1/user/api-keys/{id}.