Platform Error Handling

Error Handling Reference

Common Error Responses

Understanding error responses is critical for building robust error handling and user messaging.

Note: All error response examples below are actual responses from the CLEAR API, captured from live testing. Your application will encounter these exact error formats.

Authentication Errors

401 Unauthorized - Invalid API Key

curl --request POST \
  --url https://verified.clearme.com/v1/verification_sessions \
  --header 'Authorization: Bearer invalid_api_key' \
  --header 'Content-Type: application/json' \
  --data '{
    "project_id": "proj_abc123",
    "redirect_url": "https://yourapp.com/callback"
  }'

Response (actual from CLEAR API):

{
  "error_type": "unauthenticated",
  "fields": [],
  "message": "Invalid authentication"
}

HTTP Status: 401

How to Handle:

  • Log the error with full context
  • Alert administrators (API key may be rotated or expired)
  • Return user-friendly message: "Unable to connect to verification service. Please contact support."
  • Check environment variables and credential storage

Validation Errors

400 Bad Request - Invalid Project ID

curl --request POST \
  --url https://verified.clearme.com/v1/verification_sessions \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "project_id": "proj_nonexistent",
    "redirect_url": "https://yourapp.com/callback"
  }'

Response (actual from CLEAR API):

{
  "error_type": "invalid_argument",
  "fields": [],
  "message": "The project_id does not exist or is archived."
}

HTTP Status: 400

How to Handle:

  • Verify project IDs in your configuration (environment variables or database)
  • Check that you're using the correct project ID (User Profile Matching vs Known User Key)
  • Ensure project hasn't been archived in CLEAR dashboard
  • Validate project ID format before API call

400 Bad Request - Missing Required User Profile Information

curl --request POST \
  --url https://verified.clearme.com/v1/verification_sessions \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "project_id": "proj_abc123",
    "redirect_url": "https://yourapp.com/callback",
    "user_profile_information": {
      "name": {
        "first_name": "Jane"
      }
    }
  }'

Response (actual from CLEAR API):

{
  "error_type": "invalid_argument",
  "fields": [],
  "message": "Traits for user profile matching do not match project configuration. Missing traits: {'last_name'}"
}

HTTP Status: 400

How to Handle:

  • Ensure all required UPM fields configured in your project are present
  • Common required fields: first_name, last_name
  • Validate employee data completeness before API call
  • Check project configuration in CLEAR dashboard for required traits

400 Bad Request - Extra/Unconfigured Traits

curl --request POST \
  --url https://verified.clearme.com/v1/verification_sessions \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "project_id": "proj_abc123",
    "redirect_url": "https://yourapp.com/callback",
    "user_profile_information": {
      "name": {
        "first_name": "Jane",
        "last_name": "Smith"
      },
      "dob": "1990-01-15"
    }
  }'

Response (actual from CLEAR API):

{
  "error_type": "invalid_argument",
  "fields": [],
  "message": "Traits for user profile matching do not match project configuration. Extra traits: {'dob'}"
}

HTTP Status: 400

How to Handle:

  • Only send traits (fields) that are configured in your CLEAR project
  • Check project configuration in CLEAR dashboard
  • Remove unconfigured fields from user_profile_information
  • Common configured traits: first_name, last_name (DOB is optional and must be enabled in project)

Session Retrieval Errors

404 Not Found - Invalid Session ID

curl --request GET \
  --url https://verified.clearme.com/v1/verification_sessions/vs_nonexistent \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response (actual from CLEAR API):

{
  "error_type": "not_found",
  "fields": [],
  "message": "Invalid verification_session.id"
}

HTTP Status: 404

How to Handle:

  • Verify session ID is correct (should start with verify_ not vs_)
  • Check that session hasn't expired (sessions typically expire after 10 days)
  • Ensure you're using the id field from the create session response
  • Log error with session ID for debugging

Rate Limiting

429 Too Many Requests

{
  "error": {
    "type": "rate_limit_error",
    "message": "Too many requests. Please retry after 60 seconds"
  }
}

How to Handle:

  • Implement exponential backoff
  • Cache session results to reduce API calls
  • Contact CLEAR if you need higher rate limits

Server Errors

