API Reference

Complete API documentation for the Keverd fraud detection platform. All endpoints, request/response formats, error handling, and integration examples.

API Overview

Base URL

https://api.keverd.com

Authentication

All API requests require authentication using an API key. Include your API key in one of the following headers:

  • x-keverd-key (recommended)
  • X-API-KEY
  • Authorization: Bearer YOUR_API_KEY

Content Type

All requests must use Content-Type: application/json

SDK Source Identification

SDKs automatically include the X-SDK-Source header to identify the SDK type:

  • javascript - Vanilla JavaScript SDK
  • react - React SDK
  • vue - Vue.js SDK
  • angular - Angular SDK
  • android - Android SDK
POST

/fingerprint/score

Score a fingerprint submission and return risk assessment. This is the primary endpoint for fraud detection. Accepts both SDK format (nested structure) and direct format (flat structure). Target latency: <100ms p99.

Request Format

SDK Format (Recommended)

This is the format used by all Keverd SDKs. It provides a structured, nested format that's easier to work with.

http
POST https://api.keverd.com/fingerprint/score
Content-Type: application/json
x-keverd-key: your-api-key-here
X-SDK-Source: javascript

{
  "userId": "user123",
  "device": {
    "deviceId": "abc123...",
    "fingerprint": "sha256_hash_64_chars...",
    "manufacturer": "Apple",
    "model": "iPhone 13",
    "brand": "Apple",
    "device": "mobile",
    "product": "iPhone",
    "hardware": "iPhone13,2",
    "sdkVersion": "1.0.0",
    "osVersion": "15.0",
    "screenWidth": "390",
    "screenHeight": "844",
    "screenDensity": "3.0",
    "locale": "en-US",
    "timezone": "America/New_York"
  },
  "session": {
    "sessionId": "session_123",
    "timestamp": "2025-01-15T10:30:00Z"
  },
  "behavioral": {
    "typing_dwell_ms": [120.5, 135.2, 110.8, 125.3, 130.1],
    "typing_flight_ms": [45.2, 50.1, 42.3, 48.7, 46.5],
    "swipe_velocity": 2.5,
    "session_entropy": 3.8
  }
}

Android SDK Format (with SIM data)

Android SDK includes SIM card information for enhanced fraud detection:

json
{
  "userId": "user123",
  "device": {
    "deviceId": "abc123...",
    "fingerprint": "sha256_hash...",
    "manufacturer": "Samsung",
    "model": "SM-G991B",
    "osVersion": "13",
    "timezone": "Africa/Nairobi",
    ...
  },
  "sim": {
    "simOperator": "63902",
    "simOperatorName": "Safaricom",
    "simSerialNumber": "hashed_sim_serial",
    "networkOperator": "63902",
    "networkType": "LTE"
  },
  "session": {
    "sessionId": "session_123",
    "sessionCount": "5",
    "firstSession": "2025-01-01T00:00:00Z"
  },
  "behavioral": {
    "typing_dwell_ms": [120.5, 135.2],
    "typing_flight_ms": [45.2, 50.1],
    "swipe_velocity": 2.5,
    "session_entropy": 3.8
  }
}

Request Parameters

ParameterTypeRequiredDescription
userIdstringNoUser identifier. If not provided, backend auto-generates from device fingerprint
deviceobjectYesDevice information object (see DeviceInfo below)
sessionobjectNoSession information object (see SessionInfo below)
behavioralobjectNoBehavioral data object (see BehavioralData below)
simobjectNoSIM card information (Android/iOS only, see SimInfo below)

DeviceInfo Object

FieldTypeRequiredDescription
deviceIdstringYesUnique device identifier (first 32 chars of fingerprint)
fingerprintstringYesSHA-256 hash of device characteristics (64 hex characters)
manufacturerstringNoDevice manufacturer (e.g., "Apple", "Samsung")
modelstringNoDevice model name
osVersionstringNoOperating system version
screenWidthstringNoScreen width in pixels
screenHeightstringNoScreen height in pixels
timezonestringYesIANA timezone identifier (e.g., "America/New_York", "Africa/Nairobi")
localestringNoDevice locale (e.g., "en-US", "sw-KE")

SessionInfo Object

