API
Error Handling

Error Handling

Learn how to properly handle errors when working with the Digifi API.

Error Response Format

All API errors follow a consistent format:

{
  "success": false,
  "error": "Error message",
  "details": "Additional error information"
}

HTTP Status Codes

Status CodeMeaningCommon Causes
200SuccessRequest completed successfully
400Bad RequestInvalid parameters or malformed request
401UnauthorizedInvalid or missing API key
403ForbiddenQuota exceeded or insufficient permissions
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side error or deployment failure

Common Errors

Authentication Errors

Invalid API Key (401)

{
  "error": "Invalid API key"
}

Causes:

  • API key is incorrect or doesn't exist
  • API key has been revoked
  • Missing apiKey parameter

Solution:

// Verify your API key in the dashboard
const apiKey = process.env.DIGIFI_API_KEY;
if (!apiKey) {
  throw new Error('API key not configured');
}

Missing API Key (401)

{
  "error": "Missing API key"
}

Solution:

  • Include API key in Authorization header
  • Add apiKey to request body/query parameters

Rate Limit Errors

Rate Limit Exceeded (429)

{
  "error": "Token deployment is rate-limited to one per minute per API key. Please try again later."
}

Solution:

const deployWithRateLimit = async (name, symbol) => {
  try {
    return await deployToken(name, symbol);
  } catch (error) {
    if (error.response?.status === 429) {
      console.log('Rate limited, waiting 60 seconds...');
      await new Promise(resolve => setTimeout(resolve, 60000));
      return await deployToken(name, symbol);
    }
    throw error;
  }
};

Monthly Limit Reached (429)

{
  "error": "Monthly deployment limit reached (150). Please try again next month.",
  "monthlyDeployments": 150,
  "monthlyLimit": 150
}

Solution:

  • Wait until the 1st of next month
  • Contact support for enterprise limits
  • Monitor usage via API dashboard

Deployment Errors

Deployment Failed (500)

{
  "success": false,
  "message": "Deployment failed",
  "error": "Deployment process exited with code: 1",
  "details": "Full deployment output...",
  "deploymentId": "..."
}

Solution:

  • Check details field for specific error
  • Verify token name/symbol are valid
  • Retry the deployment
  • Contact support with deploymentId

Invalid Token Parameters (400)

{
  "error": "Missing name or symbol"
}

Solution:

function validateTokenParams(name, symbol) {
  if (!name || name.length < 1 || name.length > 50) {
    throw new Error('Token name must be 1-50 characters');
  }
  
  if (!symbol || symbol.length < 1 || symbol.length > 10) {
    throw new Error('Token symbol must be 1-10 characters');
  }
}

Rewards Checking Errors

Invalid Token Address (400)

{
  "error": "Invalid token address",
  "details": "No contract found at the provided address on Base",
  "network": {
    "name": "base",
    "chainId": "8453",
    "expectedChain": "Base Mainnet (chainId: 8453)"
  }
}

Solution:

  • Verify token exists on Base Mainnet
  • Check address format (0x... 42 characters)
  • Ensure token was deployed through Digifi

Invalid Contract (400)

{
  "error": "Invalid contract",
  "details": "Contract does not appear to be a SimpleToken",
  "hint": "Make sure this is a token deployed through the V4 factory on Base"
}

Solution:

  • Use only tokens deployed via Digifi
  • Verify it's a V4 factory token
  • Check the contract address is correct

Error Handling Patterns

Basic Try-Catch

const deployToken = async (name, symbol) => {
  try {
    const response = await fetch('https://api.digifi.fun/deployToken', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify({ name, symbol, chain_id: '8453', apiKey })
    });
    
    const data = await response.json();
    
    if (!data.success) {
      throw new Error(data.error || 'Deployment failed');
    }
    
    return data;
  } catch (error) {
    console.error('Deployment error:', error.message);
    throw error;
  }
};

Retry Logic

