Authentication & API Keys
All API requests to ChainX Scanner require authentication via an API key. This guide explains how to generate, manage, and use API keys securely.
API Key Authentication
ChainX Scanner uses API key-based authentication. All protected endpoints require the X-API-Key header:
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/scan \ -H "X-API-Key: prod-chainx-abc123..." \ -F "file=@contract.sol"
Authentication Flow
- Register Account → Receive user ID
- Verify Email → Activate account
- Generate API Key → Get authentication credential
- Use API Key → Include in
X-API-Keyheader
Managing API Keys
Generate a New API Key
Create an API key for your application:
- cURL
- JavaScript
- Python
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/generate-api-key \ -H "Content-Type: application/json" \ -d '{ "userId": "cluxyz123", "type": "PRODUCTION", "name": "My App API Key" }'
async function generateApiKey(userId, type, name) { const response = await fetch('https://chainx-api-a154bfdeaf7a.herokuapp.com/api/generate-api-key', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: userId, type: type, name: name }) }); return response.json();}// Usageconst apiKey = await generateApiKey('cluxyz123', 'PRODUCTION', 'My App API Key');console.log(apiKey.apiKey.keyValue); // prod-chainx-abc123...
import requestsdef generate_api_key(user_id, key_type, name): url = 'https://chainx-api-a154bfdeaf7a.herokuapp.com/api/generate-api-key' payload = { 'userId': user_id, 'type': key_type, 'name': name } response = requests.post(url, json=payload) return response.json()# Usageapi_key = generate_api_key('cluxyz123', 'PRODUCTION', 'My App API Key')print(api_key['apiKey']['keyValue'])
Response:
{ "message": "API key generated successfully", "apiKey": { "id": "key_123", "keyValue": "prod-chainx-abc123...", "type": "PRODUCTION", "expiresAt": "2027-01-31T00:00:00Z" }}
Retrieve Your API Keys
List all API keys associated with your account:
- cURL
- JavaScript
- Python
curl -X GET "https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/user-api-keys?userId=cluxyz123" \ -H "Content-Type: application/json"
async function getApiKeys(userId) { const response = await fetch(`https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/user-api-keys?userId=${userId}`); return response.json();}// Usageconst keys = await getApiKeys('cluxyz123');console.log(keys.data.apiKeys);
import requestsdef get_api_keys(user_id): url = f'https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/user-api-keys?userId={user_id}' response = requests.get(url) return response.json()# Usagekeys = get_api_keys('cluxyz123')print(keys['data']['apiKeys'])
Response:
{ "success": true, "message": "API keys fetched successfully", "data": { "apiKeys": [ { "id": "key_123", "name": "My App API Key", "keyValue": "prod-chainx-abc123...", "type": "PRODUCTION", "expiresAt": "2027-01-31T00:00:00Z", "status": "ACTIVE" }, { "id": "key_456", "name": "Test Key", "keyValue": "test-chainx-def456...", "type": "TEST", "expiresAt": "2026-06-30T00:00:00Z", "status": "ACTIVE" } ], "total": 2 }}
API Key Types
PRODUCTION Key
- For production environments
- Longer expiration (typically 1+ years)
- Subject to full rate limits
- Use for actual smart contract scanning
TEST Key
- For development and testing
- Shorter expiration (typically 3-6 months)
- May have higher rate limits
- Use before deploying to production
Security Best Practices
1. Environment Variables
Never hardcode API keys:
// ❌ DON'T DO THISconst apiKey = 'prod-chainx-abc123...';// ✅ DO THISconst apiKey = process.env.CHAINX_API_KEY;
2. Secure Storage
Store API keys in:
- Environment variable files (
.env) - Secret management systems (AWS Secrets Manager, HashiCorp Vault)
- Secure credential stores (1Password, LastPass)
3. Key Rotation
- Regularly rotate old API keys
- Create new keys before deleting old ones
- Audit key usage periodically
4. Minimal Permissions
- Use different keys for different environments
- Use TEST keys for development
- Limit key expiration dates
5. Monitoring
Monitor API key usage patterns:
- Track scan frequency
- Monitor rate limit errors
- Check for unusual activity
Error Handling
401 Unauthorized - Missing API Key
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/scan \ -F "file=@contract.sol"
Response:
{ "error": "API key is required. Please provide X-API-Key header."}
Fix: Include the X-API-Key header:
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/scan \ -H "X-API-Key: prod-chainx-abc123..." \ -F "file=@contract.sol"
403 Forbidden - Invalid API Key
{ "error": "Invalid or expired API key"}
Causes:
- API key doesn't exist
- API key has expired
- API key is inactive
Fix:
- Verify the API key value is correct
- Check if the key has expired
- Generate a new API key if needed
429 Too Many Requests - Rate Limited
{ "error": "API rate limit exceeded"}
Fix:
- Wait before making additional requests
- Implement exponential backoff
- Upgrade your subscription plan
- Contact support for higher limits
Rate Limiting
Rate limits vary by subscription plan:
| Plan | Requests/Hour | Scans/Day |
|---|---|---|
| Free | 60 | 5 |
| Basic | 600 | 100 |
| Pro | 6000 | 1000 |
Handling Rate Limits
Implement exponential backoff with jitter:
- JavaScript
- Python
async function scanWithRetry(filePath, apiKey, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { const response = await fetch('https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/scan', { method: 'POST', headers: { 'X-API-Key': apiKey }, body: formData }); if (response.status === 429) { // Calculate exponential backoff: 2^attempt * 1000ms + random jitter const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000; console.log(`Rate limited. Retrying in ${delay}ms...`); await new Promise(resolve => setTimeout(resolve, delay)); continue; } return response.json(); } catch (error) { console.error(`Attempt ${attempt + 1} failed:`, error); if (attempt === maxRetries - 1) throw error; } }}
import requestsimport timeimport randomdef scan_with_retry(file_path, api_key, max_retries=3): for attempt in range(max_retries): try: with open(file_path, 'rb') as f: files = {'file': f} response = requests.post( 'https://chainx-api-a154bfdeaf7a.herokuapp.com/api/v1/scan', headers={'X-API-Key': api_key}, files=files ) if response.status_code == 429: # Exponential backoff with jitter delay = (2 ** attempt) * 1 + random.random() print(f"Rate limited. Retrying in {delay:.2f}s...") time.sleep(delay) continue return response.json() except requests.RequestException as e: if attempt == max_retries - 1: raise time.sleep((2 ** attempt) * 1)
Account Management
Change Password
Request a password reset:
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/forgot-password \ -H "Content-Type: application/json" \ -d '{ "email": "developer@example.com" }'
Reset password with token:
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/reset-password \ -H "Content-Type: application/json" \ -d '{ "token": "reset-token-from-email", "newPassword": "newSecurePassword123" }'
Resend OTP
If you didn't receive the verification OTP:
curl -X POST https://chainx-api-a154bfdeaf7a.herokuapp.com/api/resend-otp \ -H "Content-Type: application/json" \ -d '{ "email": "developer@example.com" }'
Troubleshooting
| Issue | Solution |
|---|---|
| "API key is required" | Add X-API-Key header to your request |
| "Invalid or expired API key" | Generate a new API key and update your code |
| "Rate limit exceeded" | Implement exponential backoff or upgrade plan |
| Can't access account | Check email for password reset link |
| Lost API key | Generate a new key from your account |