FieldTypeDescription
sessionIdstringUnique session identifier
timestampstring (ISO 8601)Session timestamp in ISO 8601 format
sessionCountstringNumber of sessions for this device (Android SDK)
firstSessionstring (ISO 8601)Timestamp of first session (Android SDK)

BehavioralData Object

FieldTypeDescription
typing_dwell_msnumber[]Array of typing dwell times (time key is held down) in milliseconds. Typically 5-20 samples.
typing_flight_msnumber[]Array of typing flight times (time between key releases) in milliseconds. Typically 5-20 samples.
swipe_velocitynumberAverage swipe velocity in pixels per millisecond. 0.0 if no swipe data available.
session_entropynumberSession entropy value (Shannon entropy) based on event diversity. Higher values indicate more diverse user interactions. 0.0 if no events collected.

Enhanced Signals (Automatically Collected)

The SDK automatically collects enhanced behavioral signals that are critical for accurate risk scoring, especially for registration use cases. These signals are included automatically in all requests - you don't need to manually collect or send them.

Automatic Collection

All enhanced signals are collected automatically in the background from the moment the SDK is initialized. No manual collection or configuration is required.

Mouse Signals
FieldTypeDescription
clickCountnumberTotal number of mouse clicks detected
totalDistancenumberTotal distance mouse moved in pixels
averageVelocitynumberAverage mouse movement velocity (pixels/ms)

Used for: Detecting uniform mouse patterns (bot behavior), measuring user engagement, identifying automation

Keyboard Signals
FieldTypeDescription
keydownCountnumberTotal number of keydown events
typingSpeednumberAverage typing speed (characters per second)

Used for: Detecting uniform typing patterns (bot behavior), identifying copy-paste behavior, measuring typing consistency

Page Interactions
FieldTypeDescription
clickCountnumberTotal page clicks
scrollDepthnumberMaximum scroll depth (0-100%)
timeToFirstInteractionnumberTime to first user interaction in milliseconds
timeOnPagenumberTotal time spent on page in milliseconds

Used for: Detecting minimal interactions (bot behavior), measuring engagement, identifying fast flows

Form Interactions
FieldTypeDescription
focusCountnumberNumber of form field focus events
pasteCountnumberNumber of paste events (high risk for registration)
autofillDetectedbooleanWhether browser autofill was detected
fieldFocusOrderstring[]Order in which fields were focused (detects perfect completion)

Used for: Detecting copy-paste behavior, identifying perfect form completion (bot), measuring form interaction patterns

Privacy Signals
FieldTypeDescription
isIncognitobooleanWhether browser is in incognito/private mode
isVPNbooleanWhether VPN or proxy is detected
isAutomatedbooleanWhether automation/bot is detected (high risk)
hasAdBlockerbooleanWhether ad blocker is detected

Used for: Detecting automation tools, identifying privacy-focused users, flagging suspicious browser configurations

Why These Signals Matter for Registration

  • Bot Detection: Uniform mouse/keyboard patterns indicate automation
  • Behavior Change: Mid-session changes suggest session hijacking or account sharing
  • Copy-Paste Detection: Excessive paste events suggest fake account creation
  • Perfect Completion: Forms filled too quickly or perfectly indicate bots
  • Minimal Interactions: Low click/scroll counts suggest non-human behavior

Response Format

json
{
  "risk_score": 25,
  "score": 0.25,
  "action": "allow",
  "reason": [],
  "session_id": "123e4567-e89b-12d3-a456-426614174000",
  "requestId": "123e4567-e89b-12d3-a456-426614174000",
  "sim_swap_engine": {
    "risk": 0.0,
    "flags": {
      "sim_changed": false,
      "device_changed": false,
      "behavior_anomaly": false,
      "time_anomaly": false,
      "velocity_anomaly": false
    },
    "updatedProfile": {}
  }
}

Response Fields

FieldTypeDescription
risk_scorenumber (0-100)Risk score from 0 (lowest risk) to 100 (highest risk). Integer value for easy comparison.
scorenumber (0.0-1.0)Normalized risk score as float. Equal to risk_score / 100. Provided for SDK compatibility.
actionstringRecommended action: "allow", "soft_challenge", "hard_challenge", or "block"
reasonstring[]Array of risk reasons explaining why the risk score was assigned. Examples: ["new_user_profile", "geo_jump", "device_changed", "behavior_anomaly"]
session_idstring (UUID)Unique session identifier for this request. Use this to track and correlate events.
requestIdstring (UUID)Unique request identifier. Same as session_id, provided for SDK compatibility.
sim_swap_engineobjectSIM swap detection results (only present for Android/iOS SDKs with SIM data). Contains risk score and flags indicating detected anomalies.

