Skip to main content

Overview

This guide covers essential best practices for integrating and using the FAD SDK effectively. Following these recommendations will help you build robust, maintainable, and user-friendly applications.

SDK Initialization

Single Instance Pattern

Always create a single SDK instance per process flow to avoid conflicts and resource issues.
async function processLiveness() {
  const FAD_SDK = new FadSDK(TOKEN, options);
  try {
    const response = await FAD_SDK.startFacetec(CREDENTIALS, CONFIG);
    return response;
  } finally {
    FAD_SDK.end();
  }
}

Environment Configuration

Use appropriate environments based on your deployment stage:
// Development/Testing
const options = {
  environment: FadSDK.getFadEnvironments().UATHA,
};

// Production
const options = {
  environment: FadSDK.getFadEnvironments().PRODUCTION,
};
Store environment configuration in environment variables or configuration files, never hardcode production credentials in your source code.

Error Handling

Comprehensive Error Catching

Always implement comprehensive error handling with specific error code checks:
try {
  const response = await FAD_SDK.startFacetec(CREDENTIALS, CONFIGURATION);
  // Process success
  handleSuccess(response);
  
} catch (ex) {
  console.error('SDK Error:', ex);
  
  // Handle specific error codes
  switch (ex.code) {
    case FadSDK.Errors.Facetec.Session.CAMERA_NOT_RUNNING:
      showUserMessage('Camera not available. Please check camera permissions.');
      break;
      
    case FadSDK.Errors.Facetec.Session.INITIALIZATION_NOT_COMPLETED:
      showUserMessage('Initialization failed. Retrying...');
      retryInitialization();
      break;
      
    case FadSDK.Errors.Facetec.Status.TIMEOUT:
      showUserMessage('Process timed out. Please try again.');
      break;
      
    case FadSDK.Errors.Facetec.Session.USER_CANCELLED:
      showUserMessage('Process cancelled by user.');
      break;
      
    default:
      showUserMessage('An unexpected error occurred. Please try again.');
      logErrorToService(ex);
  }
  
} finally {
  FAD_SDK.end();
}

Error Response Structure

Understand the error response structure:
interface ResponseError<T> {
  code: T;          // Error code specific to the module
  error: string;    // Human-readable error message
}
Different modules have different error codes. Always consult the module-specific documentation for complete error code lists.

User-Friendly Error Messages

if (ex.code === FadSDK.Errors.Regula.CAMERA_PERMISSION_DENIED) {
  showNotification({
    title: 'Camera Access Required',
    message: 'Please enable camera access in your browser settings to capture documents.',
    type: 'warning',
    actions: [{ label: 'Learn How', onClick: showCameraHelp }]
  });
}

Module Lifecycle Management

Always Use Finally Block

The end() method must always be called to cleanup resources:
const FAD_SDK = new FadSDK(TOKEN, options);

try {
  // Module operations
  const response = await FAD_SDK.startRegula(...);
  
} catch (ex) {
  // Error handling
  handleError(ex);
  
} finally {
  // CRITICAL: Always cleanup
  FAD_SDK.end();
}
Failing to call FAD_SDK.end() can lead to memory leaks, camera/resource locks, and degraded performance.

Sequential Module Execution

When running multiple modules sequentially, ensure proper cleanup between them:
async function runMultipleModules() {
  // First module: Document capture
  let documentData;
  {
    const FAD_SDK = new FadSDK(TOKEN, options);
    try {
      documentData = await FAD_SDK.startRegula(CREDENTIALS, TYPE, true, true, CONFIG);
    } finally {
      FAD_SDK.end();
    }
  }

  // Second module: Liveness check
  let livenessData;
  {
    const FAD_SDK = new FadSDK(TOKEN, options);
    try {
      livenessData = await FAD_SDK.startFacetec(CREDENTIALS, CONFIG);
    } finally {
      FAD_SDK.end();
    }
  }

  return { documentData, livenessData };
}

Handle Module Close Events

Always check if the user closed the module:
const response = await FAD_SDK.startRegula(...);

if (response.event === FadSDK.Constants.EventModule.MODULE_CLOSED) {
  console.log('User closed the module');
  // Don't treat this as an error - the user intentionally cancelled
  return null;
}

