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.comAuthentication
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-KEYAuthorization: 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 SDKreact- React SDKvue- Vue.js SDKangular- Angular SDKandroid- Android SDK
/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.
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:
{
"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
| Parameter | Type | Required | Description |
|---|---|---|---|
| userId | string | No | User identifier. If not provided, backend auto-generates from device fingerprint |
| device | object | Yes | Device information object (see DeviceInfo below) |
| session | object | No | Session information object (see SessionInfo below) |
| behavioral | object | No | Behavioral data object (see BehavioralData below) |
| sim | object | No | SIM card information (Android/iOS only, see SimInfo below) |
DeviceInfo Object
| Field | Type | Required | Description |
|---|---|---|---|
| deviceId | string | Yes | Unique device identifier (first 32 chars of fingerprint) |
| fingerprint | string | Yes | SHA-256 hash of device characteristics (64 hex characters) |
| manufacturer | string | No | Device manufacturer (e.g., "Apple", "Samsung") |
| model | string | No | Device model name |
| osVersion | string | No | Operating system version |
| screenWidth | string | No | Screen width in pixels |
| screenHeight | string | No | Screen height in pixels |
| timezone | string | Yes | IANA timezone identifier (e.g., "America/New_York", "Africa/Nairobi") |
| locale | string | No | Device locale (e.g., "en-US", "sw-KE") |
SessionInfo Object
| Field | Type | Description |
|---|---|---|
| sessionId | string | Unique session identifier |
| timestamp | string (ISO 8601) | Session timestamp in ISO 8601 format |
| sessionCount | string | Number of sessions for this device (Android SDK) |
| firstSession | string (ISO 8601) | Timestamp of first session (Android SDK) |
BehavioralData Object
| Field | Type | Description |
|---|---|---|
| typing_dwell_ms | number[] | Array of typing dwell times (time key is held down) in milliseconds. Typically 5-20 samples. |
| typing_flight_ms | number[] | Array of typing flight times (time between key releases) in milliseconds. Typically 5-20 samples. |
| swipe_velocity | number | Average swipe velocity in pixels per millisecond. 0.0 if no swipe data available. |
| session_entropy | number | Session entropy value (Shannon entropy) based on event diversity. Higher values indicate more diverse user interactions. 0.0 if no events collected. |
Response Format
{
"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
| Field | Type | Description |
|---|---|---|
| risk_score | number (0-100) | Risk score from 0 (lowest risk) to 100 (highest risk). Integer value for easy comparison. |
| score | number (0.0-1.0) | Normalized risk score as float. Equal to risk_score / 100. Provided for SDK compatibility. |
| action | string | Recommended action: "allow", "soft_challenge", "hard_challenge", or "block" |
| reason | string[] | Array of risk reasons explaining why the risk score was assigned. Examples: ["new_user_profile", "geo_jump", "device_changed", "behavior_anomaly"] |
| session_id | string (UUID) | Unique session identifier for this request. Use this to track and correlate events. |
| requestId | string (UUID) | Unique request identifier. Same as session_id, provided for SDK compatibility. |
| sim_swap_engine | object | SIM 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 Range | Action | Meaning | Recommended Response |
|---|---|---|---|
| 0-29 | allow | Low risk. User appears to be legitimate based on device history and behavior patterns. | Proceed with login/transaction. No additional verification required. |
| 30-49 | soft_challenge | Moderate 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-69 | hard_challenge | High 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-100 | block | Very 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 userdevice_changed- Different device than usualmultiple_devices- User has multiple devices
Geographic Reasons
geo_jump- Unusual location changevpn_detected- VPN or proxy detectedunusual_location- Location not in user history
Behavioral Reasons
behavior_anomaly- Typing patterns don't matchtyping_speed_mismatch- Typing speed differs significantlysession_entropy_low- Unusual interaction patterns
SIM Swap Reasons
sim_changed- SIM card changed (Android only)time_anomaly- Unusual timing patternsvelocity_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.
/fingerprint/verify/login
Verify user identity during login attempts. Optimized for detecting account takeover and credential stuffing.
Use Case: Automatically set to "login"
/fingerprint/verify/checkout
Verify user during checkout/payment flows. Detects payment fraud and stolen card usage.
Use Case: Automatically set to "checkout"
/fingerprint/verify/registration
Verify new account registrations. Detects bot signups and fake accounts.
Use Case: Automatically set to "registration"
/fingerprint/verify/password-reset
Verify password reset requests. High-risk use case requiring enhanced security checks.
Use Case: Automatically set to "password_reset"
/fingerprint/verify/account-change
Verify account modification requests (email change, phone change, etc.).
Use Case: Automatically set to "account_change"
Error Handling
HTTP Status Codes
| Status Code | Meaning | Response Body |
|---|---|---|
| 200 | Success | FingerprintScoreResponse object |
| 400 | Bad Request | Error message describing invalid request format or missing required fields |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | API key inactive or insufficient permissions |
| 429 | Too Many Requests | Rate limit exceeded. Check Retry-After header |
| 500 | Internal Server Error | Server error. Retry request after a delay |
Error Response Format
{
"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:
# 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-hereSecurity 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:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum number of requests allowed per window |
| X-RateLimit-Remaining | Number of requests remaining in current window |
| X-RateLimit-Reset | Unix timestamp when rate limit resets |
| Retry-After | Seconds 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
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
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
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: