How To: Migrate to the Coinflow Fraud SDK
Overview
The Coinflow Fraud SDK replaces the device-signal setup your mobile app does today for chargeback protection. Instead of installing and initializing a device module with credentials, reading a device ID, and attaching several protection headers, your app:
- Initializes the Coinflow Fraud SDK once with your
merchantId. - Asks it for headers at checkout time.
- Sends the single
x-device-idheader it returns on your Coinflow API request.
The SDK collects every device, session and purchase signal Coinflow uses to score a payment and packs them into that one header. You don’t configure individual signal sources, and you don’t need credentials from Coinflow to initialize it.
What changes for your integration
Who should migrate
This guide is for iOS, Android and React Native apps that call Coinflow’s APIs directly, either from the app or through your own backend.
No change is needed for:
- Web integrations using
<CoinflowPurchaseProtection>or the protection script on your site. - Coinflow’s hosted checkout (
<CoinflowPurchase>), which collects its own protection signals. React Native apps that render<CoinflowPurchase>keep passingdeviceIdfrom the existing device module; the Coinflow Fraud SDK’s header isn’t supported as that prop.
Keep following Implement Chargeback Protection for those.
Backward compatibility
Your current integration keeps working, and there is no cutoff date. Coinflow’s API accepts both the existing headers and the Coinflow Fraud SDK’s header on the same endpoints, so:
- You can migrate one app at a time, in a normal app release.
- Customers still on an older version of your app keep being protected after you ship the migrated version.
- No API, endpoint or request-body changes are required; only your protection headers change.
Prerequisites
- Chargeback protection enabled for your merchant account. Contact Coinflow’s integrations team if it isn’t.
- Your Coinflow
merchantId. - iOS: iOS 15 or later, built with Xcode 26 or later, and CocoaPods.
- Android:
minSdk24 or later, built with Gradle on JDK 17 or later. - React Native: a development build or bare React Native app, targeting iOS 15.1 or later. The SDK includes a native module, so it doesn’t run in Expo Go.
Migrate your app
Install the Coinflow Fraud SDK
iOS (Native)
Add the SDK to your Podfile, then run pod install:
The SDK isn’t on CocoaPods trunk, so the pod line points at its Git repository. See the iOS SDK README for the latest tag.
For a working setup, see the iOS example app.
Android (Native)
Some of the SDK’s signal sources are served outside Maven Central. Apply Coinflow’s settings plugin, which adds their repositories, in settings.gradle.kts:
The plugin is published to Maven Central, so keep mavenCentral() in pluginManagement. It works whether your app declares repositories in settings.gradle.kts or in a root allprojects block.
Then add the SDK to your app module:
For a working setup, see the Android example app.
React Native
Install the package. React Native autolinks its native module:
-
Expo: add the SDK’s config plugin to your app config, then rebuild. It adds the iOS SDK to your
Podfile, applies the iOS deployment-target fix the SDK needs, and adds the SDK’s Maven repositories to your Android build. -
Bare React Native (iOS): make the two
Podfilechanges in the package README, an extra pod line and apost_installdeployment-target fix, then runpod install. -
Android: usually no extra setup. If your app centralizes repositories in
settings.gradle(dependencyResolutionManagementwithrepositoriesMode), add Coinflow’scash.coinflow.fraud.repositoriessettings plugin toandroid/settings.gradle, as shown in the package README.
For a working setup, see the React Native example app.
Initialize the SDK once
Initialize as early as possible, at app launch or when the customer starts shopping, so signals are ready by checkout. Pass your merchantId and the environment that matches the Coinflow API you call: sandbox for api-sandbox.coinflow.cash, prod for production.
your-merchant-id below is an example value. Use your own Coinflow merchantId.iOS (Native)
initialize never throws, and calling it again has no effect. To switch merchant or environment at runtime, call it with force: true.
Android (Native)
Call initialize from your first Activity, passing the Activity itself so the SDK sees the screen that’s already showing:
initialize is a suspend function. It never throws, and calling it again has no effect. To switch merchant or environment at runtime, call it with force = true.
React Native
Wrap your app root in CoinflowProtectionProvider. It initializes the SDK once on mount, and re-initializes it if merchantId or env changes.
Attach the header at checkout
Right before each checkout, payment intent, redeem or subscription request, get the headers from the SDK and add them to the request.
iOS (Native)
Android (Native)
purchaseHeaders() is a suspend function. The example uses OkHttp; any HTTP client works the same way.
React Native
Outside a component, call CoinflowFraud.getPurchaseHeaders() instead.
If your backend calls Coinflow rather than the app, send the header value to your backend and forward it to Coinflow as x-device-id, unchanged. Treat it as opaque:
- Don’t parse, re-encode, trim or log-and-rebuild it.
- Allow header values up to 8 KB.
- Also forward the customer’s IP address in
x-coinflow-client-ip. Otherwise Coinflow scores the purchase against your server’s IP.
Remove the previous setup
Once the new header is in place, remove from your app:
- The device module and its initialization with the
appIdandpartnerIdCoinflow supplied. - Calls that read the device ID (
getDeviceIdordeviceId). - Any other protection headers besides
x-device-idthat Coinflow asked you to send.
If your app still sends the other protection headers alongside the new x-device-id, the values in x-device-id take priority, so leftover headers won’t break checkout. Removing them keeps your integration simple.
Test your migration
- Initialize the SDK with
env: sandboxand point your app athttps://api-sandbox.coinflow.cash. - Run a sandbox checkout and confirm the request to Coinflow includes a non-empty
x-device-idheader. - Confirm the checkout response matches what you saw before migrating.
- Before releasing, switch to
env: prodtogether with your production API base URL.
Troubleshooting
The SDK returns no headers
The SDK fails open: if no signal is available it returns an empty set of headers instead of throwing, so checkout is never blocked. The request still goes through, but without protection signals, which can lower approval rates. Check that:
initialize(orCoinflowProtectionProvider) runs before checkout.- The
merchantIdis correct. - The app is a development or release build, not Expo Go.
- On iOS, the
CoinflowFraudpod is in yourPodfile(the Expo config plugin adds it for you) and you ranpod installor rebuilt. - On Android,
initializereceived an Activity, and, if your app needs it, thecash.coinflow.fraud.repositoriesplugin is applied.
Approval rates dropped after migrating
Coinflow doesn’t reject a checkout because of the x-device-id header. If the value can’t be read, the checkout goes through without its protection signals, which shows up as weaker scoring and more declines rather than an error. Check that:
- The SDK environment matches the API you call:
sandboxwithapi-sandbox.coinflow.cash,prodwith production. - Your backend forwards
x-device-idexactly as the app sent it, along with the customer’s IP inx-coinflow-client-ip.
Do I still need to send chargebackProtectionData?
Yes. The Coinflow Fraud SDK replaces how device and session signals are collected, not what you send about the purchase. Keep passing chargebackProtectionData as described in Implement Chargeback Protection.
Customers on older app versions
No action is needed. Requests from older app versions that still send the previous headers keep being accepted and scored.

