API Armor LogoAPI Armor

Error Handling

Learn how to handle errors and understand error responses from the API Shield API.

Overview

API Shield uses conventional HTTP status codes to indicate the success or failure of API requests. Errors are returned with descriptive error messages to help you diagnose and fix issues.

Error Response Format

All error responses follow a consistent JSON format:

{
  "error": "error_code",
  "message": "Human-readable error description"
}

Error Response Fields

FieldTypeDescription
errorstringMachine-readable error code for programmatic handling
messagestringHuman-readable error description
retry_afternumber(Optional) Seconds to wait before retrying (for rate limit errors)

HTTP Status Codes

Success Codes

200 OK

The request was successful and the response contains the requested data.

Client Error Codes

400 Bad Request

The request was invalid or cannot be served. Check the error message for details about what's wrong with the request.

Common causes:

  • Invalid email format
  • Missing required parameters
  • Malformed request
401 Unauthorized

Authentication failed. The API key is missing, invalid, or has been revoked.

Common causes:

  • Missing Authorization header
  • Invalid API key
  • Expired or revoked API key
403 Forbidden

The API key is valid but doesn't have permission to perform the requested action.

Common causes:

  • Account suspended
  • API key permissions insufficient
  • Subscription expired
404 Not Found

The requested endpoint does not exist.

Common causes:

  • Incorrect URL
  • Typo in endpoint path
429 Too Many Requests

Rate limit exceeded. Too many requests have been made in a given time period.

Response includes:

  • retry_after field indicating seconds to wait
  • X-RateLimit-Reset header with reset timestamp

Server Error Codes

500 Internal Server Error

An error occurred on the server. If this persists, contact support.

503 Service Unavailable

The service is temporarily unavailable. Typically due to maintenance or high load.

Error Types

Invalid Email

400 Bad Request
{
  "error": "invalid_email",
  "message": "The provided email address is not valid"
}

Cause: The email parameter is not a valid email format.

Solution: Validate email format before sending to the API.

function isValidEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

Missing Parameter

400 Bad Request
{
  "error": "missing_parameter",
  "message": "The 'email' parameter is required"
}

Cause: Required parameter is missing from the request.

Solution: Ensure all required parameters are included in your request.

Invalid API Key

401 Unauthorized
{
  "error": "invalid_api_key",
  "message": "The provided API key is not valid"
}

Cause: The API key in the Authorization header is invalid.

Solution:

  • Verify your API key is correct
  • Check for extra spaces or characters
  • Ensure you're using Bearer aa_abc123xyz789 format (API keys are prefixed with aa_)

API Key Revoked

401 Unauthorized
{
  "error": "api_key_revoked",
  "message": "This API key has been revoked"
}

Cause: The API key has been revoked in the dashboard.

Solution: Generate a new API key in your dashboard.

Rate Limit Exceeded

429 Too Many Requests
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded. Please try again later.",
  "retry_after": 60
}

Cause: Too many requests in the current time window.

Solution:

  • Implement rate limiting in your application
  • Use exponential backoff for retries
  • Cache results to reduce API calls
  • Upgrade your plan for higher limits

Internal Server Error

500 Internal Server Error
{
  "error": "internal_server_error",
  "message": "An unexpected error occurred. Please try again."
}

Cause: An error occurred on our servers.

Solution:

  • Retry the request after a short delay
  • If the problem persists, contact support

Service Unavailable

503 Service Unavailable
{
  "error": "service_unavailable",
  "message": "The service is temporarily unavailable"
}

Cause: The API is temporarily unavailable, usually due to maintenance.

Solution:

  • Retry with exponential backoff
  • Check our status page for maintenance schedules

Error Handling Best Practices

1. Always Check Status Codes

const response = await fetch(
  'https://bifrost.api-armor.com/v1/check?email=test@example.com',
  {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }
);

if (!response.ok) {
  const error = await response.json();
  console.error('API Error:', error);
  throw new Error(error.message);
}

const data = await response.json();

2. Implement Retry Logic with Exponential Backoff