500 Internal Server Error

{
  "error": {
    "type": "api_error",
    "message": "An internal error occurred. Please try again later"
  }
}

How to Handle:

  • Retry with exponential backoff (3 retries recommended)
  • Log error with full context (request ID, timestamp, parameters)
  • If persistent, contact CLEAR support

503 Service Unavailable

{
  "error": {
    "type": "api_error",
    "message": "Service temporarily unavailable. Please try again"
  }
}

How to Handle:

  • Retry after brief delay
  • Show user-friendly message
  • Monitor for extended outages

Error Handling Best Practices

1. Implement Retry Logic with Exponential Backoff

async function createSessionWithRetry(payload, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch('https://verified.clearme.com/v1/verification_sessions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      });
      
      const data = await response.json();
      
      if (!response.ok) {
        // Don't retry client errors (4xx)
        if (response.status >= 400 && response.status < 500) {
          throw new Error(data.error?.message || 'Client error');
        }
        
        // Retry server errors (5xx)
        if (attempt < maxRetries - 1) {
          const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }
      
      return data;
      
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
    }
  }
}

2. Log All Errors with Context

async function logError(error, context) {
  console.error('CLEAR API Error', {
    timestamp: new Date().toISOString(),
    errorType: error.type,
    message: error.message,
    statusCode: context.statusCode,
    endpoint: context.endpoint,
    employeeId: context.employeeId,
    sessionId: context.sessionId,
    requestId: context.requestId,
  });
  
  // Send to monitoring service (Sentry, Datadog, etc.)
  // monitoringService.captureError(error, context);
}

3. User-Friendly Error Messages

Map technical errors to user-friendly messages:

function getUserMessage(errorType) {
  const messages = {
    'authentication_error': 'Unable to connect to verification service. Please contact support.',
    'permission_error': 'Configuration error. Please contact your administrator.',
    'invalid_request_error': 'Invalid request. Please try again or contact support.',
    'rate_limit_error': 'Too many requests. Please wait a moment and try again.',
    'api_error': 'Service temporarily unavailable. Please try again in a few moments.',
  };
  
  return messages[errorType] || 'An unexpected error occurred. Please try again.';
}

4. Validation Before API Calls

function validateSessionPayload(payload) {
  const errors = [];
  
  if (!payload.project_id) {
    errors.push('project_id is required');
  }
  
  if (!payload.redirect_url) {
    errors.push('redirect_url is required');
  }
  
  if (payload.user_profile_information) {
    if (!payload.user_profile_information.name?.first_name) {
      errors.push('first_name is required for User Profile Matching');
    }
    if (!payload.user_profile_information.name?.last_name) {
      errors.push('last_name is required for User Profile Matching');
    }
    if (payload.user_profile_information.dob) {
      // Validate YYYY-MM-DD format
      if (!/^\d{4}-\d{2}-\d{2}$/.test(payload.user_profile_information.dob)) {
        errors.push('dob must be in YYYY-MM-DD format');
      }
    }
  }
  
  if (errors.length > 0) {
    throw new Error(`Validation failed: ${errors.join(', ')}`);
  }
}

5. Circuit Breaker Pattern (Advanced)

For high-volume applications, implement a circuit breaker to prevent cascading failures:

class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.failureCount = 0;
    this.threshold = threshold;
    this.timeout = timeout;
    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    this.nextAttempt = Date.now();
  }
  
  async execute(fn) {
    if (this.state === 'OPEN') {
      if (Date.now() < this.nextAttempt) {
        throw new Error('Circuit breaker is OPEN');
      }
      this.state = 'HALF_OPEN';
    }
    
    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }
  
  onSuccess() {
    this.failureCount = 0;
    this.state = 'CLOSED';
  }
  
  onFailure() {
    this.failureCount++;
    if (this.failureCount >= this.threshold) {
      this.state = 'OPEN';
      this.nextAttempt = Date.now() + this.timeout;
    }
  }
}

const clearApiCircuitBreaker = new CircuitBreaker();

async function createSessionWithCircuitBreaker(payload) {
  return await clearApiCircuitBreaker.execute(() => 
    createVerificationSession(payload)
  );
}


Did this page help you?