API Keys
API keys provide higher rate limits and usage tracking for production applications.
Benefitsโ
| Feature | Free Tier | API Key |
|---|---|---|
| Daily calls | 100 | 500 |
| Per-minute limit | 30 | 60 |
| Usage analytics | Basic | Detailed |
| Priority support | Community | |
| Tracking method | By IP | By key |
How to Request an API Keyโ
Option 1: Via Dashboard (Recommended)โ
- Visit api.web3identity.com/dashboard
- Connect your wallet (SIWE authentication)
- Click "Create API Key"
- Enter a name for your key (e.g., "Production", "Staging")
- 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
}
}
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 Type | Value | Reset Window |
|---|---|---|
| Daily calls | 500 | Rolling 24 hours |
| Per minute | 60 | Rolling 60 seconds |
| Concurrent requests | 10 | โ |
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"
}
}
- 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"โ
| Cause | Solution |
|---|---|
| Typo in key | Check for extra whitespace or missing characters |
| Wrong header name | Use X-API-Key (case-insensitive) |
| Key revoked | Check dashboard for key status |
| Key rotated | Use the new key from rotation |
"Insufficient Credits"โ
| Cause | Solution |
|---|---|
| Credits depleted | Purchase more credits |
| Daily limit reached | Wait 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โ
- Rate Limits โ Understand all limits in detail
- Best Practices โ Optimize your integration
- x402 Payments โ Alternative pay-per-request model
- SIWE Authentication โ Wallet-based authentication