Risk Score Interpretation

Understanding Risk Scores: Risk scores are calculated based on multiple factors including device history, behavioral patterns, geographic anomalies, and SIM swap detection (for mobile devices).

Score RangeActionMeaningRecommended Response
0-29allowLow risk. User appears to be legitimate based on device history and behavior patterns.Proceed with login/transaction. No additional verification required.
30-49soft_challengeModerate risk. Some anomalies detected but may be legitimate (e.g., new device, location change).Require additional verification such as email/SMS verification or security questions.
50-69hard_challengeHigh risk. Significant anomalies detected (e.g., device change, behavioral mismatch, geographic jump).Require strong MFA (multi-factor authentication) such as TOTP, hardware key, or biometric verification.
70-100blockVery high risk. Strong indicators of fraud or account takeover (e.g., SIM swap, multiple device changes, suspicious behavior).Block the request and flag for manual review. Consider account lockout and user notification.

Risk Reasons

The reason array contains strings explaining why a particular risk score was assigned. Common reasons include:

Profile Reasons

  • new_user_profile - First time seeing this user
  • device_changed - Different device than usual
  • multiple_devices - User has multiple devices

Geographic Reasons

  • geo_jump - Unusual location change
  • vpn_detected - VPN or proxy detected
  • unusual_location - Location not in user history

Behavioral Reasons

  • behavior_anomaly - Typing patterns don't match
  • typing_speed_mismatch - Typing speed differs significantly
  • session_entropy_low - Unusual interaction patterns

SIM Swap Reasons

  • sim_changed - SIM card changed (Android only)
  • time_anomaly - Unusual timing patterns
  • velocity_anomaly - Rapid successive requests

Use-Case Verification Endpoints

These endpoints are optimized for specific use cases and automatically set the use_case parameter. They accept the same request format as /fingerprint/score and return the same response format.

POST

/fingerprint/verify/login

Verify user identity during login attempts. Optimized for detecting account takeover and credential stuffing.

Use Case: Automatically set to "login"

POST

/fingerprint/verify/checkout

Verify user during checkout/payment flows. Detects payment fraud and stolen card usage.

Use Case: Automatically set to "checkout"

POST

/fingerprint/verify/registration

Verify new account registrations. Detects bot signups and fake accounts.

Use Case: Automatically set to "registration"

POST

/fingerprint/verify/password-reset

Verify password reset requests. High-risk use case requiring enhanced security checks.

Use Case: Automatically set to "password_reset"

POST

/fingerprint/verify/account-change

Verify account modification requests (email change, phone change, etc.).

Use Case: Automatically set to "account_change"

Registration Behavioral Monitoring

Overview

The registration verification endpoint provides continuous behavioral monitoring from the moment a user starts the registration process. This enables real-time detection of bot signups, behavior changes, and suspicious patterns.

Key Features:

  • Automatic Baseline: SDK automatically establishes behavioral baseline from first interactions
  • Mid-Session Detection: Detects behavior changes within a single registration session
  • Enhanced Bot Detection: Identifies bots, automation, uniform patterns, and non-human behavior
  • Adaptive Responses: Recommends MFA, CAPTCHA, or custom flows based on real-time risk
  • Comprehensive Data Collection: Automatically collects mouse, keyboard, page, and form interactions

How It Works

The SDK automatically collects comprehensive behavioral data from the moment it's initialized. No manual data collection is required - everything happens automatically in the background.

1. Automatic Data Collection

When you initialize the SDK, it immediately starts collecting behavioral data automatically:

  • Mouse movements: Velocity, acceleration, click patterns, movement distance
  • Keyboard patterns: Typing speed, dwell time (key hold duration), flight time (time between keys)
  • Page interactions: Clicks, scrolls, time on page, scroll depth
  • Form interactions: Focus events, copy/paste detection, autofill detection, field focus order
  • Privacy signals: Incognito mode, VPN detection, automation detection, ad blocker
