Vanilla JavaScript SDK

Lightweight JavaScript SDK that works in any browser environment

Installation

npm (Recommended)

Install the SDK using npm, the Node.js package manager. This is the recommended installation method for most projects.

bash
npm install @keverdjs/fraud-sdk

yarn

Alternatively, install using Yarn if you prefer it over npm.

bash
yarn add @keverdjs/fraud-sdk

CDN (Alternative)

For projects that don't use a package manager, you can include the SDK via a CDN. Add this script tag to your HTML:

html
<script src="https://cdn.keverd.com/sdk/v1/keverd-sdk.min.js"></script>

Note: When using the CDN, the SDK is available globally as window.Keverd. The CDN version is automatically minified and optimized for production use.

Quick Start

1. Import and Initialize

Import the SDK and initialize it with your API key. The SDK follows a singleton pattern, so you only need to initialize it once in your application. Initialization is synchronous and non-blocking, but you should call it early in your application lifecycle (e.g., in your main entry point or app initialization code).

Important: The endpoint must use HTTPS. The SDK will throw an error if you provide an HTTP URL. The default API endpoint is https://api.keverd.com.

javascript
import { Keverd } from '@keverdjs/fraud-sdk';

// Simple initialization with API key only
Keverd.init('your-api-key-here');

// Or with full configuration object
Keverd.init({
  apiKey: 'your-api-key-here',
  endpoint: 'https://api.keverd.com', // Optional: defaults to https://api.keverd.com
  userId: 'user-123', // Optional: user identifier
  debug: true, // Optional: enable debug logging (default: false)
});

Singleton Pattern: The SDK uses a singleton pattern. Subsequent calls to init() with different configurations will be ignored after the first initialization. If you need to reinitialize with a new configuration, call destroy() first.

Behavioral Collection: When initialized, the SDK automatically starts passive behavioral data collection (mouse movements, keyboard events, touch gestures). This collection is non-blocking and does not impact page performance.

2. Get Visitor Data

Call getVisitorData() to collect device information, behavioral data, and receive a risk assessment from the Keverd API. This method is asynchronous and returns a Promise that resolves to a FingerprintResponse object.

Performance: Data collection typically completes in under 50ms. The total time (including network request) is typically under 200ms (p99 latency). The method uses the browser's native fetch API with a default timeout of 30 seconds.

javascript
// Get visitor data and risk assessment
try {
  const result = await Keverd.getVisitorData();
  
  console.log('Risk Score:', result.risk_score); // 0-100
  console.log('Normalized Score:', result.score); // 0.0-1.0
  console.log('Action:', result.action); // 'allow' | 'soft_challenge' | 'hard_challenge' | 'block'
  console.log('Session ID:', result.session_id); // UUID
  console.log('Request ID:', result.requestId); // UUID (same as session_id)
  console.log('Reasons:', result.reason); // Array of risk reasons
  
  // Handle risk score
  if (result.risk_score >= 70) {
    // High risk - block or require additional verification
    handleHighRisk(result);
  } else if (result.risk_score >= 30) {
    // Medium risk - require MFA
    requireMFA(result);
  } else {
    // Low risk - proceed normally
    proceedNormally(result);
  }
} catch (error) {
  // Handle errors (see Error Handling section)
  console.error('Error getting visitor data:', error);
}

API Reference

Keverd

Main SDK class for fingerprint collection and risk assessment. The SDK is exported as a singleton instance, so you can use it directly without instantiating a new class.

init(config: string | SDKConfig): void

Initializes the SDK singleton instance. This method follows the singleton pattern, so subsequent calls with different configurations will be ignored after the first initialization. The SDK uses the browser's native APIs internally and starts passive behavioral data collection automatically.

Parameters:

  • config: Either a string (API key) or an SDKConfig object. If a string is provided, the SDK will use default values for all other options.

Returns: void

Thread Safety: Initialization is synchronous and safe to call from any thread. The SDK uses a singleton pattern with internal checks to prevent multiple initializations.

