Error Response Format
All API errors follow a consistent JSON format:
{
"error": "Error message describing what went wrong"
}
The HTTP status code indicates the error category, and the error message provides specific details.
HTTP Status Codes
Success Codes
Request successful, data returned
Client Error Codes
The request was malformed or contains invalid parametersCommon causes:
- Missing required query parameters
- Invalid ticker_id format
- Malformed request body
The requested resource does not existCommon causes:
- Invalid endpoint path
- Ticker not found
- DAO does not exist
Rate limit exceededDetails:
- Limit: 60 requests per minute per IP
- Reset: Wait until the next minute window
Server Error Codes
An unexpected error occurred on the serverCommon causes:
- RPC connection issues
- Blockchain data unavailable
- Service temporarily down
Upstream service (RPC) is unavailable
API is temporarily unavailable (maintenance or overload)
Common Error Scenarios
Rate Limit Exceeded
When you exceed 60 requests per minute:
{
"error": "Rate limit exceeded. Please try again later."
}
Solution:
Implement Retry Logic
Wait 60 seconds before retrying
Use Exponential Backoff
Gradually increase wait time between retries
Cache Responses
Store frequently accessed data locally
Example Implementation:
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.status === 429) {
const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
// Usage
const tickers = await fetchWithRetry('https://your-api-domain.com/api/tickers');
import time
import requests
from typing import Optional, Dict
def fetch_with_retry(url: str, max_retries: int = 3) -> Optional[Dict]:
for i in range(max_retries):
try:
response = requests.get(url)
if response.status_code == 429:
wait_time = (2 ** i) * 1 # Exponential backoff
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
if i == max_retries - 1:
raise e
time.sleep(i + 1)
return None
# Usage
tickers = fetch_with_retry('https://your-api-domain.com/api/tickers')
Ticker Not Found
When requesting a specific ticker that doesn’t exist:
{
"error": "Ticker not found: INVALID_MINT_ADDRESS"
}
Solutions:
- Verify the ticker_id format:
{BASE_MINT}_{QUOTE_MINT}
- Ensure both mint addresses are valid Solana PublicKeys
- Check if the DAO is excluded via
EXCLUDED_DAOS
- Verify the DAO has active pools with reserves
RPC Connection Issues
When the Solana RPC is unavailable:
{
"error": "Failed to fetch DAO data from blockchain"
}
Solutions:
Check RPC Status
Verify your RPC provider is operational
Use Fallback RPC
Configure multiple RPC endpoints
Upgrade RPC Tier
Use a premium RPC provider
Retry Request
Implement automatic retry logic
Invalid Configuration
When required environment variables are missing:
{
"error": "FACTORY_ADDRESS not configured"
}
Solution: Ensure all required environment variables are set in your .env file:
FACTORY_ADDRESS=YOUR_FACTORY_PROGRAM_ID
ROUTER_ADDRESS=YOUR_ROUTER_PROGRAM_ID
Error Handling Best Practices
Never assume requests will succeed. Wrap all API calls in try-catch blocks.try {
const data = await fetch('/api/tickers').then(r => r.json());
} catch (error) {
console.error('API request failed:', error);
// Handle error appropriately
}
Set reasonable timeouts to prevent hanging requests.const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout
try {
const response = await fetch('/api/tickers', {
signal: controller.signal
});
clearTimeout(timeout);
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
}
}
Implement exponential backoff for transient errors.See code examples above for implementation details.
Cache successful responses to reduce API load and improve resilience.const cache = new Map();
const CACHE_TTL = 10000; // 10 seconds
async function getCached(url) {
const cached = cache.get(url);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const data = await fetch(url).then(r => r.json());
cache.set(url, { data, timestamp: Date.now() });
return data;
}
Log all errors for debugging and monitoring.async function fetchAPI(url) {
try {
return await fetch(url).then(r => r.json());
} catch (error) {
console.error({
timestamp: new Date().toISOString(),
url,
error: error.message,
stack: error.stack
});
throw error;
}
}
Monitoring API Health
Use the health check endpoint to monitor API status:
curl https://your-api-domain.com/health
Healthy Response:
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": 3600.5
}
Set up automated health checks every 1-5 minutes to detect issues early.
Getting Support
If you encounter persistent errors:
API Overview
Review API documentation for proper usage
GitHub Issues
Report bugs or request features
Discord Support
Get help from the community
Configuration Guide
Check configuration settings
Error Response Examples
{
"error": "Invalid ticker_id format. Expected: BASE_MINT_QUOTE_MINT"
}
{
"error": "Endpoint not found: /api/invalid"
}
{
"error": "Rate limit exceeded. Please try again later."
}
{
"error": "Failed to fetch DAO data from blockchain"
}
{
"error": "Service temporarily unavailable. Please try again in a few moments."
}