javascript
// Initialize SDK early (e.g., on page load)
import { Keverd } from '@keverdjs/fraud-sdk';

// SDK automatically starts collecting data
Keverd.init('your-api-key');

// No additional setup required - data collection happens automatically

The SDK establishes a behavioral baseline automatically from the first interactions. This baseline is used to detect behavior changes during registration.

2. Registration Verification

Call the registration verification endpoint when the user submits the registration form. The SDK automatically includes all collected behavioral data.

javascript
// JavaScript SDK - Complete registration flow
import { Keverd } from '@keverdjs/fraud-sdk';

// Initialize early (e.g., in your app entry point)
Keverd.init('your-api-key');

// Later, when user submits registration form
async function handleRegistrationSubmit(formData) {
  // Verify registration - SDK automatically includes all collected data
  const result = await Keverd.verifyRegistration({
    email: formData.email,
    username: formData.username
  });
  
  // Handle response based on risk level
  if (result.action === 'allow') {
    // Low risk - proceed with registration
    await createUserAccount(formData);
  } else if (result.action === 'soft_challenge') {
    // Medium risk - show recommended challenges
    const challenges = result.adaptive_response?.challenges || [];
    if (challenges.includes('captcha')) {
      await showCaptcha();
    }
    if (challenges.includes('mfa')) {
      await sendEmailVerification(formData.email);
    }
  } else if (result.action === 'block') {
    // High risk - block registration
    showError('Registration blocked due to security concerns');
  }
}

// React SDK
import { useKeverdContext } from '@keverdjs/fraud-sdk-react';

function RegistrationForm() {
  const { verifyRegistration } = useKeverdContext();
  
  const handleSubmit = async (formData) => {
    const result = await verifyRegistration({
      email: formData.email,
      username: formData.username
    });
    // Handle result...
  };
}

3. Session Management

The SDK automatically maintains a session ID that links all events together. Session continuity is maintained throughout the registration flow without any manual intervention.

javascript
// Session is automatically managed by SDK
// All events in the same session are linked
// Session persists from SDK init to page unload
// No manual session management required

Data Automatically Collected

The SDK automatically collects all the following data - you don't need to manually send anything:

Device Information

  • • Screen resolution
  • • Timezone
  • • Language/locale
  • • User agent
  • • Device fingerprint

Mouse Signals

  • • Click count
  • • Movement distance
  • • Average velocity
  • • Movement patterns

Keyboard Signals

  • • Typing speed
  • • Keydown count
  • • Dwell time (key hold)
  • • Flight time (between keys)

Page Interactions

  • • Click count
  • • Scroll depth
  • • Time to first interaction
  • • Time on page

Form Interactions

  • • Focus/blur events
  • • Copy/paste detection
  • • Autofill detection
  • • Field focus order

Privacy Signals

  • • Incognito mode
  • • VPN/proxy detection
  • • Automation detection
  • • Ad blocker detection

All data collection is automatic

You don't need to manually collect or send any of this data. The SDK handles everything automatically when you call verifyRegistration().

Response Format

The registration verification endpoint returns enhanced response data including behavioral analysis:

json
{
  "risk_score": 45,
  "action": "soft_challenge",
  "reason": [
    "behavior_shift_detected",
    "typing_speed_changed",
    "uniform_typing_pattern"
  ],
  "session_id": "session-uuid",
  "request_id": "request-uuid",
  "score": 0.45,
  
  // Behavioral change analysis
  "behavior_change": {
    "baseline_available": true,
    "behavior_changed": true,
    "change_score": 35.5,
    "change_reasons": [
      "typing_speed_changed",
      "mouse_pattern_changed"
    ],
    "similarity_score": 62.3
  },
  
  // Adaptive response recommendations
  "adaptive_response": {
    "recommended_action": "soft_challenge",
    "challenges": ["mfa", "captcha"],
    "reason": "Behavior change detected during registration",
    "confidence": 0.85
  }
}

Adaptive Responses

Understanding Adaptive Responses

Based on real-time risk assessment and behavioral analysis, the API recommends specific actions to take. You should implement these recommendations to create an adaptive registration flow.

Allow (Low Risk)

action: "allow" - Registration appears legitimate. Proceed with account creation.

javascript
if (result.action === "allow") {
  // Proceed with registration
  await createUserAccount(userData);
}

