Errors

Complete guide to error handling and troubleshooting API issues.

Errors

Understanding and properly handling errors is crucial for building robust integrations with LoomAPI. This guide covers our error response format, common error codes, and best practices for error handling.

Error Response Format

All errors follow a consistent JSON structure:

{
  "request_id": "req_1234567890abcdef",
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {
      "field": "additional_context",
      "value": "specific_information"
    }
  }
}

Response Fields

  • request_id: Unique identifier for the request (use this when contacting support)
  • error.code: Machine-readable error code
  • error.message: Human-readable description
  • error.details: Additional context (optional)

HTTP Status Codes

We use standard HTTP status codes:

  • 400 Bad Request: Invalid request parameters
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Insufficient permissions
  • 404 Not Found: Resource not found
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Server error
  • 503 Service Unavailable: Service temporarily unavailable

Common Error Codes

Authentication Errors

AUTH_INVALID_KEY

Status: 401 Description: The provided API key is invalid, expired, or malformed.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "AUTH_INVALID_KEY",
    "message": "The provided API key is invalid or expired"
  }
}

Solutions:

  • Verify your API key in the dashboard
  • Check for typos in the Authorization header
  • Ensure the key hasn't expired

AUTH_MISSING

Status: 401 Description: No authentication provided.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "AUTH_MISSING",
    "message": "Authentication required"
  }
}

Document Errors

DOCUMENT_INVALID_FORMAT

Status: 400 Description: The document format is not supported.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "DOCUMENT_INVALID_FORMAT",
    "message": "Unsupported document format. Supported: jpeg, png, pdf",
    "details": {
      "provided_format": "gif",
      "supported_formats": ["jpeg", "png", "pdf"]
    }
  }
}

DOCUMENT_TOO_LARGE

Status: 400 Description: Document file size exceeds limits.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "DOCUMENT_TOO_LARGE",
    "message": "Document size exceeds 10MB limit",
    "details": {
      "max_size_mb": 10,
      "provided_size_mb": 15.2
    }
  }
}

DOCUMENT_QUALITY_LOW

Status: 400 Description: Document image quality is insufficient for processing.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "DOCUMENT_QUALITY_LOW",
    "message": "Document quality too low for accurate processing",
    "details": {
      "issues": ["blurry", "low_resolution"],
      "min_resolution": "300x300"
    }
  }
}

Processing Errors

PROCESSING_TIMEOUT

Status: 500 Description: Document processing took too long.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "PROCESSING_TIMEOUT",
    "message": "Document processing timed out",
    "details": {
      "timeout_seconds": 30
    }
  }
}

VERIFICATION_FAILED

Status: 400 Description: Document verification failed.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "VERIFICATION_FAILED",
    "message": "Document verification failed",
    "details": {
      "reason": "document_expired",
      "confidence_score": 0.15
    }
  }
}

Rate Limiting

RATE_LIMIT_EXCEEDED

Status: 429 Description: Rate limit exceeded.

{
  "request_id": "req_1234567890",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 30 seconds.",
    "details": {
      "retry_after_seconds": 30,
      "limit": 100,
      "window_seconds": 60
    }
  }
}

Error Handling Best Practices

Implement Retry Logic

async function makeRequestWithRetry(url, options, maxRetries = 3) {
  let lastError

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options)

      if (response.ok) {
        return response
      }

      const errorData = await response.json()

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

      // Retry on server errors (5xx) and rate limits
      if (response.status >= 500 || response.status === 429) {
        lastError = new Error(`Server error: ${errorData.error.message}`)

        if (attempt < maxRetries) {
          const delay = calculateDelay(attempt, response.headers.get('X-RateLimit-Retry-After'))
          await new Promise(resolve => setTimeout(resolve, delay))
          continue
        }
      }

      throw new Error(`HTTP ${response.status}: ${errorData.error.message}`)
    } catch (error) {
      lastError = error

      if (attempt < maxRetries) {
        const delay = calculateDelay(attempt)
        await new Promise(resolve => setTimeout(resolve, delay))
        continue
      }
    }
  }

  throw lastError
}

function calculateDelay(attempt, retryAfter = null) {
  if (retryAfter) {
    return parseInt(retryAfter) * 1000
  }

  // Exponential backoff: 1s, 2s, 4s, etc.
  return Math.pow(2, attempt - 1) * 1000
}

Log Errors Appropriately

async function handleApiCall() {
  try {
    const response = await fetch('/api/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(documentData)
    })

    if (!response.ok) {
      const errorData = await response.json()

      // Log structured error for monitoring
      console.error('API Error', {
        requestId: errorData.request_id,
        code: errorData.error.code,
        message: errorData.error.message,
        status: response.status,
        timestamp: new Date().toISOString()
      })

      // Handle specific error types
      switch (errorData.error.code) {
        case 'RATE_LIMIT_EXCEEDED':
          // Show user-friendly message and retry
          showRateLimitMessage(errorData.error.details.retry_after_seconds)
          break
        case 'DOCUMENT_QUALITY_LOW':
          // Prompt user to retake photo
          showQualityError()
          break
        default:
          // Generic error handling
          showGenericError(errorData.error.message)
      }

      return
    }

    const result = await response.json()
    handleSuccess(result)

  } catch (networkError) {
    console.error('Network Error', networkError)
    showNetworkError()
  }
}

User-Friendly Error Messages

Map technical errors to user-friendly messages:

const errorMessages = {
  'AUTH_INVALID_KEY': 'Your session has expired. Please sign in again.',
  'DOCUMENT_QUALITY_LOW': 'Please take a clearer photo of your document.',
  'DOCUMENT_TOO_LARGE': 'Please choose a smaller file (max 10MB).',
  'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment and try again.',
  'PROCESSING_TIMEOUT': 'Verification is taking longer than expected. Please try again.',
  'VERIFICATION_FAILED': 'We couldn\'t verify this document. Please try with a different one.'
}

function getUserFriendlyMessage(errorCode) {
  return errorMessages[errorCode] || 'Something went wrong. Please try again.'
}

Monitoring and Debugging

Use Request IDs

Always include the request_id when contacting support:

Subject: Issue with request req_1234567890abcdef

Hi Support Team,

I'm getting a VERIFICATION_FAILED error for request req_1234567890abcdef.
The document appears valid but verification keeps failing.

Request details:
- Time: 2024-01-15 14:30:00 UTC
- Document type: passport
- Error: VERIFICATION_FAILED

Can you help investigate?

Thanks,
[Your Name]

Test with Different Documents

  • Try different document types
  • Test with high-quality images
  • Use our test mode for debugging

Check Your Integration

  • Verify authentication headers
  • Ensure correct Content-Type
  • Validate base64 encoding
  • Check file size limits

Getting Help

If you're still having issues:

  1. Check this documentation for common solutions
  2. Review your code against our examples
  3. Test with our API using different documents
  4. Contact support with your request ID

Email: support@loomapi.com Include your request ID and error details for faster resolution.