const deployWithRetry = async (name, symbol, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await deployToken(name, symbol);
    } catch (error) {
      console.log(`Attempt ${attempt} failed:`, error.message);
      
      // Don't retry on auth errors
      if (error.response?.status === 401 || error.response?.status === 403) {
        throw error;
      }
      
      // Don't retry on invalid parameters
      if (error.response?.status === 400) {
        throw error;
      }
      
      if (attempt === maxRetries) {
        throw new Error(`Failed after ${maxRetries} attempts: ${error.message}`);
      }
      
      // Exponential backoff
      const delay = 1000 * Math.pow(2, attempt - 1);
      console.log(`Waiting ${delay}ms before retry...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};

Comprehensive Error Handler

const handleApiError = (error) => {
  const status = error.response?.status;
  const data = error.response?.data;
  
  switch (status) {
    case 400:
      return {
        type: 'validation',
        message: 'Invalid request parameters',
        details: data?.error,
        retryable: false
      };
      
    case 401:
      return {
        type: 'authentication',
        message: 'Invalid API key',
        details: data?.error,
        retryable: false
      };
      
    case 403:
      return {
        type: 'authorization',
        message: 'Access denied or quota exceeded',
        details: data?.error,
        retryable: false
      };
      
    case 429:
      return {
        type: 'rate_limit',
        message: 'Rate limit exceeded',
        details: data?.error,
        retryable: true,
        retryAfter: 60000 // 1 minute
      };
      
    case 500:
      return {
        type: 'server_error',
        message: 'Server error',
        details: data?.details,
        deploymentId: data?.deploymentId,
        retryable: true,
        retryAfter: 5000 // 5 seconds
      };
      
    default:
      return {
        type: 'unknown',
        message: error.message,
        retryable: true,
        retryAfter: 5000
      };
  }
};
 
// Usage
try {
  const result = await deployToken('MyToken', 'MTK');
} catch (error) {
  const errorInfo = handleApiError(error);
  
  console.error(`Error type: ${errorInfo.type}`);
  console.error(`Message: ${errorInfo.message}`);
  console.error(`Details: ${errorInfo.details}`);
  
  if (errorInfo.retryable) {
    console.log(`Retrying after ${errorInfo.retryAfter}ms...`);
    await new Promise(resolve => setTimeout(resolve, errorInfo.retryAfter));
    // Retry logic here
  }
}

TypeScript Error Handling

interface ApiError {
  success: false;
  error: string;
  details?: string;
  deploymentId?: string;
}
 
class DigifiApiError extends Error {
  constructor(
    message: string,
    public statusCode: number,
    public details?: string,
    public deploymentId?: string
  ) {
    super(message);
    this.name = 'DigifiApiError';
  }
}
 
const deployToken = async (name: string, symbol: string) => {
  const response = await fetch('https://api.digifi.fun/deployToken', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({ name, symbol, chain_id: '8453', apiKey })
  });
  
  if (!response.ok) {
    const error: ApiError = await response.json();
    throw new DigifiApiError(
      error.error,
      response.status,
      error.details,
      error.deploymentId
    );
  }
  
  return await response.json();
};
 
// Usage
try {
  const result = await deployToken('MyToken', 'MTK');
} catch (error) {
  if (error instanceof DigifiApiError) {
    console.error(`API Error (${error.statusCode}): ${error.message}`);
    if (error.deploymentId) {
      console.error(`Deployment ID: ${error.deploymentId}`);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}

Best Practices

1. Always Check Success Field

const response = await deployToken('MyToken', 'MTK');
 
if (response.success) {
  // Handle success
  console.log('Token deployed:', response.data.tokenAddress);
} else {
  // Handle failure
  console.error('Deployment failed:', response.error);
}

2. Log Deployment IDs

try {
  const result = await deployToken('MyToken', 'MTK');
  console.log('Deployment ID:', result.deploymentId);
} catch (error) {
  const deploymentId = error.response?.data?.deploymentId;
  console.error('Failed deployment ID:', deploymentId);
  // Save for support inquiry
}

3. Implement Timeout

const deployWithTimeout = async (name, symbol, timeoutMs = 120000) => {
  const timeoutPromise = new Promise((_, reject) => 
    setTimeout(() => reject(new Error('Request timeout')), timeoutMs)
  );
  
  const deployPromise = deployToken(name, symbol);
  
  return Promise.race([deployPromise, timeoutPromise]);
};

4. Monitor Rate Limits

let lastRequestTime = 0;
const MIN_REQUEST_INTERVAL = 60000; // 1 minute
 
const deployWithRateLimitCheck = async (name, symbol) => {
  const now = Date.now();
  const timeSinceLastRequest = now - lastRequestTime;
  
  if (timeSinceLastRequest < MIN_REQUEST_INTERVAL) {
    const waitTime = MIN_REQUEST_INTERVAL - timeSinceLastRequest;
    console.log(`Waiting ${waitTime}ms to avoid rate limit...`);
    await new Promise(resolve => setTimeout(resolve, waitTime));
  }
  
  lastRequestTime = Date.now();
  return await deployToken(name, symbol);
};

5. User-Friendly Error Messages

const getUserFriendlyError = (error) => {
  const status = error.response?.status;
  
  switch (status) {
    case 400:
      return 'Invalid token details. Please check your input.';
    case 401:
      return 'Authentication failed. Please check your API key.';
    case 429:
      return 'Too many requests. Please wait a minute and try again.';
    case 500:
      return 'Deployment failed. Please try again or contact support.';
    default:
      return 'An unexpected error occurred. Please try again.';
  }
};
 
// Usage in UI
try {
  await deployToken('MyToken', 'MTK');
  showSuccessMessage('Token deployed successfully!');
} catch (error) {
  showErrorMessage(getUserFriendlyError(error));
}

Debugging Tips

Enable Verbose Logging

const DEBUG = process.env.DEBUG === 'true';
 
const debugLog = (...args) => {
  if (DEBUG) {
    console.log('[DEBUG]', ...args);
  }
};
 
const deployToken = async (name, symbol) => {
  debugLog('Starting deployment:', { name, symbol });
  
  try {
    const response = await fetch(url, options);
    debugLog('Response status:', response.status);
    
    const data = await response.json();
    debugLog('Response data:', data);
    
    return data;
  } catch (error) {
    debugLog('Error occurred:', error);
    throw error;
  }
};

Capture Request/Response

const logApiCall = async (url, options) => {
  console.log('Request:', {
    url,
    method: options.method,
    headers: { ...options.headers, Authorization: '[REDACTED]' },
    body: JSON.parse(options.body)
  });
  
  const response = await fetch(url, options);
  const data = await response.json();
  
  console.log('Response:', {
    status: response.status,
    data: { ...data, apiKey: data.apiKey ? '[REDACTED]' : undefined }
  });
  
  return data;
};

Getting Help

When contacting support, include:

  1. Deployment ID (if available)
  2. Error message and status code
  3. Request parameters (without API key)
  4. Timestamp of the request
  5. Steps to reproduce

Contact: digifievm999@gmail.com


Next: Code Examples - Ready-to-use implementations