// Process normal response
processResponse(response.data);

Resource Management

Camera Permissions

Request camera permissions before initializing camera-based modules:
async function checkCameraPermission() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    // Permission granted, stop the stream
    stream.getTracks().forEach(track => track.stop());
    return true;
  } catch (err) {
    console.error('Camera permission denied:', err);
    return false;
  }
}

async function startCapture() {
  const hasPermission = await checkCameraPermission();
  
  if (!hasPermission) {
    showCameraPermissionHelp();
    return;
  }
  
  // Proceed with SDK initialization
  const FAD_SDK = new FadSDK(TOKEN, options);
  // ...
}

Memory Management for Large Files

Handle video and image data efficiently:
async function processSignature() {
  const FAD_SDK = new FadSDK(TOKEN, options);
  
  try {
    const response = await FAD_SDK.startSignature(CONFIG);
    
    // Create object URLs for display
    const faceVideoUrl = URL.createObjectURL(response.data.videoFace);
    const signatureVideoUrl = URL.createObjectURL(response.data.videoSignature);
    
    // Use the URLs
    displayVideos(faceVideoUrl, signatureVideoUrl);
    
    // Clean up object URLs when done to free memory
    setTimeout(() => {
      URL.revokeObjectURL(faceVideoUrl);
      URL.revokeObjectURL(signatureVideoUrl);
    }, 60000); // Revoke after 1 minute
    
  } finally {
    FAD_SDK.end();
  }
}
Use URL.revokeObjectURL() to free memory when object URLs are no longer needed.

Configuration Management

Separate Configuration Files

Store credentials and configuration separately from business logic:
// constants.ts - Configuration only
export const TOKEN = process.env.FAD_SDK_TOKEN || '';

export const CREDENTIALS = {
  // Module-specific credentials
};

export const CONFIGURATION = {
  // Module-specific configuration
};

Environment-Based Configuration

const getSDKOptions = () => {
  const isDevelopment = process.env.NODE_ENV === 'development';
  
  return {
    environment: isDevelopment 
      ? FadSDK.getFadEnvironments().UATHA
      : FadSDK.getFadEnvironments().PRODUCTION,
  };
};

const FAD_SDK = new FadSDK(TOKEN, getSDKOptions());

User Experience

Loading States

Provide clear feedback during SDK operations:
async function captureDocument() {
  const loadingOverlay = showLoading('Initializing camera...');
  const FAD_SDK = new FadSDK(TOKEN, options);
  
  try {
    loadingOverlay.updateMessage('Capture your document...');
    const response = await FAD_SDK.startRegula(CREDENTIALS, TYPE, true, true, CONFIG);
    
    loadingOverlay.updateMessage('Processing document...');
    await processDocument(response.data);
    
    loadingOverlay.hide();
    showSuccess('Document captured successfully!');
    
  } catch (ex) {
    loadingOverlay.hide();
    handleError(ex);
  } finally {
    FAD_SDK.end();
  }
}

Retry Logic

Implement smart retry logic for transient errors:
async function startModuleWithRetry(
  maxRetries = 3,
  retryDelay = 1000
): Promise<any> {
  let lastError;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const FAD_SDK = new FadSDK(TOKEN, options);
    
    try {
      const response = await FAD_SDK.startFacetec(CREDENTIALS, CONFIG);
      return response;
      
    } catch (ex) {
      lastError = ex;
      
      // Don't retry user cancellations
      if (ex.code === FadSDK.Errors.Facetec.Session.USER_CANCELLED) {
        throw ex;
      }
      
      // Don't retry permission errors
      if (ex.code === FadSDK.Errors.Facetec.Session.CAMERA_NOT_RUNNING) {
        throw ex;
      }
      
      console.log(`Attempt ${attempt} failed, retrying...`);
      await new Promise(resolve => setTimeout(resolve, retryDelay));
      
    } finally {
      FAD_SDK.end();
    }
  }
  
  throw lastError;
}

Progress Indicators

class SDKProcess {
  private progressCallback: (progress: number, message: string) => void;
  
  constructor(progressCallback) {
    this.progressCallback = progressCallback;
  }
  