Throws: No exceptions are thrown. If initialization fails (e.g., invalid endpoint), errors will be logged to the console if debug is enabled, but the SDK will still attempt to function with default values.

Behavioral Collection: When initialized, the SDK automatically starts passive behavioral data collection (mouse movements, keyboard events, touch gestures). This collection is non-blocking and does not impact page performance.

getVisitorData(): Promise<FingerprintResponse>

Collects device information, behavioral data, and session information, then sends it to the Keverd API to receive a risk assessment. This is the main method for fraud detection. The method is asynchronous and returns a Promise that resolves to a FingerprintResponse object.

Parameters: None

Returns: Promise<FingerprintResponse> - A promise that resolves to a FingerprintResponse object containing the risk score, action recommendation, and session information.

Asynchronous: This method is asynchronous and must be called with await or using .then(). The method uses the browser's native fetch API for network requests.

Performance: Data collection typically completes in under 50ms. The total time (including network request) is typically under 200ms (p99 latency). Network timeouts are set to 30 seconds for connection, read, and write operations.

Error Handling: If an error occurs during data collection or API submission, the Promise will reject with an Error object. You should wrap calls in a try-catch block to handle errors gracefully. See the Error Handling section for more details.

Throws: Throws an Error if the SDK is not initialized (call init() first) or if the API request fails (network errors, invalid API key, server errors, etc.).

verifyLogin(userId?: string, metadata?: Record<string, any>): Promise<FingerprintResponse>

Use-case-specific method for login verification. Collects enhanced behavioral signals optimized for login scenarios (typing patterns, form interactions, copy-paste detection) and sends them to the Keverd API with use_case: "login".

Parameters:

  • userId (optional): User identifier for profile matching
  • metadata (optional): Additional metadata to include in the request

Returns: Promise<FingerprintResponse> - Same response format as getVisitorData()

verifyCheckout(amount?: number, currency?: string, metadata?: Record<string, any>): Promise<FingerprintResponse>

Use-case-specific method for checkout/payment verification. Optimized for detecting fraud during payment flows with enhanced form interaction and behavioral analysis.

Parameters:

  • amount (optional): Transaction amount
  • currency (optional): Currency code (e.g., "USD", "KES")
  • metadata (optional): Additional metadata

Returns: Promise<FingerprintResponse>

verifyRegistration(metadata?: Record<string, any>): Promise<FingerprintResponse>

Use-case-specific method for account registration verification. Detects bot signups and suspicious registration patterns.

Parameters:

  • metadata (optional): Additional metadata

Returns: Promise<FingerprintResponse>

verifyPasswordReset(metadata?: Record<string, any>): Promise<FingerprintResponse>

Use-case-specific method for password reset verification. High-risk use case requiring enhanced security checks.

Parameters:

  • metadata (optional): Additional metadata

Returns: Promise<FingerprintResponse>

verifyAccountChange(metadata?: Record<string, any>): Promise<FingerprintResponse>

Use-case-specific method for account modification verification (email change, phone change, etc.).

Parameters:

  • metadata (optional): Additional metadata

Returns: Promise<FingerprintResponse>

createTransactionID(metadata?: TransactionMetadata): Promise<string>

Legacy method for backward compatibility. This method internally calls getVisitorData() and returns the session_id from the response. For new implementations, use getVisitorData() instead, as it provides more comprehensive information including the risk score.

Parameters:

  • metadata (optional): Transaction metadata object. Currently not used by the SDK, but included for backward compatibility with older API versions.

Returns: Promise<string> - A promise that resolves to the session ID (UUID format).

Note: This method is deprecated. Use getVisitorData() instead to get both the session ID and risk assessment.

destroy(): void

Destroys the SDK instance and stops all data collection. This method stops behavioral data collection, clears the internal configuration, and resets the initialization state. After calling this method, you must call init() again before using the SDK.

Parameters: None

Returns: void

