Coinme Risk SDK for Android Native Apps
Introduction
The Android Coinme Risk Engine SDK is a Kotlin library, distributed privately via Cloudsmith, that allows you to interact with the Coinme Risk Engine from your application. It provides utilities that allow you to integrate against the Coinme risk engine for the various transactional flows in your application so that Coinme may appropriately assess transactional risk when processing transactions.
Note:In order to utilize Coinme transactional services from within your application, you must implement and use the Coinme Risk Engine SDK.
What is it?
The Coinme Risk Engine aggregates data about user behavior for your application. It collects:
- Device data such as the type of device, OS name and version, etc.
- Location data such as where the user is connecting from.
- Connection data such as if the user is using a proxy or VPN, etc.
- Behavioral data such as how a user is interacting with your application, how quickly they are entering data into fields, use of clipboard functions, etc.
This data is used to determine the relative riskiness of the user / transaction.
Why is Risk Tagging Important?Risk tagging allows the SDK to track user interactions tied to specific actions within your application. When an element is tagged, the risk engine can better assess whether a user is behaving normally or if suspicious automation patterns are detected.
As an example, if the risk engine determines that the user location changes suddenly via a VPN to access a region restricted transaction type, then the engine may determine automation is at play and may rank the transaction as high risk.
Implementing the Android SDK
This package is not publicYou will need an auth token in order to install it. You may obtain this by working with the Coinme business development team.
What You'll Need to Get Started
Before integrating the SDK, you will need the following credentials from the Coinme business development team:
| Credential | Required For | Notes |
|---|---|---|
| Cloudsmith auth token | Accessing the library | Required to access the private library in Cloudsmith |
clientId | RiskEngineSetupOptions | Environment-specific — you will need one for development and one for production |
partnerId | getPartnerSessionTag() | Passed via GetPartnerSessionTagOptions, this is your Partner identifier needed for integration with Coinme APIs |
⚠️ You will need two clientIds, one for your development builds and one for your prod builds; you may obtain these from the Coinme business development team. It is very important that you pass the correct mode and clientId properties into the risk engine based on development or production usage, otherwise you may not stream your behavioral data to the correct environment, which can severely impact the risk engine’s ability to assess risk. This would ultimately negatively impact your transaction approvals.
Installation
Set Your Entitlement Token
Add your token to local.properties file in your project root directory:
COINME_TOKEN=<YOUR_ENTITLEMENT_TOKEN>Replace <YOUR_ENTITLEMENT_TOKEN> with the token provided by the Coinme business development team.
Note: local.properties is already gitignored by Android Studio to keep your tokens secure, but it is good to ensure this token is not exposed and the file is in your .gitignore
Add the SDK Repository and Dependency to your project
Add the repository to either your settings.gradle OR build.gradle.kts depending on your setup
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven {
name = "CoinmeSDK"
url = uri("https://dl.cloudsmith.io/${findProperty("COINME_TOKEN") ?: ""}/coinme/coinme-sdk-mobile/maven/")
}
}
}allprojects {
repositories {
google()
mavenCentral()
maven {
name = "CoinmeSDK"
val token = project.findProperty("COINME_TOKEN")?.toString() ?: ""
url = uri("https://dl.cloudsmith.io/$token/coinme/coinme-sdk-mobile/maven/")
}
}
}Then in your app/build.gradle.kts add the dependency
dependencies {
implementation("com.coinme:risk-sdk-android:1.0.0")
}Google Play Requirements
Before releasing your application with the Coinme Risk SDK, update your Google Play settings in your developer portal.
Privacy Policy
Update your Google Play Store privacy policy with the following message:
For fraud protection purposes only, (1) we collect your Battery Usage, Device Identifier, Device Storage, MAC Address, and SIM information; (2) we also collect enough information to determine if you are trying to fake your current location by using a VPN, VPN apps with location spoofing, or other related tools.
Data Safety
For the Data Safety section in the Google Play Console:
- Navigate to App content > Data safety in your Play Console
- Declare the following data types are collected:
- Location (Approximate and Precise)
- Device or other IDs (Device ID)
- App info and performance (Crash logs, Diagnostics)
- Files and docs (for storage-related fraud detection)
Note: You may need to add any other data types your app collects beyond what the SDK requires. For easier setup, you can download and import the Data Safety CSV file from the Sardine SDK documentation if provided by your integration team.
Required Permissions
Add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />Permission usage:
| Permission | Usage |
|---|---|
INTERNET | Network communication for fraud detection |
ACCESS_WIFI_STATE | Get user's WiFi name and status |
ACCESS_NETWORK_STATE | Get user's network information and state |
READ_PHONE_STATE | Get phone and network info (MNC, MCC, IMEI, phone number, phone type, SIM number) |
USE_BIOMETRIC / USE_FINGERPRINT | Get user's biometric authentication settings (Face or Fingerprint) |
WRITE_EXTERNAL_STORAGE | Write data to check re-installation behavior |
READ_EXTERNAL_STORAGE | Get external storage status, total size, free size |
ACCESS_COARSE_LOCATION / ACCESS_FINE_LOCATION | Get user's GPS location for fraud detection |
READ_GSERVICES | Get Device GSF ID (Google Services Framework ID) |
Note: Some permissions (like location and phone state) are considered dangerous permissions on Android 6.0+ and require runtime permission requests. Ensure your app handles these properly.
ProGuard Configuration
If you use ProGuard or R8 for code obfuscation, add the following rules to your proguard-rules.pro file:
# Keep Google Play Services classes
-keep class com.google.android.gms.** { *; }
-keep class com.google.android.gms.tasks.** { *; }
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient { *; }
# Keep Sardine SDK classes
-keep class ai.sardine.** { *; }
-keepclassmembers class ai.sardine.** { *; }
Implementation
Privacy & Compliance Notice
Important: If you use the Behavior Biometrics feature (enableBehaviourBiometrics = true), please ensure that your end users agree to your privacy policy before you begin collecting their Behavior Biometric data. This is required for compliance with privacy regulations.
Configuration Options
RiskEngineSetupOptions
| Option | Type | Required | Description |
|---|---|---|---|
mode | Mode | Yes | Used to point to environment .test or .prod |
clientId | String | Yes | Your environment-specific Client ID |
partnerId | String | Yes | Partner Identifier |
customerId | String? | No | Customer/User's identifier |
sessionKey | String? | No | Session key (automatically generated if not provided) |
flow | FlowType? | No | Current User flow (Onboarding, CardTransaction, or CardLinking) |
region | AppRegion | No | Your app's region of service (.default(US), .ca, .eu, .au, .in) |
enableBehaviorBiometrics | Bool | No | Enabled behavior tracking (default: true) |
enableClipboardTracking | Bool | No | Enable clipboard tracking (default: false) |
enableFieldTracking | Bool | No | Enable automatic field tracking (default: true) |
setCloudEntitlements | Bool | No | Enable iCloud feature (default: false, requires additional setup) |
FlowType Options
FlowType.Onboarding- New user registration flowFlowType.CardTransaction- Payment/card transaction flowFlowType.CardLinking- Adding payment methods flow
sessionKey
The sessionKey is a unique identifier for tracking a specific user session.
Once a key is provided for the set up, it will be cached for the duration of the app's active session. If no value is provided, the key will be automatically generated.
You will want to invoke .getPartnerSessionTag() to get an updated value that our backend will use to associate collected user data and risk score. Failure to call this and get the expected session key value may result in loss of data for accurate risk assessment.
Using .updateCoinmeRiskEngine() with a new key will override and update the cached value.
To clear a sessionKey, you may call .resetStoredSessionKey()
Important:When you call
getPartnerSessionTag(), the returnedwebSessionIDautomatically becomes the active session key. All subsequent calls toupdateCoinmeRiskEngine()will use this session key unless you explicitly provide a different one.
getPartnerSessionTag()
Retrieve the session tag from the backend API. The resulting webSessionID is automatically used to update the CoinmeRiskEngine configuration.
suspend CoinmeRiskEngine.getPartnerSessionTag(options: GetPartnerSessionTagOptions): SessionTagDataRequest body parameters for GetPartnerSessionTagOptions:
| Param | Type | Required | Description |
|---|---|---|---|
partnerId | String | Yes | Your partner identifier |
accountId | String | Yes | The customer ID |
fingerprint | String | Yes | The device fingerprint |
additionalHeaders | Dict<String, String> | No | Additional headers that may be included if needed by the backend |
timeout | Int | No | Request timeout in milliseconds (default: 10000) |
Initialize the SDK
Initialize the Risk Engine in your Activity's onCreate():
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val options = RiskEngineSetupOptions(
mode = Mode.Prod, // Use Mode.Test for testing
clientId = "your-client-id",
enableBehaviourBiometrics = true,
enableFieldTracking = false // Set to false for manual tracking
)
CoinmeRiskEngine.setupCoinmeRiskEngine(this, options)
}
}Note: Initializing the configuration automatically calls submit(), no need to do it manually. If you need to update the configuration, please use update() method.
Update the SDK
You can update the configuration with flow, sessionKey and customerId options:
CoinmeRiskEngine.updateCoinmeRiskEngine(
RiskEngineUpdateOptions(
sessionKey = "new-session-key",
flow = "new-flow",
customerId = "customer-id")Submit Data Before Transactions
Submits all collected behavioral and device date to the backend for risk assessment. Use callback version to ensure data is submitted before making subsequent API calls.
CoinmeRiskEngine.submit(
onSuccess = {
// Data successfully submitted - safe to proceed
lifecycleScope.launch {
processCardPayment()
}
},
onError = { error ->
Log.e("RiskSDK", "Submission failed", error)
handleError(error)
}
)What it collects:
- Sensor data (motion, orientation, pressure)
- Behavioral biometrics (typing patterns, interaction timing)
- Device context (clipboard activity, focus patterns)
- Page/screen engagement metrics
When to call:
- Before payment/transaction API calls
- Before critical actions (login, signup, money transfer)
- After form completion or user interaction flow
Other Utility Methods
Setup Risk Engine (Factory Method)
Initializes the Risk Engine singleton. Safe to call multiple times - returns existing instance if already initialized.
CoinmeRiskEngine.setupCoinmeRiskEngine(
activity: Activity,
options: RiskEngineSetupOptions
)Update Configuration
Updates the runtime configuration (customer ID, session key, flow). Note: This method may throw exceptions if the update fails. Wrap in try-catch for production:
CoinmeRiskEngine.updateCoinmeRiskEngine(config: RiskEngineUpdateOptions)Get Current Config
Returns the current runtime configuration
CoinmeRiskEngine.getCoinmeRiskEngineConfig(): RiskEngineUpdateOptionsReset Session
Resets the stored session key.
CoinmeRiskEngine.resetStoredSessionKey()Reset SDK
Clears the singleton instance and cleans up resources.
CoinmeRiskEngine.reset()Manual Input Field Tracking
If you choose to manually track input fields, first disabled automatic field tracking in the configuration. This can be done by ensuring
enableFieldTracking = falsewhen you set options for theCoinmeRiskEngine.
How to set up custom fields for tracking:
// Track text changes
emailEditText.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
CoinmeRiskEngine.trackTextChange("email", s?.toString() ?: "")
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun afterTextChanged(s: Editable?) {}
})
// Track focus changes
emailEditText.setOnFocusChangeListener { _, hasFocus ->
CoinmeRiskEngine.trackFocusChange("email", hasFocus)
}Be descriptive when assigning a value for viewId ("email", "password", "debitCardNumber", etc)
Tracking Methods
Track custom events and user interactions
// Track a user action
val data = JSONObject().apply {
put("action", "card_transaction_started")
put("amount", 149.99)
put("currency", "USD")
}
CoinmeRiskEngine.trackCustomData(data)Or use the Map extension for convenience
val data = mapOf(
"action" to "card_payment_initiated",
"amount" to 299.99
).toJSONObject()
CoinmeRiskEngine.trackCustomData(data)Track Text Change
Track text input in a text field
CoinmeRiskEngine.trackTextChange(viewId: String, text: String)Track Focus Change
Track focus change events on a field or UI component
CoinmeRiskEngine.trackFocusChange(viewId: String, isFocus: Boolean)Note: If referencing the same UI component but calling various tracking methods, make sure to use the same viewId.
Updated 18 days ago