Adapty
Adapty Integration Guide
Integrate Botsi AI Pricing with Adapty to show each user the optimal paywall based on Botsi's machine learning predictions. Adapty handles paywall display and audience targeting, while Botsi determines which paywall each user should see.
Integration Flow Summary
- Create Botsi Profile → Get
profileId - Call Botsi Get Paywall API → Get predicted paywall
externalID - Set Adapty Custom Attribute → Store Botsi's
externalID - Fetch Adapty Paywall → Adapty returns targeted paywall based on custom attribute
- Show Paywall to User → Display Adapty's paywall UI
- Send Paywall Impression → Call Botsi Profile Events API
- Handle Purchase → Extract transaction data from Adapty
- Validate Purchase → Send transaction to Botsi Purchase Validate API
1. Normal Botsi AI API Setup
Complete the standard Botsi AI Pricing integration following the AI Pricing Integration Guide.
2. Set Up Different Paywalls in Adapty and Botsi
Decide what prices you want to show and how you want to present them on different paywalls.
In Adapty, you'll configure Paywalls with different products/price points in their dashboard — Adapty Paywalls define which products are shown to users.
For example, if you want to use multiple annual price points, you could set up:
- Paywall: "standard_paywall" — annual →
com.app.pro.annual_standard - Paywall: "discounted_paywall" — annual →
com.app.pro.annual_discounted
Then, you'll set up corresponding Paywalls in Botsi that match your Adapty Paywalls. Add the same products you have in an Adapty Paywall to the Botsi Paywall. This lets the AI model know what prices/products are available.
3. Botsi Get Paywall API
You will specify the external ID value (data.externalID) in the Botsi dashboard when setting up a paywall.
The exact value is not important as long as it's unique, but we recommend using a common naming convention so you can keep track in other tools. (e.g. onboardingPaywall_29.99Annual_v2)
When you call the Botsi Get Paywall API, it will return that "external ID" value to you. Technically, you can use data.ID or data.externalID, but ID is always a number that you cannot adjust and so is less easily understood.
You will then use this value to set a "Custom Attribute" in Adapty using their SDK. See Adapty's Custom Attributes documentation.
The naming of this custom attribute is not important as you'll parse out the value from the Botsi API and write it via the Adapty SDK. We recommend an understandable name for other internal users. (e.g. "botsi_paywall_id" or "botsi_paywall_prediction")
You will use the externalID as the value.
4. Adapty Paywall Targeting using Botsi
You will use Adapty's Audience targeting with custom attributes to show the right paywall to the right user. Follow Adapty's Audience documentation and Add audience and paywall to placement guide for setting up your audience rules based on the custom attribute you added.
Set the custom attribute in Adapty before fetching the paywall:
- Swift
- Kotlin
- Flutter
- React Native
- Unity
// Set the custom attribute with Botsi's predicted paywall ID
try await Adapty.setProfile(
customAttributes: ["botsi_paywall_id": botsiExternalPaywallId]
)
// Then fetch the paywall - Adapty will use the custom attribute for targeting
let paywall = try await Adapty.getPaywall(placementId: "your_placement_id")
// Set the custom attribute with Botsi's predicted paywall ID
Adapty.updateProfile(
params = AdaptyProfileParameters.Builder()
.withCustomAttribute("botsi_paywall_id", botsiExternalPaywallId)
.build()
) { error ->
if (error != null) {
// handle error
}
}
// Then fetch the paywall - Adapty will use the custom attribute for targeting
Adapty.getPaywall("your_placement_id") { result ->
when (result) {
is AdaptyResult.Success -> {
val paywall = result.value
// show paywall
}
is AdaptyResult.Error -> {
// handle error
}
}
}
try {
final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID");
// the requested paywall
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
See Adapty's React Native SDK documentation for more details. Install via react-native-adapty on npm.
import { adapty } from 'react-native-adapty';
// Set the custom attribute with Botsi's predicted paywall ID
await adapty.updateProfile({
customAttributes: { "botsi_paywall_id": botsiExternalPaywallId }
});
// Then fetch the paywall - Adapty will use the custom attribute for targeting
const paywall = await adapty.getPaywall("your_placement_id");
See Adapty's Unity SDK documentation for more details.
using AdaptySDK;
// Set the custom attribute with Botsi's predicted paywall ID
var builder = new Adapty.ProfileParameters.Builder()
.SetCustomAttribute("botsi_paywall_id", botsiExternalPaywallId);
Adapty.UpdateProfile(builder.Build(), (error) => {
if (error != null) {
// handle error
}
});
// Then fetch the paywall - Adapty will use the custom attribute for targeting
Adapty.GetPaywall("your_placement_id", (paywall, error) => {
if (error != null) {
// handle error
return;
}
// show paywall
});
5. Send the Paywall Impression
Continue with API call 3, Profile Events API in the documentation, to send the paywall impression.
This should reference the Get Paywall API response field "id" (not externalID).
6. Send Purchase Transaction Data to Botsi
You will need to send the iOS Transaction ID/Original Transaction ID, or Android Purchase token after a successful purchase through Adapty.
- Swift (iOS)
- Kotlin (Android)
- Flutter
- React Native
- Unity
See Adapty's iOS Purchase documentation for more details.
let result = try await Adapty.makePurchase(product: product)
// Extract transaction information
if let transaction = result?.sk2Transaction {
let appleTransactionId = transaction.id // e.g. "2000001234567890"
let originalTxId = transaction.originalID // stable across renewals
// Send to Botsi backend API (Section 4a in Botsi documentation)
// POST to /api/v1/web-api/purchases/apple-store/validate
}
let profile = result.profile
See Adapty's Android Purchase documentation for more details.
Adapty.makePurchase(activity, product) { result ->
when (result) {
is AdaptyResult.Success -> {
val purchaseResult = result
// Extract purchase token
val purchaseToken = purchaseResult?.purchaseToken
// Send to Botsi backend API (Section 4b in Botsi documentation)
// POST to /api/v1/web-api/purchases/play-store/validate
val profile = purchaseResult.profile
}
}
}
try {
final purchaseResult = await Adapty().makePurchase(product: product);
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
if (profile.accessLevels['premium']?.isActive ?? false) {
// Send to Botsi backend API (Section 4b in Botsi documentation)
// POST to /api/v1/web-api/purchases/play-store/validate
}
break;
case AdaptyPurchaseResultPending():
break;
case AdaptyPurchaseResultUserCancelled():
break;
default:
break;
}
} on AdaptyError catch (adaptyError) {
// Handle the error
} catch (e) {
// Handle the error
}
See Adapty's React Native Purchase documentation for more details.
import { adapty } from 'react-native-adapty';
const purchaseResult = await adapty.makePurchase(product);
switch (purchaseResult.type) {
case 'success':
const profile = purchaseResult.profile;
// Access vendor transaction ID from profile subscriptions
// profile.subscriptions[vendorProductId]?.vendorTransactionId
// profile.subscriptions[vendorProductId]?.vendorOriginalTransactionId
// Send to Botsi backend API
// iOS: POST to /api/v1/web-api/purchases/apple-store/validate
// Android: POST to /api/v1/web-api/purchases/play-store/validate
break;
case 'user_cancelled':
// User cancelled the purchase
break;
case 'pending':
// Purchase is pending
break;
}
See Adapty's Unity Purchase documentation for more details.
using AdaptySDK;
Adapty.MakePurchase(product, (result, error) => {
if (error != null) {
// handle error
return;
}
switch (result.Type) {
case AdaptyPurchaseResultType.Success:
var profile = result.Profile;
// Access vendor transaction ID from profile subscriptions
// Send to Botsi backend API
// iOS: POST to /api/v1/web-api/purchases/apple-store/validate
// Android: POST to /api/v1/web-api/purchases/play-store/validate
break;
case AdaptyPurchaseResultType.UserCancelled:
// User cancelled
break;
case AdaptyPurchaseResultType.Pending:
// Purchase pending
break;
}
});
Notes
- Ensure server-side notifications are configured in both Adapty and Botsi for accurate analytics
- The custom attribute set in Adapty should match the targeting rules you configure in the Adapty dashboard
- Always handle errors appropriately when calling both Botsi and Adapty APIs
- Test the integration thoroughly in sandbox/test environments before going to production