Skip to main content

API Keys

API keys provide higher rate limits and usage tracking for production applications.

Benefitsโ€‹

FeatureFree TierAPI Key
Daily calls100500
Per-minute limit3060
Usage analyticsBasicDetailed
Priority supportCommunityEmail
Tracking methodBy IPBy key

How to Request an API Keyโ€‹

  1. Visit api.web3identity.com/dashboard
  2. Connect your wallet (SIWE authentication)
  3. Click "Create API Key"
  4. Enter a name for your key (e.g., "Production", "Staging")
  5. Copy and securely store your key โ€” it's only shown once!

Option 2: Via APIโ€‹

First, authenticate with SIWE to get a session token:

# 1. Get a nonce
curl https://api.web3identity.com/api/auth/siwe/nonce
# Returns: { "nonce": "abc123..." }

# 2. Sign message with wallet and verify
curl -X POST https://api.web3identity.com/api/auth/siwe/verify \
-H "Content-Type: application/json" \
-d '{"message":"...", "signature":"0x..."}'
# Returns: { "token": "eyJ...", "address": "0x...", "expiresAt": "..." }

Then request an API key:

# 3. Request API key
curl -X POST https://api.web3identity.com/api/auth/apikey/request \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{"name": "My Production App"}'

Response:

{
"success": true,
"key": {
"id": "key_abc123def456",
"name": "My Production App",
"key": "atv_live_xK9mN2pL5qR8sT1vW4yZ7aB0cD3eF6gH",
"createdAt": "2026-02-08T15:30:00Z",
"credits": 0,
"dailyLimit": 500,
"minuteLimit": 60
}
}
Store Your Key Securely

The full API key is only returned once during creation. Store it in a secure location like a password manager or environment variable. You cannot retrieve it later.

How to Use API Keysโ€‹

Include the X-API-Key header in all requests:

cURLโ€‹

curl -H "X-API-Key: atv_live_xK9mN2pL5qR8sT1vW4yZ7aB0cD3eF6gH" \
https://api.web3identity.com/api/ens/resolve/vitalik.eth

JavaScriptโ€‹

const response = await fetch('https://api.web3identity.com/api/ens/resolve/vitalik.eth', {
headers: {
'X-API-Key': process.env.WEB3_IDENTITY_API_KEY
}
});

const data = await response.json();

Using the SDKโ€‹

import { Web3IdentityClient } from '@atv-eth/x402-sdk';

const client = new Web3IdentityClient({
apiKey: process.env.WEB3_IDENTITY_API_KEY
});

const profile = await client.getProfile('vitalik.eth');

Pythonโ€‹

import requests

response = requests.get(
'https://api.web3identity.com/api/ens/resolve/vitalik.eth',
headers={'X-API-Key': os.environ['WEB3_IDENTITY_API_KEY']}
)

Rate Limits with API Keysโ€‹

Limit TypeValueReset Window
Daily calls500Rolling 24 hours
Per minute60Rolling 60 seconds
Concurrent requests10โ€”

API key rate limits are tracked per key, not per IP. You can use the same key from multiple servers.

Rate Limit Headersโ€‹

Every response includes rate limit information:

X-RateLimit-Limit: 500
X-RateLimit-Remaining: 423
X-RateLimit-Reset: 1707440400

Credits Systemโ€‹

How Credits Workโ€‹

API keys can optionally use prepaid credits for higher limits or to ensure uninterrupted service:

  • Base tier: 500 calls/day included
  • With credits: Each call deducts from your credit balance
  • Overage: When daily limit is reached, credits are used

Purchasing Creditsโ€‹

# Check available credit packages
curl -H "Authorization: Bearer eyJ..." \
https://api.web3identity.com/api/credits/packages
{
"packages": [
{ "id": "credits_100", "credits": 100, "price": "$0.90", "perCall": "$0.009" },
{ "id": "credits_500", "credits": 500, "price": "$4.00", "perCall": "$0.008" },
{ "id": "credits_1000", "credits": 1000, "price": "$7.00", "perCall": "$0.007" },
{ "id": "credits_5000", "credits": 5000, "price": "$30.00", "perCall": "$0.006" }
]
}

Purchase via the dashboard or API:

curl -X POST https://api.web3identity.com/api/credits/purchase \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{"keyId": "key_abc123", "packageId": "credits_1000"}'

Checking Credit Balanceโ€‹

curl -H "X-API-Key: atv_live_..." \
https://api.web3identity.com/api/usage
{
"used": 234,
"limit": 500,
"remaining": 266,
"credits": {
"balance": 766,
"usedToday": 0
},
"tier": "api_key",
"resetsAt": "2026-02-09T00:00:00Z"
}

Managing API Keysโ€‹

List All Keysโ€‹