  async run() {
    this.progressCallback(0, 'Initializing...');
    const FAD_SDK = new FadSDK(TOKEN, options);
    
    try {
      this.progressCallback(30, 'Starting camera...');
      const response = await FAD_SDK.startFacetec(CREDENTIALS, CONFIG);
      
      this.progressCallback(70, 'Processing results...');
      const processed = await this.processResponse(response);
      
      this.progressCallback(100, 'Complete!');
      return processed;
      
    } finally {
      FAD_SDK.end();
    }
  }
}

Performance Optimization

Lazy Loading

Load the SDK only when needed:
let FadSDK;

async function loadSDK() {
  if (!FadSDK) {
    FadSDK = (await import('@fad-producto/fad-sdk')).default;
  }
  return FadSDK;
}

async function startProcess() {
  const SDK = await loadSDK();
  const FAD_SDK = new SDK(TOKEN, options);
  // ...
}

Code Splitting

Split module implementations into separate chunks:
// liveness.ts
export async function runLivenessCheck() {
  const FadSDK = (await import('@fad-producto/fad-sdk')).default;
  // Implementation
}

// document.ts  
export async function captureDocument() {
  const FadSDK = (await import('@fad-producto/fad-sdk')).default;
  // Implementation
}

// app.ts
import { runLivenessCheck } from './liveness';
import { captureDocument } from './document';

Security Best Practices

Token Management

Never expose authentication tokens in client-side code or version control systems.
// Good: Fetch token from your backend
async function getSDKToken() {
  const response = await fetch('/api/sdk-token', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${userAuthToken}` }
  });
  const { token } = await response.json();
  return token;
}

const token = await getSDKToken();
const FAD_SDK = new FadSDK(token, options);

Data Transmission

Securely transmit captured data to your backend:
async function submitCapturedData(sdkResponse) {
  // Send data securely to your backend
  const response = await fetch('/api/verify', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${userAuthToken}`
    },
    body: JSON.stringify({
      data: sdkResponse.data,
      timestamp: Date.now(),
      sessionId: getSessionId()
    })
  });
  
  return response.json();
}

Testing

Mock SDK for Unit Tests

// __mocks__/@fad-producto/fad-sdk.ts
export default class MockFadSDK {
  constructor(token, options) {}
  
  async startFacetec(credentials, config) {
    return {
      data: {
        auditTrail: ['mock-image-data'],
        lowQualityAuditTrail: ['mock-low-quality-data'],
        faceScan: 'mock-face-scan'
      }
    };
  }
  
  end() {}
  
  static getFadEnvironments() {
    return { UATHA: 'UATHA', PRODUCTION: 'PRODUCTION' };
  }
}

Integration Testing

describe('FAD SDK Integration', () => {
  it('should handle successful liveness check', async () => {
    const response = await runLivenessCheck();
    expect(response.data).toBeDefined();
    expect(response.data.auditTrail).toHaveLength(1);
  });
  
  it('should handle camera permission error', async () => {
    // Mock permission denial
    await expect(runLivenessCheck()).rejects.toMatchObject({
      code: FadSDK.Errors.Facetec.Session.CAMERA_NOT_RUNNING
    });
  });
});

Logging and Monitoring

Structured Logging

const logger = {
  sdkEvent(event: string, data: any) {
    console.log('[FAD SDK]', event, data);
    // Send to your logging service
    analyticsService.track('sdk_event', { event, ...data });
  }
};

async function processModule() {
  logger.sdkEvent('module_start', { module: 'liveness' });
  
  const FAD_SDK = new FadSDK(TOKEN, options);
  
  try {
    const response = await FAD_SDK.startFacetec(CREDENTIALS, CONFIG);
    logger.sdkEvent('module_success', { module: 'liveness' });
    return response;
    
  } catch (ex) {
    logger.sdkEvent('module_error', { 
      module: 'liveness', 
      error: ex.code,
      message: ex.error 
    });
    throw ex;
    
  } finally {
    FAD_SDK.end();
    logger.sdkEvent('module_end', { module: 'liveness' });
  }
}

Next Steps

Troubleshooting

Solutions to common issues

NPM Integration

TypeScript/JavaScript integration

Vanilla JS Integration

Script tag integration

API Reference

Complete API documentation

Build docs developers (and LLMs) love