Soft Challenge (Medium Risk)

action: "soft_challenge" - Some suspicious signals detected. Require additional verification.

javascript
if (result.action === "soft_challenge") {
  // Check adaptive_response for recommended challenges
  const challenges = result.adaptive_response?.challenges || [];
  
  if (challenges.includes("captcha")) {
    // Show CAPTCHA
    await showCaptcha();
  }
  
  if (challenges.includes("mfa")) {
    // Request email/SMS verification
    await sendVerificationCode(userEmail);
  }
  
  // After challenge completion, verify again
  const recheck = await keverd.verifyRegistration();
  if (recheck.action === "allow") {
    await createUserAccount(userData);
  }
}

Hard Challenge (High Risk)

action: "hard_challenge" - Multiple suspicious signals. Require strong verification.

javascript
if (result.action === "hard_challenge") {
  // Require multiple verification steps
  await showCaptcha();
  await sendVerificationCode(userEmail);
  await sendVerificationCode(userPhone);
  
  // Verify all challenges passed
  const allVerified = await verifyAllChallenges();
  if (allVerified) {
    const recheck = await keverd.verifyRegistration();
    if (recheck.action === "allow") {
      await createUserAccount(userData);
    }
  }
}

Block (Very High Risk)

action: "block" - Clear bot or fraud indicators. Block registration.

javascript
if (result.action === "block") {
  // Block registration
  showError("Registration blocked due to security concerns");
  // Optionally log for review
  logSuspiciousRegistration(result);
}

Behavior Change Indicators

The behavior_change object provides detailed information about behavioral anomalies:

baseline_available

Whether a behavioral baseline exists (automatically established from first interactions)

behavior_changed

Whether behavior deviated from baseline during the session

change_score

0-100 score indicating severity of behavior change (higher = more suspicious)

similarity_score

0-100 percentage similarity to baseline (higher = more similar, lower = more suspicious)

change_reasons

List of specific reasons for behavior change (e.g., "typing_speed_changed", "mouse_pattern_changed")

Complete Integration Example

javascript
// React example
import { useKeverdContext } from '@keverdjs/fraud-sdk-react';

function RegistrationForm() {
  const { verifyRegistration } = useKeverdContext();
  const [step, setStep] = useState('form');
  
  const handleSubmit = async (formData) => {
    try {
      // Verify registration with behavioral monitoring
      const result = await verifyRegistration({
        email: formData.email,
        username: formData.username
      });
      
      // Check risk level
      if (result.action === "block") {
        // Block registration
        showError("Registration blocked. Please contact support.");
        return;
      }
      
      if (result.action === "hard_challenge") {
        // Require multiple verifications
        setStep('challenge');
        await showCaptcha();
        await sendEmailVerification(formData.email);
        await sendSMSVerification(formData.phone);
        return;
      }
      
      if (result.action === "soft_challenge") {
        // Check recommended challenges
        const challenges = result.adaptive_response?.challenges || [];
        
        if (challenges.includes("captcha")) {
          await showCaptcha();
        }
        
        if (challenges.includes("mfa")) {
          await sendEmailVerification(formData.email);
        }
        
        // Re-verify after challenges
        const recheck = await verifyRegistration();
        if (recheck.action !== "allow") {
          showError("Verification failed. Please try again.");
          return;
        }
      }
      
      // Behavior change detected?
      if (result.behavior_change?.behavior_changed) {
        console.warn("Behavior change detected:", result.behavior_change.change_reasons);
        // Log for review or require additional verification
        if (result.behavior_change.change_score > 50) {
          await sendEmailVerification(formData.email);
        }
      }
      
      // Proceed with registration
      await createUserAccount(formData);
      showSuccess("Account created successfully!");
      
    } catch (error) {
      console.error("Registration verification failed:", error);
      showError("Registration failed. Please try again.");
    }
  };
  
  return (
    // Your registration form JSX
  );
}

Use Case Integration Examples

Registration Flow

Complete registration flow with behavioral monitoring, bot detection, and adaptive challenges.

Vanilla JavaScript

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

// 1. Initialize SDK early (e.g., in your app entry point)
Keverd.init('your-api-key');

