Quick Start Integration Guide
N.B: The documentation is still undergoing standardization, please report any issues you had while following the guide.
SolydFlow is the revenue infrastructure for African mobile/web apps.
It unifies app stores (Apple App Store and Google Play), local African payment gateways (Paystack and Flutterwave), and Stripe for global coverage and portability into a single API.
Beyond payment aggregation, SolydFlow includes Smart Payment Routing, allowing transactions to be automatically routed to the payment rail most likely to succeed based on the customer's region, currency, and available payment methods.
Built for the realities of emerging markets, SolydFlow provides:
- Offline entitlement access, so users can continue accessing paid features even when connectivity is unstable.
- Transaction recovery, ensuring successful payments are restored even if the app closes before completion.
- Churn protection tools that help recover subscribers before they cancel or expire.
- A single dashboard for managing products, pricing, entitlements, and payment providers.
This guide walks you through setting up your project, connecting payment providers, configuring products, and integrating the SolydFlow SDK into your Flutter application.
How SolydFlow Works
At a high level, SolydFlow sits between your application and your payment providers.
Customer
↓
Your App
↓
SolydFlow SDK
↓
SolydFlow Platform
↓
Paystack / Flutterwave / Stripe
↓
Payment Verified
↓
Entitlement Activated
↓
Premium Features Unlocked
What Happens During a Purchase?
- A customer selects a product in your application.
- SolydFlow initiates the payment with the configured payment provider.
- The payment provider confirms the transaction.
- SolydFlow verifies the payment and activates the associated entitlement.
- The SDK updates the customer's access locally and remotely.
- Premium content or features become immediately available.
Why Entitlements Matter
An entitlement represents access, not a product.
For example:
| Package | Entitlement |
|---|---|
| gold_monthly | gold_access |
| gold_yearly | gold_access |
Although the customer purchased different packages, both unlock the same entitlement (gold_access).
This allows you to manage access consistently regardless of billing period, currency, or payment provider.
Smart Payment Routing
SolydFlow can automatically route payments to the most appropriate payment provider based on currency, geography, and configured routing rules.
This helps improve conversion rates by reducing failed card transactions and directing users to payment methods that are commonly used in their region.
Example Routing Flow
Customer (NGN)
↓
SolydFlow Smart Router
↓
Monnify Virtual Account
Customer (KES)
↓
SolydFlow Smart Router
↓
M-Pesa STK Push
Customer (USD)
↓
SolydFlow Smart Router
↓
Stripe
Supported Payment Rails
| Payment Rail | Best For |
|---|---|
| Paystack | General African card payments |
| Flutterwave | General African card payments |
| Monnify | Nigerian virtual accounts |
| M-Pesa / Daraja | Kenyan mobile money payments |
| Stripe | Global card payments |
Routing rules are configured from the SolydFlow Console and require no application code changes.
Prerequisites
- A SolydFlow Account
- A Flutter/Web App
- A Payment Gateway Account (Live or Test)
Step 1: Configure Your Project in the SolydFlow Console
Before writing code, you need to configure your project in the SolydFlow Console.
1. Create a Project
Log in to the SolydFlow Console and click New Project.
Enter your application's name and create the project.
After creation, you'll receive:
- Public Key (
sf_pk_...): Used by your mobile application. - Secret Key (
sf_sk_...): Used only by your backend services.
Keep your Secret Key private and never expose it inside your mobile application.
2. Connect Your Payment Providers
SolydFlow follows a secure Bring Your Own Keys (BYOK) model. This ensures you maintain direct ownership of your merchant accounts, payouts, and compliance, while SolydFlow orchestrates the intelligence and routing.
Navigate to SolydFlow Console → Projects → Configuration (Settings Icon) to access your API Credentials Vault and connect the payment providers you want to use.
Depending on your target markets, configure the following providers:
- Connecting Paystack (Pan-African Cards)
- Connecting Flutterwave (Pan-African Cards)
- Connecting Stripe (Global Cards)
- Connecting Monnify (Nigerian Virtual Accounts) - coming soon
- Connecting M-Pesa / Daraja (Kenyan Mobile Money)
(Click any provider above to view their specific key and webhook setup guide).
Production-ready providers
- Paystack
- Flutterwave
- Stripe
Currently in testing
- Apple In-App Purchases
- Google Play Billing
Overview for each provider:
- Paste your provider's Secret Key.
- Save the configuration.
- Copy the SolydFlow Webhook URL displayed in the dashboard.
- Add the webhook URL to your payment provider's dashboard.
Webhook integration enables:
- Automatic payment verification
- Transaction recovery
- Background subscription synchronization
- Restoration of interrupted purchases
Connecting Paystack to SolydFlow
Connect your Paystack account to enable payment monitoring, transaction recovery, and financial consensus across your revenue infrastructure.
By integrating Paystack, SolydFlow's Consensus Engine, Sweeper, and Immutable Ledger continuously monitor transaction states and eliminate revenue uncertainty.
Prerequisites
- An active Paystack account (Live or Test mode).
- A SolydFlow project.
Step 1: Add Your Paystack Secret Keys to SolydFlow
SolydFlow requires your Paystack Secret Keys to initialize payments and independently verify transaction states directly from Paystack's API.
- Log in to your Paystack Dashboard.
- Navigate to Settings → API Keys & Webhooks.
- Copy your Secret Key (
sk_live_...andsk_test_...). - Log in to the SolydFlow Console.
- Open your Project settings.
- Navigate to API Credentials Vault.
- Paste your Paystack Secret Keys into the Paystack section.
- Click Save Configuration.
Security Note: All gateway credentials are encrypted using AES-256-GCM and are never exposed to client applications.
Step 2: Configure the Inbound Webhook
Paystack must notify SolydFlow when payment activity occurs.
- In the SolydFlow Console, open Inbound Gateway Webhook Configurations.
- Copy your Paystack Webhook URL:
https://api.solydflow.com/api/v1/webhook/paystack/{your_solydflow_api_key}
- Log in to Paystack.
- Navigate to Settings → API Keys & Webhooks.
- Paste the SolydFlow URL into the Webhook URL field.
- Save your configuration.
How SolydFlow Secures Paystack Events
SolydFlow never grants access based solely on a webhook payload.
When Paystack sends an event:
- SolydFlow intercepts the webhook.
- The Consensus Engine pauses entitlement activation.
- SolydFlow securely queries Paystack's Verify Transaction API using your encrypted Secret Key.
- The returned transaction state is compared against the webhook payload.
- If both states agree, SolydFlow records a
SETTLED_CONSENSUSevent in the Immutable Ledger. - Access is granted.
This prevents:
- Webhook spoofing
- Replay attacks
- State manipulation
- False payment confirmations
What SolydFlow Monitors
Once connected, SolydFlow continuously tracks:
- Successful transactions
- Delayed callbacks
- Missing webhooks
- Abandoned checkouts
- Zombie transactions
- State mismatches
These signals power Recover, Truth, and Enforce across your payment infrastructure.
Connecting Flutterwave to SolydFlow
Connect your Flutterwave account to enable transaction recovery, payment verification, and financial consensus across your revenue stack.
By integrating Flutterwave, SolydFlow's Consensus Engine continuously verifies transaction states before access is granted to customers.
Prerequisites
- An active Flutterwave account (Live or Test mode).
- A SolydFlow project.
Step 1: Add Your Flutterwave Secret Keys to SolydFlow
SolydFlow requires your Flutterwave Secret Keys to independently verify transactions and eliminate trust in client-side responses.
- Log in to your Flutterwave Dashboard.
- Navigate to Settings → API Keys.
- Copy your Secret Key (
FLWSECK_TEST...andFLWSECK_LIVE...). - Log in to the SolydFlow Console.
- Open your Project settings.
- Navigate to API Credentials Vault.
- Paste your Flutterwave Secret Keys into the Flutterwave section.
- Click Save Configuration.
Security Note: SolydFlow encrypts all gateway credentials using AES-256-GCM before storage.
Step 2: Configure the Inbound Webhook
Flutterwave must notify SolydFlow whenever transaction activity occurs.
- In the SolydFlow Console, open Inbound Gateway Webhook Configurations.
- Copy your Flutterwave Webhook URL:
https://api.solydflow.com/api/v1/webhook/flutterwave/{your_solydflow_api_key}
- Log in to Flutterwave.
- Navigate to Settings → Webhooks.
- Paste the SolydFlow URL.
- Save your webhook configuration.
How SolydFlow Secures Flutterwave Events
Unlike traditional integrations, SolydFlow does not blindly trust incoming webhooks.
When Flutterwave sends a payment event:
- SolydFlow receives the webhook.
- The Consensus Engine pauses entitlement activation.
- SolydFlow queries Flutterwave's transaction verification API using your encrypted Secret Key.
- The API response is compared against the webhook payload.
- If consensus is reached, a
SETTLED_CONSENSUSrecord is written to the Immutable Ledger. - User access is activated.
This guarantees financial truth even when:
- Webhooks arrive late
- Duplicate events are received
- Client responses are manipulated
- Network interruptions occur
What SolydFlow Monitors
After connection, SolydFlow actively monitors:
- Successful payments
- Pending transactions
- Failed callbacks
- Missing webhooks
- Delayed settlements
- Zombie transactions
- Ledger conflicts
These signals feed SolydFlow Recover, Truth, and Enforce to ensure every payment reaches a final and correct state.
Connecting Stripe to SolydFlow
Connect your Stripe account to enable global card processing. By integrating Stripe, SolydFlow's Consensus Engine and Sweeper can actively monitor your international transactions, resolve state mismatches, and automate recovery workflows.
Prerequisites
- An active Stripe account (Live or Test mode).
- A SolydFlow project.
Step 1: Add Your Stripe Keys to SolydFlow
SolydFlow requires your Stripe Secret Keys to securely initialize payments and verify transaction status directly with the Stripe API (bypassing client-side spoofing).
- Log in to your Stripe Dashboard.
- Navigate to Developers → API Keys.
- Copy your Secret Key (
sk_live_...andsk_test_...). - Log in to the SolydFlow Console.
- Go to your Project settings and open the API Credentials Vault.
- Paste your Stripe Secret Keys into the Stripe section and click Save Configuration.
Security Note: SolydFlow uses military-grade AES-256-GCM encryption to store your Secret Keys at rest.
Step 2: Configure the Inbound Webhook
Stripe must notify SolydFlow whenever a payment completes. SolydFlow uses a cryptographically secure webhook endpoint unique to your project.
- In the SolydFlow Console, scroll down to Inbound Gateway Webhook Configurations.
- Copy your unique Stripe Webhook URL:
https://api.solydflow.com/api/v1/webhook/stripe/{your_solydflow_api_key} - In your Stripe Dashboard, navigate to Developers → Webhooks → Add Endpoint.
- Paste the SolydFlow URL.
- Under Select Events, add
payment_intent.succeeded. (SolydFlow's Consensus Engine will automatically query the API for the rest of the required data). - Click Add Endpoint.
How SolydFlow Secures Stripe Events
Unlike standard integrations, SolydFlow does not blindly trust incoming webhooks.
When Stripe fires a webhook to SolydFlow, our Layer 2 Consensus Engine activates:
- We intercept the webhook.
- We pause the entitlement grant.
- We securely query the Stripe REST API using your encrypted
sk_live_...key. - If the live API confirms the webhook payload, we log a
SETTLED_CONSENSUSevent to your Immutable Ledger and grant the user access.
This completely eliminates Webhook Replay attacks and guarantees Absolute Financial Truth.
3. Create Entitlements
Entitlements represent the access level a customer receives after a successful purchase.
Examples:
pro_accessgold_accessenterprise_access
Think of an entitlement as the permission that unlocks premium features inside your application.
4. Create Packages
Packages are the products customers actually purchase.
Examples:
gold_monthlygold_yearlypro_monthlypro_annual
Each package should be mapped to an entitlement.
Example:
| Package | Entitlement |
|---|---|
| gold_monthly | gold_access |
| gold_yearly | gold_access |
Both subscriptions unlock the same access level even though they have different billing periods.
5. Configure Regional Pricing
When creating packages, SolydFlow can automatically suggest localized pricing across supported regions using Smart Suggestions.
This helps maintain purchasing-power parity across currencies such as:
- NGN
- KES
- GHS
- ZAR
- USD
- EUR
You can accept the suggested pricing or customize prices manually for each market.
6. Configure Payment Routing Rules
SolydFlow allows you to define routing rules that determine which payment provider should be used for specific currencies or markets.
Navigate to:
Settings → Payment Routing Rules
Configure:
- A default payment provider.
- Currency-specific routing overrides.
- Local payment rail preferences.
Example:
| Currency | Route To |
|---|---|
| NGN | Monnify |
| KES | M-Pesa |
| USD | Stripe |
| Other | Paystack |
These rules can be updated without releasing a new version of your application.
Step 2: Install the SDK
Add SolydFlow to your Flutter project's pubspec.yaml.
dependencies:
flutter:
sdk: flutter
solydflow_flutter:
git:
url: https://github.com/solydflow/solydflow_flutter.git
path: sdk_flutter
ref: v0.8.0
After updating your dependencies, run:
flutter pub get
Platform Requirements
Android
SolydFlow requires Android API Level 21 (Android 5.0) or higher.
Open:
android/app/build.gradle
or
android/app/build.gradle.kts
and ensure:
defaultConfig {
minSdkVersion = 21
}
iOS
If you are participating in Apple In-App Purchase testing, enable the In-App Purchase capability in Xcode.
- Open:
ios/Runner.xcworkspace
- Navigate to:
Signing & Capabilities
- Click:
+ Capability
- Add:
In-App Purchase
Apple In-App Purchase support is currently in testing. Most Paystack and Flutterwave integrations do not require this step.
Step 3: Initialize SolydFlow
Initialize SolydFlow as early as possible in your application's lifecycle, ideally before rendering your first screen.
import 'package:flutter/material.dart';
import 'package:solydflow_flutter/solydflow_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SolydFlow.configure(
apiKey: "sf_pk_your_public_key",
userID: "unique_user_id",
userPhone: "2348012345678",
userEmamil: "user@mail.com"
);
runApp(const MyApp());
}
Configuration Parameters
apiKey
Your project's public API key.
You can find this in your SolydFlow project dashboard.
Example:
sf_pk_xxxxxxxxxxxxxxxxx
userID
A unique identifier for the currently authenticated user in your application.
Examples:
- Firebase UID
- Supabase User ID
- Internal database user ID
This value is used to:
- Track purchases
- Restore access across devices
- Sync entitlements
- Recover interrupted transactions
Example:
user_12345
userPhone (Recommended)
The user's phone number in international format.
Example:
2348012345678
Providing a phone number enables SolydFlow features such as:
- Subscription recovery campaigns
- Churn prevention messaging
- Customer re-engagement workflows
- and local payment rails such as M-Pesa.
If a phone number is not available, M-Pesa can not be used, you can then pass empty string for the phone number field and SolydFlow will continue to function normally.
When Should Initialization Happen?
Initialize SolydFlow:
- After the user has authenticated.
- Before checking entitlements.
- Before displaying a paywall.
- Before making purchases.
If your application supports guest users, initialize SolydFlow with a temporary identifier and reconfigure it once the user signs in.
Step 4: Choose Your Integration Strategy
SolydFlow supports two different integration approaches.
Choose the one that best matches your team's workflow and product requirements.
| Option | Best For |
|---|---|
| Custom UI | Teams that want complete control over the paywall experience and design. |
| No-Code Paywall | Teams that want to design, update, and publish paywalls directly from the SolydFlow Console without releasing a new app version. |
Option A: Custom UI
With the Custom UI approach, your application fetches products from SolydFlow and renders them using your own Flutter widgets and layouts.
This gives you complete control over:
- Design
- User experience
- Layout
- Product presentation
Fetch your available packages:
Future<void> loadProducts() async {
List<SolydPackage> offerings = await SolydFlow.getOfferings();
for (var pkg in offerings) {
if (pkg.isUpgrade) {
print(
"Upgrade Price: ${pkg.currency} ${pkg.calculatedAmountKobo / 100}"
);
} else {
print(
"Base Price: ${pkg.currency} ${pkg.amountKobo / 100}"
);
}
}
}
The returned packages can be displayed in any UI design you choose.
Purchase a Package
When a user selects a package, initiate the purchase flow:
Future<void> buyPlan(
BuildContext context,
String packageID,
) async {
try {
final CustomerInfo? info =
await SolydFlow.purchasePackage(
context,
packageID,
);
if (info == null) {
return;
}
if (info.activeEntitlements["gold_access"] == true) {
Navigator.pop(context);
print("Purchase successful!");
}
} catch (e) {
print("Purchase failed: $e");
}
}
The SDK automatically handles:
- Payment processing
- Verification
- Entitlement updates
- Transaction recovery
- Customer synchronization
Option B: No-Code Paywall
With the No-Code Paywall, you design and manage your paywall directly from the SolydFlow Console.
Changes can be published without requiring users to update your application.
Display the paywall with:
void showPaywall(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (ctx) => SolydPaywall(
onPurchaseSuccess: (CustomerInfo info) {
Navigator.pop(ctx);
ScaffoldMessenger.of(ctx).showSnackBar(
const SnackBar(
content: Text(
"Subscription Unlocked! 🚀",
),
),
);
},
onClose: () => Navigator.pop(ctx),
),
);
}
The paywall automatically:
- Displays products configured in your dashboard
- Uses your published paywall design
- Handles purchases
- Tracks conversion events
- Updates customer entitlements after successful payment
Which Option Should You Choose?
Choose Custom UI if:
- You need full control over the user experience.
- Your design system is highly customized.
- You want to build your own paywall components.
Choose No-Code Paywall if:
- You want faster implementation.
- Product teams need to update paywalls without app releases.
- You want dashboard-managed paywall experiences.
Step 5: Checking Entitlements and Customer State
SolydFlow provides two ways to check a user's access level depending on your needs.
Option A: Simple Access Check (Recommended for UI)
Use this when you only need to quickly determine whether a user has access to a feature.
Future<void> checkAccess() async {
bool isPro = await SolydFlow.hasEntitlement("pro_tier");
if (isPro) {
// Unlock premium features
print("User has access");
} else {
// Show paywall or restrict access
print("User does not have access");
}
}
Why use this method?
- Fast ( < 5ms )
- Works offline using encrypted local cache
- Ideal for UI gating and navigation decisions
Option B: Full Customer State (Advanced)
Use this when you need complete information about a user's subscriptions, expiry dates, or entitlement history.
Future<void> getCustomerState() async {
CustomerInfo info = await SolydFlow.getCustomerInfo();
// Check active entitlement
if (info.activeEntitlements["pro_tier"] == true) {
print("User is Pro");
}
// Get entitlement expiry
DateTime? expiry = info.allEntitlements["pro_tier"];
if (expiry != null) {
print("Expires on: $expiry");
}
}
What CustomerInfo Contains
The CustomerInfo object includes:
-
activeEntitlements→ A map of currently active access levels -
allEntitlements→ All entitlements with their expiration dates -
Cached local state (instant access even offline)
-
Synchronized server state (updated in background when connection is restored)
Offline-First Behavior
SolydFlow is designed to work in unstable network conditions.
When calling getCustomerInfo():
- The SDK first checks encrypted local storage (instant response).
- If available, it returns immediately.
- It then syncs with the server in the background.
- Any updates are automatically merged.
This ensures:
- No blocked UI
- No dependency on constant internet connectivity
- Reliable entitlement restoration after interruptions
When to Use Which
| Scenario | Recommended Method |
|---|---|
| Show/hide premium UI | hasEntitlement() |
| Route navigation decisions | hasEntitlement() |
| Show subscription details | getCustomerInfo() |
| Analytics / billing insights | getCustomerInfo() |
| Debugging user access issues | getCustomerInfo() |
Step 6: Display Products and Process Purchases
Before a customer can make a purchase, your application needs to retrieve the products configured in your SolydFlow dashboard.
Fetch Available Packages
Use getOfferings() to retrieve the packages associated with your project.
Future<void> loadProducts() async {
List<SolydPackage> offerings =
await SolydFlow.getOfferings();
for (var pkg in offerings) {
print(
"${pkg.name} - ${pkg.currency} ${pkg.amountKobo / 100}"
);
}
}
Example output:
Gold Monthly - NGN 1000
Gold Yearly - NGN 10000
The returned packages can be displayed using your own UI or through the SolydFlow No-Code Paywall.
Upgrade Pricing and Smart Credits
When a customer is upgrading from one plan to another, SolydFlow can return adjusted pricing information.
for (var pkg in offerings) {
if (pkg.isUpgrade) {
print(
"Upgrade Price: ${pkg.currency} ${pkg.calculatedAmountKobo / 100}"
);
}
}
When isUpgrade is true, the package contains upgrade-adjusted pricing that can be displayed to the customer.
Initiate a Purchase
When a customer selects a package, call purchasePackage().
Future<void> buyPlan(
BuildContext context,
String packageID,
) async {
try {
final CustomerInfo? info =
await SolydFlow.purchasePackage(
context,
packageID,
);
if (info == null) {
// User cancelled purchase
return;
}
if (info.activeEntitlements["gold_access"] == true) {
print("Purchase successful!");
}
} catch (e) {
print("Purchase failed: $e");
}
}
What Happens During a Purchase?
The SDK automatically handles:
- Payment initialization
- Payment provider communication
- Transaction verification
- Entitlement activation
- Customer synchronization
- Transaction recovery
After a successful purchase, the updated CustomerInfo object is returned immediately.
This allows your application to unlock features without requiring another API call.
Handling Purchase Results
Successful Purchase
if (info.activeEntitlements["gold_access"] == true) {
// Unlock premium features
}
User Cancelled
if (info == null) {
return;
}
Failed Purchase
catch (e) {
print("Purchase failed: $e");
}
Always handle all three scenarios to provide a smooth user experience.
Recommended Flow
- Fetch offerings using
getOfferings(). - Display products to the user.
- User selects a package.
- Call
purchasePackage(). - Verify access using the returned
CustomerInfo. - Unlock premium functionality immediately.
Checkout Experience
Depending on the configured routing rules, the customer may experience different payment flows.
Examples include:
- Hosted checkout pages (Paystack, Flutterwave, Stripe)
- Virtual account payments (Monnify)
- Native mobile money prompts (M-Pesa)
The SDK automatically selects and manages the appropriate flow.
No additional application logic is required.
Step 7: Test Transaction Recovery
One of SolydFlow's core capabilities is transaction recovery.
In regions with unstable networks, users may successfully complete a payment but lose connectivity before the application receives confirmation. This can result in paid customers temporarily losing access.
SolydFlow automatically reconciles these transactions using webhook events, entitlement synchronization, and secure local caching.
The "Zombie Transaction" Test
Use this test to verify that transaction recovery is working correctly.
Test Steps
- Start a purchase on a physical device.
- Complete the payment process.
- Before the payment flow returns to your application, immediately force-close the app.
- Wait approximately 15 to 30 seconds.
- Re-open the application.
- Check the user's entitlement status.
Expected Result
The user should automatically regain access to the purchased entitlement even though the application was closed before the purchase flow completed.
For example:
bool hasAccess =
await SolydFlow.hasEntitlement(
"gold_access",
);
The result should return:
true
What This Test Validates
A successful recovery test confirms:
- Webhooks are configured correctly.
- Payment verification is working.
- Entitlement synchronization is active.
- Customer state recovery is functioning properly.
- Interrupted purchases can be restored automatically.
Common Issues
Purchase Not Restored
Verify:
- Gateway credentials are correct.
- Webhook URLs are configured.
- The webhook endpoint is reachable.
- The payment was successfully completed on the provider side.
Entitlement Not Activated
Verify:
- The package is mapped to the correct entitlement.
- The entitlement exists in the SolydFlow Console.
- The application is checking the correct entitlement identifier.
Example:
await SolydFlow.hasEntitlement(
"gold_access",
);
Recovery Takes Longer Than Expected
Recovery timing depends on:
- Payment provider webhook delivery
- Network conditions
- Application reconnect timing
In most cases, recovery should occur automatically within a short period after the payment provider confirms the transaction.
Web Integration (JavaScript & TypeScript)
SolydFlow provides a lightweight, framework-agnostic JavaScript SDK for web applications (React, Vue, Next.js, or Vanilla JS).
The JavaScript SDK provides the same core capabilities available on mobile, including:
- Dynamic pricing
- Purchasing Power Parity (PPP)
- Smart Upgrade Credits
- Entitlement management
- Subscription lifecycle tracking
It allows you to use the same pricing logic, entitlement system, and upgrade rules as your mobile applications while maintaining a separate web checkout flow. This allows customers to purchase and manage subscriptions from your website while maintaining a single source of truth across platforms.
Mobile vs Web Purchase Flow
The purchase experience differs slightly between mobile and web platforms.
Mobile SDK
User
↓
In-App Purchase Flow
↓
Payment Completed
↓
CustomerInfo Returned
↓
Entitlement Activated
The SDK waits for the purchase flow to complete and returns an updated CustomerInfo object immediately.
Web SDK
User
↓
Hosted Checkout Page
↓
Payment Completed
↓
Webhook Sent
↓
Backend Updated
↓
Entitlement Activated
Because the browser is redirected to a hosted checkout page, the web application cannot wait for payment completion.
Instead, SolydFlow notifies your backend using webhooks after the transaction has been verified.
1. Installation
Install directly from GitHub:
npm install solydflow-js
or:
yarn add solydflow-js
or
pnpm add solydflow-js
2. Initialization
Initialize the SDK as early as possible in your web application.
import { SolydFlow } from "solydflow-js";
await SolydFlow.configure(
"sf_pk_live_YOUR_PUBLIC_KEY",
"user_12345",
"user@mail.com"
);
3. Choose Your Integration Strategy
The SolydFlow JavaScript SDK supports two integration approaches.
| Option | Best For |
|---|---|
| Drop-In Paywall | Teams that want the fastest integration and dashboard-managed pricing experiences. |
| Custom UI | Teams that want complete control over their website's pricing and checkout experience. |
Option A: Drop-In Paywall
Instead of spending days building your own pricing page, SolydFlow provides a fully responsive, high-converting Drop-In Paywall that automatically stays synchronized with the design, colors, copy, products, and pricing configured in your SolydFlow Console.
The paywall automatically handles:
- Purchasing Power Parity (Geo-IP pricing)
- Smart Upgrade Credits
- Payment routing rules
- Checkout initiation
- Product rendering
Step 1: Create a Container
Add a container element to your page:
<div id="solydflow-paywall-container"></div>
Step 2: Render the Paywall
import { SolydFlow } from "solydflow-js";
async function showPricing() {
await SolydFlow.configure(
"sf_pk_live_YOUR_PUBLIC_KEY",
"user_12345",
"user@mail.com"
);
await SolydFlow.renderPaywall(
"solydflow-paywall-container"
);
}
That's all that's required.
The SDK automatically loads and renders the paywall you designed in the SolydFlow Console.
When Should You Use This?
Choose the Drop-In Paywall if:
- You want the fastest implementation.
- Product teams manage pricing and promotions.
- You want paywall updates without deploying new website code.
- You want built-in optimization and localization.
Option B: Custom UI (Advanced)
If you prefer to build your own pricing experience, you can fetch package information directly and render your own components.
SolydFlow will still calculate:
- Purchasing Power Parity pricing
- Smart Upgrade Credits
- Regional pricing adjustments
async function fetchRawPackages() {
const offerings = await SolydFlow.getOfferings();
offerings.forEach(pkg => {
if (pkg.is_upgrade) {
console.log(
`Upgrade for ${pkg.currency} ${pkg.calculated_amount_kobo / 100}`
);
} else {
console.log(
`Standard Price: ${pkg.currency} ${pkg.amount_kobo / 100}`
);
}
});
}
You are responsible for rendering the UI, while SolydFlow remains responsible for pricing logic, checkout routing, and entitlement management.
4. Checking Access
Check whether the current user has an active entitlement.
async function checkAccess() {
const isGold = await SolydFlow.hasEntitlement("gold_access");
if (isGold) {
console.log("Welcome to the premium dashboard!");
} else {
// Redirect to pricing page
}
}
5. Making a Purchase (Web Redirect Flow)
When a user initiates a purchase, they are redirected to a secure hosted checkout page.
⚠️ Web Flow Difference: Unlike the mobile SDK (which returns
CustomerInfodirectly), the web SDK redirects the user to a hosted payment page. Your application does not wait for completion.
async function handleCheckout(packageId) {
try {
await SolydFlow.purchasePackage(
packageId,
"2348012345678"
);
// Redirect occurs automatically.
// Code below will not execute immediately.
} catch (error) {
console.error("Checkout failed:", error.message);
}
}
6. Fulfilling the Purchase (Webhooks)
Unlike the mobile SDK, web applications cannot wait for a payment to complete because the customer is redirected to a hosted checkout experience.
To unlock subscriptions, grant entitlements, and synchronize customer access, you must configure a backend webhook endpoint.
Configure Your Webhook Endpoint
- Log in to the SolydFlow Console.
- Navigate to Projects.
- Click Manage Connection.
- Under Your Backend Webhook.
- Enter your backend endpoint URL (for example, a Node.js API, Laravel endpoint, Django view, or Supabase Edge Function).
- Save the configuration.
When subscription activity occurs, SolydFlow securely delivers signed webhook events to your backend.
The 4 Webhook Events
To keep your integration incredibly simple while still supporting powerful marketing analytics, SolydFlow consolidates all billing complexity into just four specific events.
1. subscription_started
When it fires: A user successfully pays for an entitlement for the very first time, or they purchase it again after their previous subscription completely expired.
What to do: Grant the user access to the entitlement until the expires_at date. Tip: This is the perfect event to trigger a "Welcome to Premium" onboarding email!
{
"event": "subscription_started",
"event_id": "evt_110e8400-e29b-41d4-a716-446655440001",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"provider": "paystack",
"expires_at": "2026-07-27T18:33:00Z"
}
2. subscription_renewed
When it fires: A user's active subscription is renewed, upgraded, or a dropped payment is rescued by the SolydFlow Sweeper. Time is added to their current access.
What to do: Silently extend the user's access in your database to the new expires_at date.
{
"event": "subscription_renewed",
"event_id": "evt_550e8400-e29b-41d4-a716-446655440000",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"provider": "paystack",
"expires_at": "2026-08-27T18:33:00Z"
}
3. subscription_revoked
When it fires: A user's access is forcefully killed before their natural expiration date (e.g., a card chargeback, an Apple refund, or a manual Admin rejection in the dashboard).
What to do: Immediately revoke the user's access to the entitlement and pause their services.
{
"event": "subscription_revoked",
"event_id": "evt_991f8400-e29b-41d4-a716-446655440001",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"reason": "chargeback",
"revoked_at": "2026-06-27T18:33:00Z"
}
4. test_event
When it fires: You click "Send Test Webhook" in the SolydFlow Console API Vault. What to do: Use this to verify your HMAC SHA-256 cryptographic signature logic is working correctly before going live.
{
"event": "test_event",
"user_id": "sf_test_user_999",
"package_id": "test_monthly_gold",
"entitlement": "gold_access",
"provider": "solydflow_test",
"expires_at": "2026-07-27T18:33:00Z"
}
Your backend should use these events to update customer records, synchronize subscriptions, and unlock application features.
Securing Your Webhooks
Because webhook endpoints are publicly accessible, every incoming request must be verified before processing.
SolydFlow protects webhook deliveries using:
- Cryptographic request signatures
- Timestamp validation
- Replay attack protection
The Signature Header
Every webhook request includes the following header:
X-SolydFlow-Signature: t=1687263530,v1=9b1d2e3f4a5b6c7d8e9f...
The header contains two values:
| Field | Description |
|---|---|
t | UNIX timestamp of when the webhook was generated |
v1 | HMAC SHA-256 cryptographic signature |
Verification Process
Your backend should perform three verification steps before processing any webhook.
Step 1: Extract the Timestamp and Signature
Parse the X-SolydFlow-Signature header and extract:
- Timestamp (
t) - Signature (
v1)
Step 2: Prevent Replay Attacks
Compare the supplied timestamp against your server's current UNIX timestamp.
Reject requests older than 300 seconds (5 minutes).
This prevents attackers from intercepting a valid webhook and replaying it later.
Step 3: Verify the Signature
Construct the payload using:
timestamp.raw_body
Example:
1687263530.{"event":"subscription_renewed"}
Generate an HMAC SHA-256 hash using your SolydFlow Webhook Secret and compare it against the supplied v1 signature.
Only process the webhook if both signatures match.
Node.js / Express Verification Example
The example below demonstrates a complete webhook verification implementation.
const express = require('express');
const crypto = require('crypto');
const app = express();
// Preserve the raw request body for signature verification
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString();
}
}));
const SOLYDFLOW_WEBHOOK_SECRET =
process.env.SOLYDFLOW_WEBHOOK_SECRET;
app.post('/webhook/solydflow', (req, res) => {
const signatureHeader =
req.headers['x-solydflow-signature'];
if (!signatureHeader) {
return res
.status(401)
.send('Missing SolydFlow signature');
}
// Extract timestamp and signature
const parsedHeader = signatureHeader
.split(',')
.reduce((acc, pair) => {
const [key, value] = pair.split('=');
acc[key] = value;
return acc;
}, {});
const timestamp = parsedHeader['t'];
const providedSignature = parsedHeader['v1'];
if (!timestamp || !providedSignature) {
return res
.status(401)
.send('Invalid signature format');
}
// Replay attack protection
const currentTimestamp =
Math.floor(Date.now() / 1000);
const webhookAge =
currentTimestamp - parseInt(timestamp, 10);
if (webhookAge > 300) {
return res
.status(401)
.send(
'Webhook timestamp is too old'
);
}
// Compute expected signature
const payloadToSign =
`${timestamp}.${req.rawBody}`;
const expectedSignature = crypto
.createHmac(
'sha256',
SOLYDFLOW_WEBHOOK_SECRET
)
.update(payloadToSign)
.digest('hex');
const isValid =
crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(providedSignature)
);
if (!isValid) {
return res
.status(401)
.send(
'Cryptographic signature mismatch'
);
}
// Webhook verified
const payload = req.body;
console.log(
'Verified SolydFlow Event:',
payload.event
);
switch (payload.event) {
case 'subscription_started':
// Create subscription
break;
case 'subscription_renewed':
// Extend subscription
break;
case 'subscription_revoked':
// Revoke access
break;
default:
console.log(
'Unhandled event:',
payload.event
);
}
// Acknowledge receipt
return res.status(200).json({
received: true
});
});
app.listen(3000, () => {
console.log(
'Server listening on port 3000'
);
});
Production Best Practices
Before updating customer records, your backend should:
- Verify the webhook signature.
- Verify the timestamp.
- Reject duplicate events (idempotency).
- Update customer subscription records.
- Synchronize entitlement access.
- Return a successful response immediately.
A successful webhook response should return:
res.status(200).json({
received: true
});
This confirms to SolydFlow that the event was successfully delivered and processed.
Need Help?
Documentation
Visit the SolydFlow Console documentation for detailed guides, SDK references, and platform-specific integration examples.
Support
For technical assistance, contact:
When contacting support, include:
- Project name
- SDK version
- Platform (Android or iOS)
- Relevant error messages
- Steps to reproduce the issue
This helps the team resolve issues more quickly.