Use Cases: Call this method when you want to stop all SDK activity, such as when a user logs out, when switching to a different API key, or when cleaning up resources. After destroying, you can reinitialize with a new configuration.

SDKConfig

Configuration object for SDK initialization. All parameters are optional except apiKey.

The SDKConfig object is used to configure the SDK during initialization. You can also pass a string (API key) directly to init(), which will use default values for all other options.

ParameterTypeRequiredDefaultDescription
apiKeystringYesAPI key for authenticating requests to the Keverd API. Obtain your API key from the API Keys page in the dashboard. The API key is sent in the request header as x-keverd-key. Keep your API key secure and never commit it to version control. Consider using environment variables or a secure configuration management system.
endpointstringNo'https://api.keverd.com'Base URL for the fingerprint API endpoint. Must start with "https://" (HTTP is not allowed for security). The default production endpoint is https://api.keverd.com. Only change this if you're using a custom endpoint or testing environment.
userIdstringNoundefinedUser identifier (string). This is not hashed and is sent as-is to the API. If not provided or empty, the backend will auto-generate an identifier from the device fingerprint. Use this to associate fingerprint requests with specific users in your system. This is useful for tracking user behavior across sessions and devices.
debugbooleanNofalseEnable debug logging. When true, the SDK will log debug information to the browser console, including initialization status, API requests, and errors. Set to true during development and false in production to avoid exposing sensitive information in the console.

FingerprintResponse

The response object returned by getVisitorData(). Contains the risk assessment, action recommendation, and session information.

FingerprintResponse Structure

typescript
interface FingerprintResponse {
  risk_score: number;        // 0-100 risk score (integer)
  score: number;             // 0.0-1.0 normalized score (float)
  action: 'allow' | 'soft_challenge' | 'hard_challenge' | 'block';
  reason: string[];          // Array of risk reasons
  session_id: string;         // UUID session identifier
  requestId: string;         // UUID request identifier (same as session_id)
  sim_swap_engine?: {        // SIM swap detection (null for web SDKs)
    userId?: string;
    risk: number;
    flags: {
      sim_changed?: boolean;
      device_changed?: boolean;
      behavior_anomaly?: boolean;
      time_anomaly?: boolean;
      velocity_anomaly?: boolean;
    };
    updatedProfile?: Record<string, unknown>;
  };
}

risk_score: Risk score as an integer from 0 (lowest risk) to 100 (highest risk). This is the primary score used for risk assessment. Use this score to make security decisions in your application.

score: Normalized risk score as a float between 0.0 (lowest risk) and 1.0 (highest risk). This is equal to risk_score / 100. Use this for calculations that require a normalized value.

action: Recommended action based on the risk score. Possible values: 'allow' (low risk, proceed normally), 'soft_challenge' (medium risk, require additional verification like MFA), 'hard_challenge' (high risk, require strong verification), or 'block' (very high risk, deny access).

reason: Array of strings explaining why the risk score was assigned. Each string describes a specific risk factor (e.g., "Device fingerprint mismatch", "Unusual behavioral patterns", "High velocity transactions"). Use this to provide context to users or for debugging purposes.

session_id: Unique session identifier in UUID format. This identifier is generated client-side and is consistent across requests within the same browser session. Use this to track and correlate events, debug issues, or reference the request in support tickets.

requestId: Unique request identifier in UUID format. This is the same as session_id and is included for backward compatibility. Use this to track individual API requests.

sim_swap_engine: SIM swap detection data. This field is always null or undefined for web SDKs, as SIM card information is only available on mobile devices. This field is included for API consistency with mobile SDKs.

Data Collection

The SDK collects three types of data: device information, session information, and behavioral data. All sensitive identifiers are hashed client-side before transmission to ensure privacy and compliance with data protection regulations. No personally identifiable information (PII) is collected or transmitted in plain text.

Device Information