// 2. Registration form handler
async function handleRegistrationSubmit(formData) {
  try {
    // Verify registration - SDK automatically includes all collected data
    const result = await Keverd.verifyRegistration({
      email: formData.email,
      username: formData.username
    });
    
    // Handle based on risk level
    if (result.action === 'block') {
      // High risk - block registration
      showError('Registration blocked due to security concerns');
      logSecurityEvent('blocked_registration', result);
      return;
    }
    
    if (result.action === 'hard_challenge') {
      // High risk - require multiple verifications
      await showCaptcha();
      await sendEmailVerification(formData.email);
      await sendSMSVerification(formData.phone);
      
      // Re-verify after challenges
      const recheck = await Keverd.verifyRegistration();
      if (recheck.action !== 'allow') {
        showError('Verification failed. Please contact support.');
        return;
      }
    }
    
    if (result.action === 'soft_challenge') {
      // Medium risk - show recommended challenges
      const challenges = result.adaptive_response?.challenges || [];
      
      if (challenges.includes('captcha')) {
        const captchaValid = await showCaptcha();
        if (!captchaValid) {
          showError('CAPTCHA verification failed');
          return;
        }
      }
      
      if (challenges.includes('mfa')) {
        await sendEmailVerification(formData.email);
      }
      
      // Re-verify after challenges
      const recheck = await Keverd.verifyRegistration();
      if (recheck.action !== 'allow') {
        showError('Verification failed. Please try again.');
        return;
      }
    }
    
    // Check for behavior changes
    if (result.behavior_change?.behavior_changed) {
      console.warn('Behavior change detected:', result.behavior_change.change_reasons);
      // Log for review or require additional verification
      if (result.behavior_change.change_score > 50) {
        await sendEmailVerification(formData.email);
      }
    }
    
    // All checks passed - create account
    const account = await createUserAccount(formData);
    showSuccess('Account created successfully!');
    return account;
    
  } catch (error) {
    console.error('Registration verification failed:', error);
    showError('Registration failed. Please try again.');
  }
}

React

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

function RegistrationForm() {
  const { verifyRegistration } = useKeverdContext();
  const [loading, setLoading] = useState(false);
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    
    const formData = {
      email: e.target.email.value,
      username: e.target.username.value,
      password: e.target.password.value
    };
    
    try {
      const result = await verifyRegistration({
        email: formData.email,
        username: formData.username
      });
      
      if (result.action === 'block') {
        setError('Registration blocked. Please contact support.');
        return;
      }
      
      if (result.action === 'soft_challenge' || result.action === 'hard_challenge') {
        const challenges = result.adaptive_response?.challenges || [];
        
        // Show challenges based on recommendations
        if (challenges.includes('captcha')) {
          await showCaptcha();
        }
        if (challenges.includes('mfa')) {
          await sendEmailVerification(formData.email);
        }
        
        // Re-verify
        const recheck = await verifyRegistration();
        if (recheck.action !== 'allow') {
          setError('Verification failed.');
          return;
        }
      }
      
      // Create account
      await createAccount(formData);
      router.push('/dashboard');
      
    } catch (error) {
      setError('Registration failed. Please try again.');
    } finally {
      setLoading(false);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      {/* Your form fields */}
    </form>
  );
}

Vue.js

javascript
<script setup>
import { useKeverdProvider } from '@keverdjs/fraud-sdk-vue';

const { verifyRegistration } = useKeverdProvider();
const loading = ref(false);
const error = ref(null);

const handleSubmit = async (formData) => {
  loading.value = true;
  error.value = null;
  
  try {
    const result = await verifyRegistration({
      email: formData.email,
      username: formData.username
    });
    
    if (result.action === 'block') {
      error.value = 'Registration blocked. Please contact support.';
      return;
    }
    
    if (result.action !== 'allow') {
      const challenges = result.adaptive_response?.challenges || [];
      // Handle challenges...
    }
    
    await createAccount(formData);
    router.push('/dashboard');
    
  } catch (err) {
    error.value = 'Registration failed. Please try again.';
  } finally {
    loading.value = false;
  }
};
</script>

Login Flow

Detect account takeover attempts and credential stuffing during login.

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