async function checkEmailWithRetry(email, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(
        `https://bifrost.api-armor.com/v1/check?email=${encodeURIComponent(email)}`,
        {
          headers: { 'Authorization': `Bearer ${API_KEY}` }
        }
      );

      if (response.ok) {
        return await response.json();
      }

      // Don't retry on client errors (4xx)
      if (response.status >= 400 && response.status < 500) {
        throw new Error(`Client error: ${response.status}`);
      }

      // Retry on server errors (5xx) with exponential backoff
      if (i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      throw new Error(`Server error: ${response.status}`);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
}

3. Handle Rate Limits Gracefully

async function checkEmailWithRateLimit(email) {
  const response = await fetch(
    `https://bifrost.api-armor.com/v1/check?email=${encodeURIComponent(email)}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  if (response.status === 429) {
    const error = await response.json();
    const retryAfter = error.retry_after || 60;
    
    console.log(`Rate limited. Retrying after ${retryAfter} seconds`);
    
    // Wait and retry
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    return checkEmailWithRateLimit(email);
  }

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  return await response.json();
}

4. Fail Open for Better UX

When the API is unavailable, consider allowing the operation to proceed rather than blocking users:

def check_email_safely(email):
    """Check email with graceful degradation"""
    try:
        response = requests.get(
            'https://bifrost.api-armor.com/v1/check',
            params={'email': email},
            headers={'Authorization': f'Bearer {API_KEY}'},
            timeout=5  # Set a reasonable timeout
        )
        
        if response.status_code == 200:
            data = response.json()
            return data['is_disposable']
        
        # For 5xx errors, fail open
        if response.status_code >= 500:
            logger.warning(f"API unavailable: {response.status_code}")
            return False  # Assume not disposable
        
        # For 4xx errors, fail closed or raise
        response.raise_for_status()
        
    except requests.exceptions.Timeout:
        logger.warning("API timeout - failing open")
        return False  # Fail open on timeout
    
    except Exception as e:
        logger.error(f"Email check failed: {e}")
        return False  # Fail open on unexpected errors

5. Log Errors for Debugging

async function checkEmail(email) {
  try {
    const response = await fetch(
      `https://bifrost.api-armor.com/v1/check?email=${encodeURIComponent(email)}`,
      {
        headers: { 'Authorization': `Bearer ${API_KEY}` }
      }
    );

    if (!response.ok) {
      const error = await response.json();
      
      // Log error details
      console.error('API Error:', {
        status: response.status,
        error: error.error,
        message: error.message,
        email: email,
        timestamp: new Date().toISOString()
      });
      
      // Send to error tracking service
      // trackError(error);
      
      throw error;
    }

    return await response.json();
  } catch (error) {
    // Log and re-throw
    console.error('Request failed:', error);
    throw error;
  }
}

6. Provide User-Friendly Error Messages

function getUserFriendlyError(error) {
  const errorMessages = {
    'invalid_email': 'Please enter a valid email address.',
    'rate_limit_exceeded': 'Too many attempts. Please try again in a moment.',
    'invalid_api_key': 'Service configuration error. Please contact support.',
    'service_unavailable': 'Service temporarily unavailable. Please try again later.'
  };

  return errorMessages[error.error] || 'An unexpected error occurred. Please try again.';
}

// Usage in UI
try {
  await checkEmail(email);
} catch (error) {
  const userMessage = getUserFriendlyError(error);
  showErrorToUser(userMessage);
}

Testing Error Handling

You can test your error handling by simulating different error conditions:

// Test with invalid email
await checkEmail('not-an-email');

// Test with missing API key
await fetch('https://bifrost.api-armor.com/v1/check?email=test@example.com');

// Test with invalid API key
await fetch('https://bifrost.api-armor.com/v1/check?email=test@example.com', {
  headers: { 'Authorization': 'Bearer invalid_key' }
});

Getting Help

If you encounter persistent errors:

  1. Check our status page for service issues
  2. Review this documentation for common solutions
  3. Contact support with:
    • Error message and status code
    • Request details (without sensitive data)
    • Timestamp of the error
    • Your API key prefix (first 8 characters only)

Next Steps

On this page