Skip to content

Error Handling

Comprehensive guide to API error codes and handling strategies.

Overview

The Inspira API uses standard HTTP status codes and detailed error responses to help you handle errors gracefully. All error responses follow a consistent format for easy parsing and handling.

Error Response Format

Standard Error Response

json
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The provided API key is invalid or has been revoked",
    "field": "authorization",
    "details": {
      "keyFormat": "invalid",
      "suggestion": "Check your API key format and ensure it starts with 'inspira_'"
    }
  },
  "timestamp": "2025-01-06T12:00:00.000Z",
  "requestId": "req_123456789"
}

Error Response Fields

FieldTypeDescription
successbooleanAlways false for errors
error.codestringMachine-readable error code
error.messagestringHuman-readable error description
error.fieldstringField that caused the error (if applicable)
error.detailsobjectAdditional error context
timestampstringISO 8601 timestamp
requestIdstringUnique request identifier for support

HTTP Status Codes

Success Codes (2xx)

CodeNameDescription
200OKRequest succeeded
201CreatedResource created successfully
202AcceptedRequest accepted for processing
204No ContentRequest succeeded with no response body

Client Error Codes (4xx)

CodeNameCommon Causes
400Bad RequestInvalid request format, missing parameters
401UnauthorizedMissing or invalid API key
402Payment RequiredInsufficient credits
403ForbiddenAccess denied to resource
404Not FoundEndpoint or resource doesn't exist
405Method Not AllowedWrong HTTP method
409ConflictResource conflict (duplicate)
413Payload Too LargeRequest body exceeds limits
422Unprocessable EntityValid format but semantic errors
429Too Many RequestsRate limit exceeded

Server Error Codes (5xx)

CodeNameDescription
500Internal Server ErrorUnexpected server error
502Bad GatewayUpstream service error
503Service UnavailableTemporary maintenance/overload
504Gateway TimeoutRequest processing timeout

Common Error Codes

Authentication Errors

INVALID_API_KEY

json
{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The provided API key is invalid or has been revoked",
    "details": {
      "keyFormat": "invalid"
    }
  }
}

MISSING_API_KEY

json
{
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key is required for this endpoint",
    "details": {
      "header": "Authorization",
      "format": "Bearer inspira_your_api_key"
    }
  }
}

EXPIRED_API_KEY

json
{
  "error": {
    "code": "EXPIRED_API_KEY",
    "message": "This API key has expired",
    "details": {
      "expiredAt": "2024-12-31T23:59:59.000Z"
    }
  }
}

Credit Errors

INSUFFICIENT_CREDITS

json
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credits for this operation",
    "details": {
      "required": 10,
      "available": 5.5,
      "shortfall": 4.5,
      "purchaseUrl": "https://app.inspirahub.net/developer?tab=credits"
    }
  }
}

CREDIT_LIMIT_EXCEEDED

json
{
  "error": {
    "code": "CREDIT_LIMIT_EXCEEDED",
    "message": "Monthly credit limit exceeded",
    "details": {
      "limit": 10000,
      "used": 10050,
      "resetDate": "2025-02-01T00:00:00.000Z"
    }
  }
}

Validation Errors

INVALID_PARAMETER

json
{
  "error": {
    "code": "INVALID_PARAMETER",
    "message": "Invalid parameter value",
    "field": "size",
    "details": {
      "provided": "2048x2048",
      "allowed": ["512x512", "1024x1024"],
      "reason": "Size not supported"
    }
  }
}

MISSING_PARAMETER

json
{
  "error": {
    "code": "MISSING_PARAMETER",
    "message": "Required parameter is missing",
    "field": "prompt",
    "details": {
      "type": "string",
      "required": true
    }
  }
}

VALIDATION_ERROR

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": {
      "errors": [
        {
          "field": "temperature",
          "message": "Must be between 0 and 1",
          "provided": 2.5
        },
        {
          "field": "maxTokens",
          "message": "Must be a positive integer",
          "provided": -100
        }
      ]
    }
  }
}

Rate Limit Errors

RATE_LIMIT_EXCEEDED

json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "details": {
      "limit": 60,
      "window": "1 minute",
      "retryAfter": 45,
      "resetAt": "2025-01-06T12:01:00.000Z"
    }
  }
}

Service Errors

SERVICE_UNAVAILABLE

json
{
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "The AI service is temporarily unavailable",
    "details": {
      "service": "image-generation",
      "reason": "High load",
      "estimatedRecovery": "2025-01-06T12:30:00.000Z"
    }
  }
}

UPSTREAM_ERROR

json
{
  "error": {
    "code": "UPSTREAM_ERROR",
    "message": "Error from AI provider",
    "details": {
      "provider": "openai",
      "originalError": "Model overloaded"
    }
  }
}

Error Handling Best Practices

1. Comprehensive Error Handling

javascript
async function makeApiRequest(endpoint, data) {
  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });
    
    const result = await response.json();
    
    if (!response.ok) {
      // Handle different error types
      switch (result.error?.code) {
        case 'INSUFFICIENT_CREDITS':
          throw new InsufficientCreditsError(result.error);
          
        case 'RATE_LIMIT_EXCEEDED':
          throw new RateLimitError(result.error);
          
        case 'INVALID_PARAMETER':
          throw new ValidationError(result.error);
          
        default:
          throw new ApiError(result.error);
      }
    }
    
    return result;
    
  } catch (error) {
    // Handle network errors
    if (error instanceof TypeError && error.message === 'Failed to fetch') {
      throw new NetworkError('Unable to connect to API');
    }
    
    // Re-throw API errors
    throw error;
  }
}