async function handleLogin(email, password) {
  try {
    // Verify login attempt
    const result = await Keverd.verifyLogin(email);
    
    if (result.action === 'block') {
      // Block login - potential account takeover
      showError('Login blocked due to security concerns');
      logSecurityEvent('blocked_login', { email, result });
      return;
    }
    
    // Proceed with authentication
    const authResult = await authenticateUser(email, password);
    
    if (!authResult.success) {
      return;
    }
    
    // If high risk, require MFA even after successful password
    if (result.action === 'hard_challenge') {
      const mfaValid = await requestMFA();
      if (!mfaValid) {
        showError('MFA verification failed');
        return;
      }
    }
    
    // Login successful
    redirectToDashboard();
    
  } catch (error) {
    console.error('Login verification failed:', error);
    showError('Login failed. Please try again.');
  }
}

Checkout Flow

Verify payment transactions and detect payment fraud.

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

async function handleCheckout(cart, paymentMethod) {
  try {
    // Verify checkout
    const result = await Keverd.verifyCheckout(
      cart.total,
      cart.currency,
      {
        paymentMethod: paymentMethod.type,
        cardLast4: paymentMethod.last4,
        items: cart.items.length
      }
    );
    
    if (result.action === 'block') {
      // Block transaction
      showError('Transaction blocked due to security concerns');
      logSecurityEvent('blocked_transaction', { amount: cart.total, result });
      return;
    }
    
    if (result.action === 'hard_challenge') {
      // Require payment verification
      const verified = await requestPayment2FA();
      if (!verified) {
        showError('Payment verification failed');
        return;
      }
    }
    
    // Proceed with payment
    const paymentResult = await processPayment(cart, paymentMethod);
    if (paymentResult.success) {
      showSuccess('Payment processed successfully!');
    }
    
  } catch (error) {
    console.error('Checkout verification failed:', error);
    showError('Payment failed. Please try again.');
  }
}

Password Reset Flow

Detect account takeover attempts during password reset requests.

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

async function handlePasswordReset(email) {
  try {
    // Verify password reset request
    const result = await Keverd.verifyPasswordReset(email);
    
    if (result.action === 'block') {
      // Block password reset - potential account takeover
      showError('Password reset blocked. Please contact support.');
      logSecurityEvent('blocked_password_reset', { email, result });
      return;
    }
    
    if (result.action === 'hard_challenge') {
      // Require additional verification
      const verified = await sendVerificationCode(email);
      if (!verified) {
        showError('Verification failed');
        return;
      }
    }
    
    // Send password reset email
    await sendPasswordResetEmail(email);
    showSuccess('Password reset email sent!');
    
  } catch (error) {
    console.error('Password reset verification failed:', error);
    showError('Password reset failed. Please try again.');
  }
}

Account Change Flow

Verify sensitive account modifications (email, phone, password changes).

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

async function handleEmailChange(currentEmail, newEmail) {
  try {
    // Verify account change
    const result = await Keverd.verifyAccountChange('email', {
      oldEmail: currentEmail,
      newEmail: newEmail
    });
    
    if (result.action === 'block') {
      showError('Email change blocked. Please contact support.');
      return;
    }
    
    if (result.action === 'hard_challenge') {
      // Require verification from both emails
      await sendVerificationCode(currentEmail);
      await sendVerificationCode(newEmail);
      
      const bothVerified = await verifyBothCodes();
      if (!bothVerified) {
        showError('Verification failed');
        return;
      }
    }
    
    // Proceed with email change
    await updateUserEmail(newEmail);
    showSuccess('Email updated successfully!');
    
  } catch (error) {
    console.error('Account change verification failed:', error);
    showError('Email change failed. Please try again.');
  }
}

Error Handling

HTTP Status Codes

Status CodeMeaningResponse Body
200SuccessFingerprintScoreResponse object
400Bad RequestError message describing invalid request format or missing required fields
401UnauthorizedInvalid or missing API key
403ForbiddenAPI key inactive or insufficient permissions
429Too Many RequestsRate limit exceeded. Check Retry-After header
500Internal Server ErrorServer error. Retry request after a delay

Error Response Format

json
{
  "detail": "Error message describing what went wrong",
  "error_code": "ERROR_CODE",
  "status_code": 400
}

Common Error Codes

INVALID_API_KEY

The provided API key is invalid or has been revoked.

MISSING_DEVICE_INFO

Required device information is missing from the request.

RATE_LIMIT_EXCEEDED

Too many requests. Rate limit is 100 requests per second per API key.

