Integrating the Coinme Risk Engine
Introduction
The Coinme Risk Engine SDK is a library, distributed as an NPM package, 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.
The Coinme Risk Engine SDK is currently only available in React and React Native. Coinme is working on implementations for other languages, such as Flutter and Swift. Coinme will provide an update when this framework support is available.
In order to utilize Coinme payment processing services from within your application (i.e. buying/selling with a debit card), 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, browser, 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 includes how a user interacts with your application, how quickly they enter data into fields, 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 behaves normally or if suspicious automation patterns are detected.
For example, if the risk engine determines that the user is connected with an unknown browser type via a VPN or proxy and that interactions with elements of your app are happening much faster than would be normal for a human, then the engine may determine automation is at play and rank the transaction as high risk.
How to Use the SDK
The Coinme Risk Engine SDK is an NPM package. You may install it as follows.
This package is not public; you will need to access credentials or a package key in order to install it. You may obtain this by working with the Coinme Business Development team.
Installation
To install the package, you must configure your .npmrc or .yarnrc (or equivalent) to include your authentication token:
@coinme:registry=https://npm.coinme.com/coinme-security-wrapper/
//npm.coinme.com/coinme-security-wrapper/:_authToken=<AUTHENTICATION_TOKEN>
always-auth=trueReplace
<AUTHENTICATION_TOKEN>with your provided token.
Then install via:
NPM:
npm install @coinme/risk-sdk-jsYarn:
yarn add @coinme/risk-sdk-jsPNPM:
pnpm add @coinme/risk-sdk-jsQuickStart
You can use the Coinme Risk Engine SDK in your project by following the steps below.
Setup the Coinme Risk Engine
The setup function initializes the Risk Engine and applies all necessary configurations.
import { setupCoinmeRiskEngine } from "@coinme/risk-sdk-js";
setupCoinmeRiskEngine({
mode: "test",
clientId: "client-id",
})
.catch((error) => {
console.error("Error setting up Risk Engine:", error);
})
.finally(() => {
console.log("Risk Engine setup complete!");
});
Note:
setupCoinmeRiskEngineis not sufficient in and of itself to use the risk SDK; this call is to be made when your app starts up in order to initialize the risk engine. There are other conditions which will require you to update additional parameters dynamically during the user session, such as when a user starts a high-risk action like a transaction, after a user has onboarded and now there is acustomerId, etc. In these cases, useupdateCoinmeRiskEngine.
Key Takeaway: When should I use this?
You should call
setupCoinmeRiskEnginewhen your application instantiates.
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 correctmodeandclientIdproperties 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.
Get Current Configuration
To check which risk parameters are applied, use:
import { getCoinmeRiskEngineConfig } from "@coinme/risk-sdk-js";
const config = getCoinmeRiskEngineConfig();
console.log(config);
Note that the configuration is only available after setup completes.
Update Coinme Risk Engine Configuration
While setup handles initial configuration, you can and should manually update specific parameters when needed. An example would be after a user has onboarded or logged in, as at this point you will have a customerId available to you; this helps the risk engine associate user behavior with your user.
Another example is when you wish to update the flow identifier being sent to the risk engine. This is necessary so that when your user is entering a specific flow in your app such as onboarding, linking a payment method, or transacting, these special activities will be properly tagged; the risk engine examines user behavior in such flows closely. Therefore, you should tag these flows by updating the risk engine config by providing a flow identifier as seen below.
A flow identifier is a string that acts as a tag to uniquely identify that data the risk engine is logging belongs to a contiguous and related flow of user actions.
import { updateCoinmeRiskEngine } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "customer-123",
flow: "customer-onboarding",
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("Configuration updated");
});
Flow Types
Certain flows are universal and are important to the operation of the Coinme Risk Engine. You can use a pre-defined FlowType in these cases to ensure you are properly tagging these flows. We export a FlowType enumeration that exposes these common flows, which the risk engine can understand and use when making risk decisions. This enum is structured as follows:
export enum FlowType {
Onboarding = 'customer-onboarding',
CardTransaction = 'card-transaction',
CardLinking = 'payment-method-linking',
}For maximum value, you should use the appropriate FlowType as the flow identifier when you are onboarding users, adding a payment method, or undertaking a transaction.
Why Use Flow Identifiers?
Flow identifiers help group multiple actions into a single session so that risk is assessed based on contextual user behavior. Instead of analyzing each interaction separately, the risk engine can detect patterns within a specific user journey.
For example:
- If a user enters payment details too quickly after onboarding, this might indicate a scripted attack rather than a real person.
- If a user switches IP addresses midway through a transaction, it could indicate a fraud attempt.
- If a user is interacting normally but suddenly switches to rapid inputs, the system can adapt its risk evaluation in real time.
By tagging actions with the correct FlowType, your application provides the risk engine with the necessary context to assess transactional legitimacy.
The Coinme risk engine requires the specific flow identifiers exposed by the risk SDK for any of these pre-defined flow types; if you do not use the supported identifier, your users and transactions may not be appropriately scored and you will be at risk of high denial rates for your transactions.
Usage Examples
Each example demonstrates when and how to use updateCoinmeRiskEngine with a specific flow type.
Example 1: Onboarding Flow
When a new user signs up, you must tag their session as onboarding so the risk engine can monitor suspicious activities.
import { updateCoinmeRiskEngine, FlowType } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "new-user-456",
flow: FlowType.Onboarding,
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("User onboarding flow tracked.");
});
When to use?
Call this when the user starts the signup process.
Example 2: After Onboarding or Sign-in
After a new user finishes signing up, or after a user has signed in, you must update the risk engine with their userID so that data can now be associated with the user rather than a session. This allows the risk engine to aggregate and interpret data over time.
import { updateCoinmeRiskEngine, FlowType } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "user-456",
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("User ID now tracked.");
});
When to use?
Call this right after the user completes the signup or login process and the user’s permanent ID is known.
Example 3: Linking a New Card
If a user is adding a new payment method, this is a high-risk action that must be monitored.
import { updateCoinmeRiskEngine, FlowType } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "user-789",
flow: FlowType.CardLinking,
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("Card linking flow tracked.");
});
When to use?
Call this when the user enters a process to add a payment method.
Example 4: Processing a Card Transaction
When a user makes a purchase or transaction, you should explicitly tag it.
import { updateCoinmeRiskEngine, FlowType } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "user-123",
flow: FlowType.CardTransaction,
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("Card transaction flow tracked.");
});
When to use?
Call this when the user enters a transactional flow such as when they start a buy or sell transaction.
Note on Using the
updateCoinmeRiskEngineProperly:
TheupdateCoinmeRiskEnginefunction is designed to modify the risk engine's configuration after the initial setup. However, since bothsetupCoinmeRiskEngineandupdateCoinmeRiskEngineare asynchronous, calling them sequentially without ensuring the setup is complete may cause the update function to override the initial configuration.
How to Update Correctly
- Ensure that
setupCoinmeRiskEngineis completed before callingupdateCoinmeRiskEngine. - If calling both on the first render (e.g., in a React setup), chain them properly using
awaitor a state check. - Calling
updateCoinmeRiskEnginebeforesetupCoinmeRiskEnginefinishes may lead to an incomplete or overridden configuration.
Example: Correct Usage - Await the Setup Before Updating
async function initializeRiskEngine() { await setupCoinmeRiskEngine({ mode: "test", clientId: "client-id", }); console.log("Setup complete:", getCoinmeRiskEngineConfig()); await updateCoinmeRiskEngine({ customerId: "[email protected]", flow: "flow-id", }); console.log("Update complete:", getCoinmeRiskEngineConfig()); } initializeRiskEngine();Why is this correct?
- Ensures setup completes before update can be called
Example: Incorrect Usage - Running Setup and Update in Parallel
setupCoinmeRiskEngine({ mode: "test", clientId: "client-id", }); updateCoinmeRiskEngine({ customerId: "[email protected]", flow: "flow-id", });Why is this wrong?
updateCoinmeRiskEnginemay execute beforesetupCoinmeRiskEnginecompletes.- The update call might override important setup details.
- Leads to unpredictable behavior in the risk engine configuration.
Key Takeaway: When should I use this?
You should call
updateCoinmeRiskEngine:
- After a user has onboarded or logged in, and you have a
customerId
- By updating the risk engine with the
customerId, you ensure that the risk engine can understand the user’s behavior over time, which leads to better risk modeling.- When a user begins a flow that needs to be explicitly identified, such as onboarding, linking a payment method, or transacting.
- These are key actions that should be tagged with the correct
flowidentifier.
Tagging Elements
You can add Risk attributes to elements, components, or strings with the addCoinmeRiskTag function. The risk engine SDK automatically detects these tags and will flow behavioral metrics into the risk engine from any tagged entities automatically.
Examples:
- Returning a pre-tagged HTML element:
import { addCoinmeRiskTag } from "@coinme/risk-sdk-js";
// Using a raw HTML string
const elementAsString = addCoinmeRiskTag({
element: '<div>Hello, World!</div>',
riskIdentifier: 'my-element',
});
console.log(elementAsString); // Outputs a div with the risk data attribute 'my-element' added.- Tagging an existing DOM element:
import { addCoinmeRiskTag } from "@coinme/risk-sdk-js";
// Using an existing DOM element
const divElement = document.createElement('div');
divElement.textContent = 'Hello, World!';
const taggedElement = addCoinmeRiskTag({ element: divElement, riskIdentifier: 'my-element' });
console.log(taggedElement.outerHTML); // Outputs a div with the risk data attribute 'my-element' added.- Tagging a React-Like object:
import { addCoinmeRiskTag } from "@coinme/risk-sdk-js";
// Tagging a React/Vue-style object
const reactLikeObject = {
type: 'div',
props: { children: 'Hello, World!' },
};
const taggedObject = addCoinmeRiskTag({ element: reactLikeObject, riskIdentifier: 'my-element' });
console.log(taggedObject);
// Outputs a react / vue style object with the risk data attribute 'my-element' added.Core Concepts
You must provide your
clientIdto use the SDK. If you don't have yourclientId, contact Coinme business development team.
The clientId uniquely identifies your partner integration within the Risk Engine.
- It is provided by Coinme during onboarding.
- Usually shared with other credentials like auth tokens or access scopes.
- Without it, the SDK will throw an error and refuse to initialize.
UnderstandingsessionKey
The sessionKey is a unique identifier for tracking a specific user session.
| Behavior | Outcome |
|---|---|
Provide sessionKey in setup | Used & stored for session |
Provide sessionKey in update | Overrides previous one |
No sessionKey provided | Auto-generated using FingerprintJS |
Call resetStoredSessionKey() | Clears stored key |
Resetting thesessionKey
import { resetStoredSessionKey } from "@coinme/risk-sdk-js";
resetStoredSessionKey();
Use this when:
- Logging out users.
- Switching accounts.
- Resetting state for tests.
Typical Session Flow Example
// Setup with auto-generated sessionKey
await setupCoinmeRiskEngine({
mode: 'prod',
clientId: 'client-id',
});
// Later — Update without providing sessionKey (uses stored one)
await updateCoinmeRiskEngine({
flow: 'customer-onboarding',
});
// On session end (e.g., logout)
resetStoredSessionKey();
// Start new user/session
await setupCoinmeRiskEngine({
mode: 'prod',
clientId: 'client-id',
});
API Reference
The Coinme Risk Engine SDK provides the following functions for interacting with the Risk Engine.
You can find detailed information about each function below
setupCoinmeRiskEngine
setupCoinmeRiskEngineSets up the Coinme Risk Engine with the provided options.
| Param | Type | Required | Description | |
|---|---|---|---|---|
mode | `'test' \ | 'prod'` | ✅ | Operating environment |
clientId | string | ✅ | Partner-specific risk engine client ID | |
partnerId | string | optional | Partner identifier | |
customerId | string | optional | Customer identifier | |
sessionKey | string | optional | Custom session tracking key | |
flow | `string \ | FlowType` | optional | Flow context |
Example:
import { setupCoinmeRiskEngine } from "@coinme/risk-sdk-js";
setupCoinmeRiskEngine({ mode: "test", clientId: "client-id" })
.catch((error) => {
console.error("Error setting up Risk Engine:", error);
})
.finally(() => {
console.log("Risk Engine setup complete!");
});
getCoinmeRiskEngineConfig
getCoinmeRiskEngineConfigRetrieves the latest risk assessment settings applied to the current session.
Returns:
Record<string, any>: An object containing the current Risk Engine configuration.- If no configuration has been set, it returns {}.
Example:
const config = getCoinmeRiskEngineConfig();
console.log(config); // Outputs: { partnerId: "...", sessionKey: "...", ... }
updateCoinmeRiskEngine
updateCoinmeRiskEngineUpdates the Coinme risk assessment settings for the current session. This ensures that risk evaluations, such as device fingerprinting and geolocation tracking, are correctly applied.
Parameters:
| Param | Type | Required | Description | |
|---|---|---|---|---|
partnerId | string | optional | Partner identifier | |
customerId | string | optional | Customer identifier | |
sessionKey | string | optional | Override session key | |
flow | `string \ | FlowType` | optional | Flow context |
parentSessionKey | string | optional | Parent session key | |
enableBiometrics | boolean | optional | Enable biometric signals | |
enableGeoLocation | boolean | optional | Enable geo-location | |
enablePortScanning | boolean | optional | Enable port scanning |
Example:
import { updateCoinmeRiskEngine } from "@coinme/risk-sdk-js";
updateCoinmeRiskEngine({
customerId: "customer-123",
flow: "onboarding",
})
.catch((error) => {
console.error("Error updating configuration:", error);
})
.finally(() => {
console.log("Configuration updated");
});
addCoinmeRiskTag
addCoinmeRiskTagEnhances an element, component, or string representation of HTML by tagging the element with a risk tag. The risk engine SDK automatically detects these tags and will flow metrics into the risk engine from any tagged entities automatically.
Parameters:
| Prop | Type | Required | Description | ||
|---|---|---|---|---|---|
element | `HTMLElement \ | object \ | string` | ✅ | Target element |
riskIdentifier | string | ✅ | Unique risk tag |
Returns:
The same element with the risk tag applied.
Example:
import { addCoinmeRiskTag } from "@coinme/risk-sdk-js";
const element = addCoinmeRiskTag({
element: '<div>Hello, World!</div>',
riskIdentifier: 'my-element',
});
console.log(element); // Outputs a div tagged with the specified risk tag
withCoinmeRiskTag
withCoinmeRiskTagCreates a higher-order component that adds a risk tag to the props (or equivalent) of the wrapped component.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
Component | function | ✅ | The component function to wrap. |
id | string | ✅ | Unique risk tag to apply. |
Returns:
- A wrapped component with the risk tag attribute added to
propsor its equivalent.
Examples
Wrapping a simple component:
import { withCoinmeRiskTag } from "@coinme/risk-sdk-js";
const MyComponent = (props) => `<div>${props.text}</div>`;
const TaggedComponent = withCoinmeRiskTag(MyComponent, 'my-element');
console.log(TaggedComponent({ text: 'Hello, world!' }));
// Outputs a div tagged with the given risk tag
Wrapping an object-based component:
import { withCoinmeRiskTag } from "@coinme/risk-sdk-js";
const MyObjectComponent = (props) => ({
type: 'div',
props: { children: props.text },
});
const WrappedObject = withCoinmeRiskTag(MyObjectComponent, 'object-component');
console.log(WrappedObject({ text: 'Hello, world!' }));
// Outputs an object tagged with the specified risk tagUpdated about 1 month ago