curl -H "Authorization: Bearer eyJ..." \
https://api.web3identity.com/api/user/keys
{
"keys": [
{
"id": "key_abc123",
"name": "Production",
"prefix": "atv_live_xK9m...",
"createdAt": "2026-02-01T10:00:00Z",
"lastUsedAt": "2026-02-08T14:23:00Z",
"credits": 847,
"usageToday": 153
},
{
"id": "key_def456",
"name": "Staging",
"prefix": "atv_live_yL0n...",
"createdAt": "2026-02-05T09:00:00Z",
"lastUsedAt": "2026-02-07T11:45:00Z",
"credits": 0,
"usageToday": 42
}
]
}

Rotate a Keyโ€‹

Generate a new key while keeping the same ID and credits:

curl -X POST https://api.web3identity.com/api/user/keys/key_abc123/rotate \
-H "Authorization: Bearer eyJ..."
{
"success": true,
"key": {
"id": "key_abc123",
"key": "atv_live_newKeyValue123...",
"note": "Previous key is now invalid"
}
}
Key Rotation Best Practices
  • Rotate keys every 90 days
  • Rotate immediately if you suspect compromise
  • Update all services with the new key before the old one expires

Revoke a Keyโ€‹

Permanently disable a key:

curl -X DELETE https://api.web3identity.com/api/user/keys/key_abc123 \
-H "Authorization: Bearer eyJ..."
{
"success": true,
"message": "Key revoked. Any unused credits have been returned to your account."
}

Security Best Practicesโ€‹

Keep Keys Secretโ€‹

// โœ… Good: Environment variable
const apiKey = process.env.WEB3_IDENTITY_API_KEY;

// โŒ Bad: Hardcoded in source
const apiKey = 'atv_live_abc123...';

// โŒ Bad: In client-side code
// API keys should NEVER be in browser JavaScript

Use Environment Variablesโ€‹

# .env file (add to .gitignore!)
WEB3_IDENTITY_API_KEY=atv_live_xK9mN2pL5qR8sT1vW4yZ7aB0cD3eF6gH
// Node.js
import 'dotenv/config';
const apiKey = process.env.WEB3_IDENTITY_API_KEY;

Server-Side Onlyโ€‹

API keys should only be used in server-side code:

// โœ… Server-side (Node.js, Next.js API routes, serverless)
export async function getServerSideProps() {
const data = await fetch(url, {
headers: { 'X-API-Key': process.env.API_KEY }
});
}

// โœ… API route (Next.js)
export default async function handler(req, res) {
const data = await fetch(url, {
headers: { 'X-API-Key': process.env.API_KEY }
});
res.json(data);
}

// โŒ Client-side (NEVER!)
// Browser JavaScript exposes keys to users

Monitor for Anomaliesโ€‹

Check usage regularly for unexpected patterns:

const checkUsage = async () => {
const response = await fetch('https://api.web3identity.com/api/usage', {
headers: { 'X-API-Key': process.env.API_KEY }
});
const usage = await response.json();

// Alert if usage is unusually high
if (usage.used > usage.limit * 0.8) {
console.warn(`API usage at ${usage.used}/${usage.limit} (${Math.round(usage.used/usage.limit*100)}%)`);
}
};

Implementing Rate Limit Handlingโ€‹

class RateLimitedAPIClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.web3identity.com';
}

async fetch(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
...options.headers,
'X-API-Key': this.apiKey,
},
});

if (response.status === 429) {
const error = await response.json();
const retryAfter = error.details?.retryAfter || 60;

console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));

return this.fetch(endpoint, options); // Retry
}

if (!response.ok) {
const error = await response.json();
throw new Error(error.message || `HTTP ${response.status}`);
}

return response.json();
}
}

// Usage
const client = new RateLimitedAPIClient(process.env.WEB3_IDENTITY_API_KEY);
const profile = await client.fetch('/api/ens/resolve/vitalik.eth');

Troubleshootingโ€‹

"Invalid API Key"โ€‹

CauseSolution
Typo in keyCheck for extra whitespace or missing characters
Wrong header nameUse X-API-Key (case-insensitive)
Key revokedCheck dashboard for key status
Key rotatedUse the new key from rotation

"Insufficient Credits"โ€‹

CauseSolution
Credits depletedPurchase more credits
Daily limit reachedWait for reset or use credits

"Rate Limited" with API Keyโ€‹

Even with an API key, you're limited to 60 requests/minute:

// Implement proper throttling
const queue = [];
let lastRequest = 0;
const minInterval = 1000; // 1 req/sec = 60/min

async function throttledFetch(url) {
const now = Date.now();
const waitTime = Math.max(0, lastRequest + minInterval - now);

if (waitTime > 0) {
await new Promise(r => setTimeout(r, waitTime));
}

lastRequest = Date.now();
return fetch(url, { headers: { 'X-API-Key': API_KEY } });
}

Next Stepsโ€‹