INVALID_FINGERPRINT

Device fingerprint format is invalid. Must be SHA-256 hash (64 hex characters).

Authentication

All API requests require authentication using an API key. You can obtain your API key from the API Keys page in the dashboard.

Header Format

Include your API key in the request headers. The API accepts multiple header formats for compatibility:

http
# Recommended format
x-keverd-key: your-api-key-here

# Alternative formats (also supported)
X-API-KEY: your-api-key-here
Authorization: Bearer your-api-key-here

Security Note: Never expose your API key in client-side code or commit it to version control. Always use environment variables or secure configuration management.

Rate Limiting

Rate Limits

  • Per API Key: 100 requests per second
  • Per User ID: 100 requests per second (additional limit)
  • Sandbox Environment: 10 requests per second

Rate Limit Headers

When rate limits are approached or exceeded, the API includes the following headers:

HeaderDescription
X-RateLimit-LimitMaximum number of requests allowed per window
X-RateLimit-RemainingNumber of requests remaining in current window
X-RateLimit-ResetUnix timestamp when rate limit resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Best Practice: Implement exponential backoff when receiving 429 responses. Start with a 1-second delay and double it for each subsequent retry, up to a maximum of 60 seconds.

Code Examples

cURL Example

bash
curl -X POST https://api.keverd.com/fingerprint/score \
  -H "Content-Type: application/json" \
  -H "x-keverd-key: your-api-key-here" \
  -d '{
    "userId": "user123",
    "device": {
      "deviceId": "abc123",
      "fingerprint": "sha256_hash_64_chars...",
      "timezone": "America/New_York"
    },
    "behavioral": {
      "typing_dwell_ms": [120.5, 135.2, 110.8],
      "typing_flight_ms": [45.2, 50.1, 42.3],
      "swipe_velocity": 2.5,
      "session_entropy": 3.8
    }
  }'

JavaScript/Fetch Example

javascript
const response = await fetch('https://api.keverd.com/fingerprint/score', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-keverd-key': 'your-api-key-here'
  },
  body: JSON.stringify({
    userId: 'user123',
    device: {
      deviceId: 'abc123',
      fingerprint: 'sha256_hash...',
      timezone: 'America/New_York'
    },
    behavioral: {
      typing_dwell_ms: [120.5, 135.2, 110.8],
      typing_flight_ms: [45.2, 50.1, 42.3],
      swipe_velocity: 2.5,
      session_entropy: 3.8
    }
  })
});

const data = await response.json();
console.log('Risk Score:', data.risk_score);
console.log('Action:', data.action);

Python Example

python
import requests

url = "https://api.keverd.com/fingerprint/score"
headers = {
    "Content-Type": "application/json",
    "x-keverd-key": "your-api-key-here"
}
payload = {
    "userId": "user123",
    "device": {
        "deviceId": "abc123",
        "fingerprint": "sha256_hash...",
        "timezone": "America/New_York"
    },
    "behavioral": {
        "typing_dwell_ms": [120.5, 135.2, 110.8],
        "typing_flight_ms": [45.2, 50.1, 42.3],
        "swipe_velocity": 2.5,
        "session_entropy": 3.8
    }
}

response = requests.post(url, json=payload, headers=headers)
data = response.json()

print(f"Risk Score: {data['risk_score']}")
print(f"Action: {data['action']}")

Performance & Latency

Target Performance

  • p50 Latency: < 50ms (median response time)
  • p95 Latency: < 80ms (95th percentile)
  • p99 Latency: < 100ms (99th percentile)

Optimization Tips

  • • Use connection pooling for multiple requests
  • • Implement request batching when possible
  • • Cache risk scores for short periods (5-10 seconds) for repeated requests
  • • Use async/await or non-blocking I/O for better concurrency

Data Privacy & Compliance

Privacy-First Design

  • All device identifiers are SHA-256 hashed client-side before transmission
  • No raw PII (Personally Identifiable Information) is stored or transmitted
  • HTTPS-only communication enforced
  • GDPR and Kenya Data Protection Act compliant

Data Retention

Fingerprint data is retained according to your subscription plan and regional compliance requirements. You can request data deletion through the dashboard or API.

SDK Integration Guides

For easier integration, use one of our official SDKs which handle all the API details for you: