FraudSense Developer Docs
Real-time device intelligence and fraud scoring API for banks and fintechs. Integrate in 10 minutes. No contracts required.
On this page
What is FraudSense?
FraudSense is a device intelligence platform that detects fraud at the device level — before transactions are processed. It works by running an SDK silently inside your mobile app, collecting 18+ signals from the device, and returning a real-time risk score via API.
| Component | Description |
|---|---|
| SDK | React Native module that collects device signals (sensors, GPS, battery, behavior, network) |
| API | REST API that scores device risk, stores history, and returns named risk labels |
| Portal | Self-serve dashboard for API key management and usage monitoring |
How it works
// 1. SDK initializes silently at app startup // 2. Collectors run in background (sensors, GPS, battery, network, behavior) // 3. At a transaction point, your app calls getReport() // 4. SDK evaluates 18+ signals → sends to API // 5. API adds server-side signals (IP intelligence, device history, replay detection) // 6. Final risk score returned in < 200ms Your App → FraudSense SDK → Risk API → Score + Labels + Recommendation
Base URL
https://api.getfraudsense.com
Quick Start
Get from zero to a working risk score in under 10 minutes.
Get your API key
Visit the developer portal → click "Get Free API Key" → fill in your details. Your API key is generated instantly.
fs_test_ in test mode. You get 1,000 free calls per month on all tiers.Install the SDK
Copy the sdk/ folder from the GitHub repo into your React Native project root. Then install dependencies:
npm install expo-battery expo-crypto expo-device expo-location expo-network expo-sensors expo-secure-store
Initialize at app startup
import FraudSense from './sdk/FraudSense'; await FraudSense.init({ apiKey: 'fs_test_xxxx', endpoint: 'https://api.getfraudsense.com', collectGPS: true, debug: false, });
Score a transaction
// At login, payment, or withdrawal const report = await FraudSense.getReport({ event: 'PAYMENT' }); if (report.riskLevel === 'CRITICAL') blockTransaction(); if (report.riskLevel === 'HIGH') blockAndFlag(); if (report.riskLevel === 'MEDIUM') requestOTP(); if (report.riskLevel === 'LOW') allowTransaction();
Authentication
FraudSense uses two authentication methods depending on the caller.
API Key — SDK and server-to-server calls
Pass your API key in the X-FraudSense-Key header for all risk scoring and event endpoints.
X-FraudSense-Key: fs_test_eb9d00476517470a95f6a6566e5deaf4
JWT Token — dashboard and management
Use a Bearer token in the Authorization header for account management endpoints.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Get a JWT token
curl -X POST https://api.getfraudsense.com/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"[email protected]","password":"yourpassword"}'
SDK Installation
Requirements
| Requirement | Version |
|---|---|
| React Native | 0.73+ |
| Expo SDK | 54 |
| Node.js | v20.19.4 |
| iOS | 13+ |
| Android | API 21+ |
Step 1 — Copy SDK folder
Clone or download the SDK from GitHub and copy the sdk/ folder into your project:
git clone https://github.com/getfraudsense/sdk.git cp -r fraudsense-sdk/sdk ./your-app/sdk
Step 2 — Install dependencies
npx expo install expo-battery expo-crypto expo-device expo-location \ expo-network expo-sensors expo-secure-store expo-localization
Step 3 — Add permissions (iOS)
Add to your app.json:
{
"expo": {
"plugins": [
["expo-location", {
"locationWhenInUsePermission": "FraudSense needs location to verify transaction safety."
}]
]
}
}
Initialization
Call FraudSense.init() once at app startup — ideally on the splash screen before navigating to login.
import FraudSense from './sdk/FraudSense'; await FraudSense.init({ apiKey: 'fs_test_xxxx', // Required — your API key endpoint: 'https://api.getfraudsense.com', // Required collectGPS: true, // Optional — default true reportInterval: 10000, // Optional — ms between auto-reports (default 10s) debug: false, // Optional — logs to console });
Configuration options
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | — | Your FraudSense API key. Required. |
| endpoint | string | — | API base URL. Required. |
| collectGPS | boolean | true | Enable GPS collection. Requires location permission. |
| reportInterval | number | 10000 | Milliseconds between automatic background reports. |
| debug | boolean | false | Print SDK logs to console. |
Event Types
Pass an event type to getReport() so the risk engine applies the correct signal weights. A withdrawal check is 2x more sensitive to GPS spoofing than a login check.
// Each event type applies different signal weights FraudSense.getReport({ event: 'LOGIN' }); FraudSense.getReport({ event: 'REGISTER' }); FraudSense.getReport({ event: 'PAYMENT' }); FraudSense.getReport({ event: 'WITHDRAWAL' }); FraudSense.getReport({ event: 'PROFILE_UPDATE' });
| Event | Use case | Sensitivity focus |
|---|---|---|
LOGIN | User signs in | Behavioral — catches credential stuffing |
REGISTER | New account created | Device — catches fake account farms |
PAYMENT | Send or receive money | Location — catches GPS spoofing |
WITHDRAWAL | Withdraw funds | All signals — maximum sensitivity |
PROFILE_UPDATE | Change email, phone, password | Behavioral — catches account takeover |
SDK Methods
getReport(options?)
Returns a full risk report for the current session. This is the primary method you will call at transaction checkpoints.
const report = await FraudSense.getReport({ event: 'PAYMENT' }); // Returns: RiskReport object (see Response Format)
getRiskScore(options?)
Returns just the numeric risk score (0–100). Lighter than getReport() if you only need the number.
const score = await FraudSense.getRiskScore({ event: 'LOGIN' }); // Returns: number (0-100)
getDeviceId()
Returns the stable SHA-256 device fingerprint. Persists across app reinstalls.
const deviceId = FraudSense.getDeviceId(); // Returns: string — e.g. "fs_a3f9b2c1d4e5..."
Other methods
| Method | Description |
|---|---|
FraudSense.flush() | Force-send pending events to the backend immediately |
FraudSense.pause() | Pause all collectors (e.g. when app goes to background) |
FraudSense.resume() | Resume collectors after pause |
FraudSense.reset() | Clear all local data and session state |
Event Hooks
Subscribe to real-time events from the SDK using FraudSense.on().
// React when risk level changes FraudSense.on('riskLevelChanged', (level, score) => { if (level === 'CRITICAL') blockAllTransactions(); }); // Log every fraud flag as it fires FraudSense.on('flagTriggered', (flag) => { analytics.track('fraud_signal', flag); }); // Get updated report every 10 seconds FraudSense.on('reportUpdated', (report) => { setRiskBadge(report.riskLevel); });
Behavioral hooks
Add these to your input components to collect behavioral signals:
// On TextInput keystrokes <TextInput onChangeText={(text) => { setValue(text); FraudSense.behavior.recordKeyPress(); }} /> // On touch events <View onResponderGrant={(e) => FraudSense.behavior.recordTouch(e)}> // On paste FraudSense.behavior.recordPaste(); // On screen navigation FraudSense.behavior.recordScreenChange('PaymentScreen');
Auth Endpoints
Register
{
"email": "[email protected]",
"password": "SecurePass1!",
"companyName": "Acme Bank"
}Risk Score
The primary endpoint. Submit a device report and receive a scored risk assessment with labels, recommendations, IP intelligence, and device history.
X-FraudSense-Key header. When using the SDK, this endpoint is called automatically — you do not need to call it directly.Request body
{
"deviceId": "fs_a3f9b2c1...", // Required — stable device fingerprint
"sessionId": "sess_20260411...", // Required — unique per session
"eventType": "PAYMENT", // Recommended — LOGIN|REGISTER|PAYMENT|WITHDRAWAL|PROFILE_UPDATE
"riskScore": 30, // SDK client-side score (0-100)
"triggeredFlags": [], // Array of triggered signal objects
"deviceProfile": {
"model": "iPhone 15",
"os": "iOS 17",
"isEmulator": false,
"isRooted": false
},
"locationProfile": {
"lat": 25.2048,
"lon": 55.2708
},
"behaviorProfile": {
"movementScore": 0.4,
"typingWPM": 45,
"sessionHour": 14
}
}
Response
{
"deviceId": "fs_a3f9b2c1...",
"sessionId": "sess_20260411...",
"eventType": "PAYMENT",
"eventLabel": "Payment transaction",
"riskScore": 63,
"riskLevel": "HIGH",
"recommendation": "BLOCK - Hold payment for review",
"riskLabels": [
{ "code": "FAKE_DEVICE", "description": "Device is an emulator" }
],
"triggeredFlags": [ ... ],
"serverFlags": [ ... ],
"ipIntelligence": { ... },
"deviceHistory": { ... },
"scoredAt": "2026-04-11T05:00:00.000Z"
}
Device History
curl https://api.getfraudsense.com/v1/risk/history/fs_abc123 \
-H "X-FraudSense-Key: fs_test_xxxx"
API Keys
{"name":"Production Key"}Dashboard
Risk Signal Catalogue
FraudSense evaluates 18+ signals per session. Each signal carries a point value that contributes to the composite risk score. Trust signals reduce the score.
Critical signals (+35 to +40 points)
| Signal | Condition | Points |
|---|---|---|
| EMULATOR_DETECTED | Device is running in an emulator or simulator | +40 |
| REPLAY_ATTACK | Same sessionId submitted more than 3 times in 60 seconds | +40 |
| HOOK_TOOL_DETECTED | Frida, Xposed, or Cydia detected on device | +35 |
| CLOUD_PHONE_DETECTED | Virtual cloud phone environment detected | +35 |
| APP_TAMPERED | App signature mismatch — possible repackaging | +35 |
| GPS_IMPOSSIBLE_VELOCITY | Travel speed exceeds 900 km/h — GPS spoofing | +30 |
High signals (+20 to +30 points)
| Signal | Condition | Points |
|---|---|---|
| ROOT_JAILBREAK | Device has been rooted or jailbroken | +30 |
| SCREEN_SHARING | Screen broadcast or remote control active | +30 |
| SHORT_UPTIME | Device uptime under 5 minutes — possible reset | +25 |
| BATTERY_ALWAYS_CHARGING | Charging ratio over 95% during session | +25 |
| LOCATION_NEVER_CHANGES | Location entropy under 0.1 — fixed farm | +20 |
| ZERO_MOVEMENT | Accelerometer variance under 0.05 | +20 |
| TOUCH_TOO_UNIFORM | Touch speed variance under 5ms — scripted input | +20 |
| NO_SIM_CARD | No SIM card detected in device | +20 |
| SUSPECTED_RESET | Uptime under 60 seconds — repeated resets | +20 |
Medium signals (+10 to +15 points)
| Signal | Condition | Points |
|---|---|---|
| ALWAYS_PORTRAIT | Portrait orientation ratio over 99% | +15 |
| TIMEZONE_GPS_MISMATCH | Timezone offset over 2 hours from GPS location | +15 |
| ABNORMAL_TYPING_SPEED | Typing speed over 200 WPM | +15 |
| NETWORK_HYPER_SWITCHING | More than 5 network type changes per minute | +15 |
| ODD_HOUR_SESSION | Session started between 1AM and 5AM | +10 |
| VPN_DETECTED | VPN or proxy interface active | +10 |
| COPY_PASTE_DETECTED | Clipboard change detected on form field | +10 |
| MAX_BRIGHTNESS_ALWAYS | Screen brightness above 95% throughout session | +10 |
Trust signals (reduce score)
| Signal | Condition | Points |
|---|---|---|
| NATURAL_MOVEMENT | Accelerometer variance over 0.3 | -10 |
| HAS_SIM_CARD | SIM card present in device | -5 |
| NORMAL_BATTERY_CYCLE | Normal mix of charge and discharge observed | -5 |
| REALISTIC_LOCATION | Location entropy between 0.2 and 0.9 | -5 |
| NORMAL_UPTIME | Device uptime over 1 hour | -5 |
Risk Labels
Named labels explain why a device scored HIGH — more actionable than a raw score alone. Returned in the riskLabels array.
| Code | Description | Typical trigger |
|---|---|---|
| FAKE_DEVICE | Device is an emulator or virtual environment | EMULATOR_DETECTED |
| TAMPERED_DEVICE | Device has been rooted or jailbroken | ROOT_JAILBREAK |
| LOCATION_SPOOFING | GPS coordinates appear to be faked | GPS_IMPOSSIBLE_VELOCITY |
| DEVICE_FARM | Device shows signs of automated farm operation | BATTERY_ALWAYS_CHARGING + ZERO_MOVEMENT |
| BOT_BEHAVIOR | Input patterns suggest automated or scripted activity | TOUCH_TOO_UNIFORM or ABNORMAL_TYPING_SPEED |
| CREDENTIAL_STUFFING | Credentials pasted at login — possible stuffing attack | COPY_PASTE_DETECTED on LOGIN event |
| SUSPICIOUS_NETWORK | VPN active during a financial transaction | VPN_DETECTED on PAYMENT or WITHDRAWAL |
| IDENTITY_MISMATCH | Device timezone does not match GPS location | TIMEZONE_GPS_MISMATCH |
| STATIC_DEVICE | Device location never changes — possible fixed farm | LOCATION_NEVER_CHANGES |
| CLEAN | No risk labels detected — device appears legitimate | No flags triggered |
Response Format
Risk levels
| Score | Level | Recommendation |
|---|---|---|
| 0 – 20 | LOW | ALLOW — proceed normally |
| 21 – 45 | MEDIUM | STEP_UP — request OTP or biometric |
| 46 – 70 | HIGH | BLOCK — require manual review |
| 71 – 100 | CRITICAL | BLOCK_AND_FLAG — escalate immediately |
Full response schema
| Field | Type | Description |
|---|---|---|
| deviceId | string | Stable SHA-256 device fingerprint |
| sessionId | string | Unique identifier for this session |
| eventType | string | Event type used for scoring |
| eventLabel | string | Human-readable event label |
| riskScore | integer | Composite risk score 0–100 |
| riskLevel | string | LOW / MEDIUM / HIGH / CRITICAL |
| recommendation | string | Event-specific action recommendation |
| riskLabels | array | Named labels explaining why the score is high |
| triggeredFlags | array | SDK-side signals that fired |
| serverFlags | array | Server-side signals that fired |
| ipIntelligence | object | IP geo, ISP, proxy/datacenter, GPS mismatch |
| deviceHistory | object | Historical risk summary for this device |
| scoredAt | string | ISO timestamp of the scoring |
IP Intelligence
Included automatically in every risk score response. No extra configuration needed.
| Field | Type | Description |
|---|---|---|
| ip | string | Client IP address |
| country | string | Country name |
| countryCode | string | ISO country code (e.g. AE, SA) |
| region | string | Region or state |
| city | string | City name |
| isp | string | Internet service provider |
| isProxy | boolean | True if IP is a known proxy |
| isDatacenter | boolean | True if IP is a cloud/datacenter IP |
| mismatchWithGPS | boolean | True if IP location is over 100km from GPS |
| distanceKm | integer | Distance in km between IP and GPS location |
| riskSignals | array | IP-specific risk flags e.g. IP_GPS_MISMATCH |
Device History
Every response includes a history summary for the device — no extra call needed.
| Field | Type | Description |
|---|---|---|
| totalSessions | integer | Total number of sessions for this device |
| highRiskCount | integer | Sessions scored HIGH or CRITICAL |
| criticalCount | integer | Sessions scored CRITICAL |
| lastHighRiskAt | string | Timestamp of last HIGH/CRITICAL session |
| firstSeenAt | string | When this device was first seen |
| historicalLabels | array | Past risk labels with count and last seen timestamp |
| riskTrend | string | INCREASING / STABLE / DECREASING / UNKNOWN |
| isNewDevice | boolean | True if this is the first session for this device |
Status Codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process the response normally |
| 400 | Bad request | Check required fields — deviceId is always required |
| 401 | Unauthorized | Check your API key or JWT token |
| 403 | Forbidden | Account suspended — contact support |
| 404 | Not found | Check the endpoint URL |
| 429 | Rate limited | Slow down requests — max 1,000/15 min |
| 500 | Server error | Retry after a short delay |
Changelog
v1.1.0 — April 2026
- Added event types (LOGIN, REGISTER, PAYMENT, WITHDRAWAL, PROFILE_UPDATE)
- Added named risk labels (FAKE_DEVICE, CREDENTIAL_STUFFING, etc.)
- Added IP intelligence layer with GPS mismatch detection
- Added device history in every risk score response
- Added replay attack detection (session reuse within 60 seconds)
- Added deeper behavior collection (rage taps, scroll, paste ratio)
- Added 8 new risk signals (NO_SIM_CARD, SHORT_UPTIME, SCREEN_SHARING, etc.)
v1.0.0 — March 2026
- Initial release
- Device fingerprinting with SHA-256 (7 components)
- 6 collectors: device, sensor, location, battery, network, behavior
- Risk scoring API with Stripe billing
- Self-serve developer portal
Support
Contact
Email: [email protected]
GitHub Issues: github.com/getfraudsense/api
Before reaching out
- Check the Status Codes section for common errors
- Verify your API key is active in the developer portal
- Make sure
deviceIdis included in every request - For SDK issues, enable
debug: trueand check console logs