Collected by the DeviceCollector class. Includes:

  • Device ID: First 32 characters of the device fingerprint hash
  • Fingerprint: SHA-256 hash (64 hex characters) of device characteristics including user agent, screen dimensions, timezone, locale, and hardware information
  • User Agent: Browser user agent string (used for fingerprinting, not sent directly)
  • Screen Dimensions: Screen width and height in pixels
  • Screen Density: Device pixel ratio (DPR)
  • Timezone: IANA timezone identifier (e.g., "America/New_York", "Africa/Nairobi")
  • Locale: Browser locale (e.g., "en-US", "sw-KE")
  • Hardware Info: Device manufacturer, model, and brand (if available from user agent)
  • OS Version: Operating system version (if available from user agent)

Privacy: The fingerprint is computed client-side and only the hash is transmitted. No raw device identifiers are sent. The fingerprint cannot be reverse-engineered to reveal the original device characteristics.

Session Information

Collected by the SDK internally. Tracks session and installation data.

  • Session ID: Unique session identifier (UUID) generated for each browser session
  • Timestamp: ISO 8601 formatted timestamp of the current session
  • Install ID: Unique identifier for the first installation (stored in localStorage)
  • Session Count: Number of sessions for this device (stored in localStorage)
  • First Session: ISO 8601 formatted timestamp of the first session (when the SDK was first initialized)

Storage: Session data is persisted in localStorage with the key prefix keverd_. The data is cleared when the user clears their browser storage or when destroy() is called.

Behavioral Data

Collected by the BehavioralCollector class. Tracks user interaction patterns for behavioral biometrics. Collection starts automatically when the SDK is initialized and stops when destroy() is called.

  • Typing Dwell Time: Array of milliseconds representing how long keys are held down (typically 5-20 samples)
  • Typing Flight Time: Array of milliseconds representing time between key releases (typically 5-20 samples)
  • Swipe Velocity: Average swipe velocity in pixels per millisecond (0.0 if no swipe data available)
  • Session Entropy: Shannon entropy value based on event diversity. Higher values indicate more diverse user interactions (0.0 if no events collected)

Collection: Behavioral data is collected passively as users interact with your website. The collector tracks mouse movements, keyboard input, touch gestures, and scroll events. Data collection is non-blocking and does not impact page performance. The collector uses event listeners that are automatically cleaned up when the SDK is destroyed.

Privacy: Behavioral data is aggregated and anonymized. Individual keystrokes or mouse movements are not transmitted; only statistical summaries (dwell times, flight times, velocities) are sent to the API.

Hashing and Privacy

All sensitive identifiers are hashed using SHA-256 before transmission. The SDK handles all hashing operations internally.

  • Device Fingerprint: Computed from a combination of device characteristics and hashed to 64 hex characters
  • No Raw PII: No personally identifiable information is transmitted in plain text
  • Client-Side Hashing: All hashing is performed in the browser before any data is sent to the API

Compliance: This approach ensures compliance with GDPR, CCPA, and other data protection regulations. The hashed identifiers cannot be reverse-engineered to reveal the original values. The SDK does not collect or transmit any personally identifiable information (PII) such as names, email addresses, phone numbers, or IP addresses.

Complete Example

Here's a complete example showing how to integrate the SDK into a web application. This example demonstrates initialization, visitor data collection, risk assessment, and error handling.

javascript
import { Keverd } from '@keverdjs/fraud-sdk';

// Initialize SDK (call this once when your app loads)
Keverd.init({
  apiKey: process.env.REACT_APP_KEVERD_API_KEY, // Use environment variables
  endpoint: 'https://api.keverd.com',
  debug: process.env.NODE_ENV === 'development' // Enable debug in dev only
});