2. Custom Error Classes

javascript
class ApiError extends Error {
  constructor(error) {
    super(error.message);
    this.name = 'ApiError';
    this.code = error.code;
    this.details = error.details;
    this.requestId = error.requestId;
  }
}

class InsufficientCreditsError extends ApiError {
  constructor(error) {
    super(error);
    this.name = 'InsufficientCreditsError';
    this.required = error.details.required;
    this.available = error.details.available;
  }
}

class RateLimitError extends ApiError {
  constructor(error) {
    super(error);
    this.name = 'RateLimitError';
    this.retryAfter = error.details.retryAfter;
    this.resetAt = new Date(error.details.resetAt);
  }
}

class ValidationError extends ApiError {
  constructor(error) {
    super(error);
    this.name = 'ValidationError';
    this.field = error.field;
    this.validationErrors = error.details.errors || [];
  }
}

3. Retry Logic

javascript
async function retryableRequest(fn, options = {}) {
  const {
    maxRetries = 3,
    retryDelay = 1000,
    exponentialBackoff = true,
    retryableErrors = ['RATE_LIMIT_EXCEEDED', 'SERVICE_UNAVAILABLE']
  } = options;
  
  let lastError;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      
      // Check if error is retryable
      if (!retryableErrors.includes(error.code)) {
        throw error;
      }
      
      // Calculate delay
      let delay = retryDelay;
      if (exponentialBackoff) {
        delay = retryDelay * Math.pow(2, attempt);
      }
      
      // Use retry-after header if available
      if (error.retryAfter) {
        delay = error.retryAfter * 1000;
      }
      
      console.log(`Retrying after ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  
  throw lastError;
}

// Usage
const result = await retryableRequest(() => 
  makeApiRequest('/api/generate-image', data)
);

4. User-Friendly Error Messages

javascript
function getUserMessage(error) {
  const messages = {
    'INSUFFICIENT_CREDITS': 'You need more credits to complete this action. Would you like to purchase more?',
    'RATE_LIMIT_EXCEEDED': 'You\'re making requests too quickly. Please wait a moment and try again.',
    'INVALID_API_KEY': 'Your API key appears to be invalid. Please check your settings.',
    'SERVICE_UNAVAILABLE': 'Our service is temporarily unavailable. Please try again in a few minutes.',
    'INVALID_PARAMETER': `Invalid ${error.field}: ${error.message}`,
    'NETWORK_ERROR': 'Unable to connect to the server. Please check your internet connection.'
  };
  
  return messages[error.code] || 'An unexpected error occurred. Please try again.';
}

5. Error Logging

javascript
class ErrorLogger {
  log(error, context = {}) {
    const errorLog = {
      timestamp: new Date().toISOString(),
      code: error.code,
      message: error.message,
      details: error.details,
      requestId: error.requestId,
      context: {
        endpoint: context.endpoint,
        userId: context.userId,
        ...context
      },
      stack: error.stack
    };
    
    // Log to console in development
    if (process.env.NODE_ENV === 'development') {
      console.error('API Error:', errorLog);
    }
    
    // Send to error tracking service
    if (window.Sentry) {
      window.Sentry.captureException(error, {
        extra: errorLog
      });
    }
    
    return errorLog;
  }
}

Error Recovery Strategies

Graceful Degradation

javascript
async function generateImageWithFallback(prompt) {
  try {
    // Try high quality first
    return await generateImage({ 
      prompt, 
      quality: 'high',
      size: '1024x1024' 
    });
  } catch (error) {
    if (error.code === 'INSUFFICIENT_CREDITS') {
      // Fall back to lower quality
      try {
        return await generateImage({ 
          prompt, 
          quality: 'standard',
          size: '512x512' 
        });
      } catch (fallbackError) {
        // Show error to user
        throw fallbackError;
      }
    }
    throw error;
  }
}

Circuit Breaker Pattern

javascript
class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.threshold = threshold;
    this.timeout = timeout;
    this.failures = 0;
    this.openedAt = null;
  }
  
  async execute(fn) {
    if (this.isOpen()) {
      throw new Error('Circuit breaker is open');
    }
    
    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }
  
  isOpen() {
    if (!this.openedAt) return false;
    return Date.now() - this.openedAt < this.timeout;
  }
  
  onSuccess() {
    this.failures = 0;
    this.openedAt = null;
  }
  
  onFailure() {
    this.failures++;
    if (this.failures >= this.threshold) {
      this.openedAt = Date.now();
    }
  }
}

Debugging Errors

Request ID Tracking

Always include the request ID when contacting support:

javascript
try {
  const result = await makeApiRequest(endpoint, data);
} catch (error) {
  console.error(`Request failed: ${error.message}`);
  console.error(`Request ID: ${error.requestId}`);
  console.error(`Please include request ID when contacting support`);
}

Debug Mode

Enable debug mode for detailed error information:

javascript
const response = await fetch(endpoint, {
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'X-Debug-Mode': 'true'
  }
});

Next Steps

Revolutionizing Education with AI and Web3