// Get visitor data and assess risk
async function checkRisk() {
  try {
    const result = await Keverd.getVisitorData();
    
    // Handle risk score based on thresholds
    if (result.risk_score >= 70) {
      // High risk - block or require additional verification
      console.log('High risk detected:', result.reason);
      showSecurityAlert(result);
      requireAdditionalVerification(result);
    } else if (result.risk_score >= 30) {
      // Medium risk - require MFA
      console.log('Medium risk:', result.reason);
      requireMFA(result);
    } else {
      // Low risk - proceed normally
      console.log('Low risk, proceeding');
      proceedWithTransaction(result);
    }
    
    // Log the session ID for tracking
    console.log('Session ID:', result.session_id);
  } catch (error) {
    // Handle errors gracefully
    console.error('Error getting visitor data:', error);
    
    // Fallback behavior - decide based on your use case
    // Option 1: Fail open (allow access)
    proceedWithTransaction(null);
    
    // Option 2: Fail closed (block access)
    // showSecurityAlert(null);
  }
}

// Call on page load or user action
document.addEventListener('DOMContentLoaded', () => {
  checkRisk();
});

Error Handling

The SDK handles errors gracefully and throws Error objects that you can catch and handle. Here's how to handle different error scenarios:

Network Errors

Network errors occur when the device cannot connect to the API or when the request times out. The SDK uses 30-second timeouts for connection, read, and write operations.

javascript
try {
  const result = await Keverd.getVisitorData();
} catch (error) {
  if (error.message.includes('timeout') || error.message.includes('Timeout')) {
    // Handle timeout - retry with exponential backoff
    console.warn('Request timed out, retrying...');
    setTimeout(() => checkRisk(), 1000); // Retry after 1 second
  } else if (error.message.includes('network') || error.message.includes('Network')) {
    // Handle network connectivity issues
    console.error('Network error:', error.message);
    showNetworkError();
  } else {
    // Handle other network errors
    console.error('Network error:', error);
  }
}

API Errors

API errors occur when the server returns an error status code (4xx or 5xx). Common causes include invalid API keys, rate limiting, or server errors.

javascript
try {
  const result = await Keverd.getVisitorData();
} catch (error) {
  if (error.message.includes('401') || error.message.includes('Unauthorized')) {
    // Invalid API key
    console.error('Invalid API key. Please check your configuration.');
    showConfigurationError();
  } else if (error.message.includes('429') || error.message.includes('rate limit')) {
    // Rate limit exceeded
    console.warn('Rate limit exceeded. Please retry after some time.');
    showRateLimitError();
  } else if (error.message.includes('500') || error.message.includes('502') || error.message.includes('503')) {
    // Server errors - retry with backoff
    console.error('Server error:', error.message);
    retryWithBackoff();
  } else {
    // Other API errors
    console.error('API error:', error.message);
    handleApiError(error);
  }
}

Initialization Errors

Initialization errors occur when you try to use the SDK before calling init() or when the SDK is not properly initialized.

javascript
try {
  const result = await Keverd.getVisitorData();
} catch (error) {
  if (error.message.includes('not initialized') || error.message.includes('init')) {
    // SDK not initialized
    console.error('SDK not initialized. Call Keverd.init() first.');
    Keverd.init({
      apiKey: 'your-api-key-here',
      endpoint: 'https://api.keverd.com'
    });
    // Retry after initialization
    setTimeout(() => checkRisk(), 100);
  } else {
    // Other errors
    console.error('Error:', error);
  }
}

Best Practices for Error Handling

  • Always use try-catch: Wrap all calls to getVisitorData() in try-catch blocks to handle errors gracefully.
  • Implement retry logic: For transient errors (network timeouts, server errors), implement retry logic with exponential backoff.
  • Fail gracefully: Decide on a fail-open or fail-closed strategy. Fail-open allows access when the SDK fails, while fail-closed blocks access. Choose based on your security requirements.
  • Log errors: Log errors to your error tracking service (e.g., Sentry, LogRocket) for debugging and monitoring.
  • User feedback: Provide clear feedback to users when errors occur, especially for authentication or security-related failures.

Best Practices

Follow these best practices to ensure optimal performance, security, and user experience when integrating the Keverd SDK:

Initialization

  • Initialize early: Call init() as early as possible in your application lifecycle, ideally in your main entry point or app initialization code.
  • Initialize once: The SDK uses a singleton pattern, so you only need to initialize it once. Subsequent calls to init() will be ignored.
  • Use environment variables: Store your API key in environment variables and never commit it to version control. Use different API keys for development, staging, and production environments.
  • Enable debug in development only: Set debug: true only in development environments. Disable it in production to avoid exposing sensitive information in the console.

API Calls

  • Call at appropriate times: Call getVisitorData() at key points in your user flow, such as login, registration, checkout, or sensitive operations.
  • Avoid excessive calls: Don't call getVisitorData() on every page load or user interaction. Use it strategically for high-value or high-risk operations.
  • Handle asynchronously: Always use await or .then() when calling getVisitorData(), as it returns a Promise.
  • Implement retry logic: For transient errors, implement retry logic with exponential backoff to improve reliability.

Use-Case-Specific Methods

  • Use appropriate methods: Use verifyLogin() for login flows, verifyCheckout() for payment flows, etc. This provides better context for risk scoring.
  • Login verification: Call verifyLogin() before authenticating the user. Block or challenge high-risk attempts (risk_score ≥ 70).
  • Checkout verification: Call verifyCheckout() before processing payment. Require additional verification for medium-risk checkouts (risk_score 30-69).
  • Registration verification: Use verifyRegistration() to detect bot signups. Block high-risk registrations automatically.
  • Password reset: Always use verifyPasswordReset() for password reset flows. This is a high-risk operation that requires extra scrutiny.

Risk Score Interpretation

  • 0-29 (Low Risk): Allow the operation. User behavior matches their profile and shows no suspicious patterns.
  • 30-69 (Medium Risk): Require additional verification (MFA, CAPTCHA, email confirmation). User behavior is unusual but not clearly fraudulent.
  • 70-100 (High Risk): Block the operation or require manual review. Strong indicators of fraud or account takeover.
  • Context matters: A risk score of 50 for login is more concerning than 50 for registration. Adjust thresholds based on use case.
  • Combine with other signals: Use risk scores alongside other security measures (rate limiting, IP reputation, etc.) for defense in depth.
  • Monitor trends: Track risk score trends over time. Sudden increases may indicate a new attack vector.

Security

  • Protect your API key: Never expose your API key in client-side code that can be viewed in the browser. Use environment variables or a secure configuration management system.
  • Use HTTPS: Always use HTTPS endpoints. The SDK will not work with HTTP endpoints for security reasons.
  • Validate risk scores: Don't blindly trust risk scores. Use them as one factor in your security decision-making process, along with other signals.
  • Monitor for anomalies: Set up monitoring and alerting for unusual patterns in risk scores or error rates.

Performance

  • Non-blocking: The SDK is designed to be non-blocking. Data collection and API calls happen asynchronously and won't block your UI.
  • Minimal impact: Behavioral data collection is passive and has minimal impact on page performance. The SDK uses efficient event listeners that are automatically cleaned up.
  • Bundle size: The SDK is lightweight and has a small bundle size. It won't significantly impact your application's load time.

Privacy and Compliance

  • GDPR compliance: The SDK is designed to be GDPR-compliant. All sensitive data is hashed client-side, and no PII is collected or transmitted.
  • User consent: Consider obtaining user consent before initializing the SDK, especially in regions with strict privacy regulations.
  • Privacy policy: Update your privacy policy to inform users about data collection and how it's used for fraud detection.
  • Data retention: The SDK stores minimal data in localStorage. Consider clearing this data when users log out or request data deletion.

Risk Score Interpretation

Score RangeActionMeaning
0-29allowLow risk, proceed with login
30-69soft_challenge or hard_challengeModerate risk, require MFA
70-100blockHigh risk, deny access

Features

Universal Compatibility

Works in any JavaScript environment (browser, Node.js)

Lightweight

Small bundle size, fast initialization

Privacy-First

No PII collected, all data hashed client-side

Easy Integration

Simple API, minimal configuration required

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • Mobile browsers (iOS Safari, Chrome Mobile)