# Create a Payment
Source: https://docs.mona.ng/api-reference/checkout/create
POST /pay/create
Create a Payment is where users can generate a new checkout session to accept payments from customers via cards, bank transfers, and Mona Pay.
# Get Payment Status
Source: https://docs.mona.ng/api-reference/checkout/status
GET /checkout/status
Poll a checkout status using transaction ID.
# Create Collection
Source: https://docs.mona.ng/api-reference/collections/create
POST /collections
Create Collection is where users can set up recurring payment schedules and subscription billing for their customers with flexible frequency options.
# Checkout
Source: https://docs.mona.ng/components/checkout
1-Tap checkout solution for web and app.
Mona One Tap allows your customers to make payment within your website or app with just a single tap. We do all the heavy lifting in the background. Your customers' bank accounts and cards will show up natively within your UI and they can complete payment without any additional UI or complex redirect flows, uplifting your conversion dramatically.
Customers can pay with biometrics using their saved payment methods, while traditional payment methods like card and manual transfer are also supported. The integration is straightforward - just drop in the SDK for your corresponding web or mobile platform without complex setup requirements.
## How It Works
The checkout process follows these key steps:
1. **Create Transaction**: Use the [create checkout session](/api-reference/checkout/create) endpoint to generate a transaction ID and payment URL
2. **Initialize SDK**: Set up the Mona SDK in your app with your merchant key
3. **Launch Checkout**: Pass the transaction ID to the SDK to start the payment flow
4. **Handle Response**: Listen for transaction status updates and handle success/failure states
## Platform Integration
### Installation
```javascript Web
```
```javascript React Native
// Install via yarn or npm
yarn add pay-with-mona-react-native
// or
npm install pay-with-mona-react-native
```
```dart Flutter
// Add to pubspec.yaml
dependencies:
pay_with_mona_sdk: ^
// Run
flutter pub get
```
```kotlin Kotlin
// Coming soon - Kotlin SDK
// Add dependency to build.gradle
```
```swift Swift
// Coming soon - Swift SDK
// Add SDK via SPM or CocoaPods
```
### Usage
```javascript Web
// 1. Create transaction via API, navigate to checkout page
// Example: /checkout?transactionId={transactionId}&checkoutToken={checkoutToken}
// 2. Initialize Mona on checkout page
useEffect(() => {
const initializeMona = async () => {
try {
if (window.MonaClient && containerRef.current) {
window.MonaClient.init(
transactionId,
containerRef.current,
checkoutToken
);
}
} catch (error) {
console.error("Failed to initialize Mona:", error);
}
};
initializeMona();
window.addEventListener("monaComplete", () => {
router.push(`/success?transactionId=${transactionId}`);
});
window.addEventListener("monaFailure", () => {
router.push("/failure");
});
return () => {
window.removeEventListener("monaComplete", () => {});
window.removeEventListener("monaFailure", () => {});
};
}, []);
// 3. Container for Mona UI
// Note: Complete integration details and additional methods
// are not yet documented for Web SDK
```
```javascript React Native
// Initialize SDK (once per app session)
PayWithMonaSDK.initialize({ merchantKey: 'mona_pub_5361ecf7' });
// Usage with config object
const config = {
amountInKobo: 5000,
merchantKey: 'your-key',
transactionId: 'unique-id'
};
{
if(status == TransactionStatus.COMPLETED) {
// handles completed state accordingly
} else if(status == TransactionStatus.FAILED) {
// handles failed state accordingly
}
}}
onStatusUpdate={(status) => {}}
onError={(error) => {
// Handle error
}}
onAuthUpdate={(status) => {}}
/>
// Alternative usage format:
{}}
onTransactionUpdate={(status) => {
if(status == TransactionStatus.COMPLETED) {
// handles completed state accordingly
} else if(status == TransactionStatus.FAILED) {
// handles failed state accordingly
}
}}
onError={(error) => {
// Handle error
}}
onAuthUpdate={(status) => {}}
/>
```
```dart Flutter
// Initialize SDK in main.dart
import 'package:pay_with_mona/pay_with_mona_sdk.dart';
void main() async {
await PayWithMona.initialize(merchantKey: {PUBLIC KEY});
runApp(MyApp());
}
// Usage in widget
late PayWithMona _payWithMona;
final _sdkNotifier = MonaSDKNotifier();
@override
void initState() {
super.initState();
_payWithMona = PayWithMona.instance;
WidgetsBinding.instance.addPostFrameCallback(
(_) {
_sdkNotifier
..txnStateStream.listen(
(state) {},
onError: (err) {},
)
..sdkStateStream.listen(
(state) {},
onError: (err) {},
);
},
);
}
// Start payment
final amount = _amountController.value.text.trim();
final checkoutDetails = MonaCheckOut(
// checkout details
);
_sdkNotifier
..setCallingBuildContext(context: context)
..setMonaCheckOut(checkoutDetails: checkoutDetails);
await _sdkNotifier.initiatePayment(
tnxAmountInKobo: num.parse(amount) * 100,
onSuccess: () {
nav();
},
onError: (errorMessage) {
showSnackBarr(errorMessage);
},
);
// Payment widget
_payWithMona.payWidget(context: context)
// Note: Full parameters for MonaCheckOut and additional
// methods are detailed in the complete Flutter documentation
```
```kotlin Kotlin
// Coming soon - Kotlin SDK integration guide
// Follow the same pattern:
// 1. Initialize SDK with merchant key
// 2. Create transaction and pass to SDK
// 3. Handle callbacks for status updates
```
```swift Swift
// Coming soon - Swift SDK integration guide
// Follow the same pattern:
// 1. Initialize with merchant key
// 2. Create transaction and launch checkout
// 3. Handle delegate callbacks
```
## Transaction Status Types
Monitor your payment status with these callback types across platforms:
| Event Description | Web | React Native | Flutter |
| ---------------------- | -------------- | ------------------------------------- | ------------------------ |
| Payment successful | `monaComplete` | `TransactionStatus.COMPLETED` | - |
| Payment failed | `monaFailure` | `TransactionStatus.FAILED` | - |
| SDK processing/loading | - | `MonaSDKStatus.LOADING` | `MonaSDKState.loading` |
| SDK ready/idle | - | - | `MonaSDKState.idle` |
| Operation successful | - | `MonaSDKStatus.SUCCESS` | `MonaSDKState.success` |
| Transaction initiated | - | `MonaSDKStatus.TRANSACTION_INITIATED` | - |
| SDK error | - | `MonaSDKStatus.ERROR` | `MonaSDKState.error` |
| User authenticated | - | `AuthStatus.LOGGED_IN` | `AuthState.loggedIn` |
| User not authenticated | - | `AuthStatus.LOGGED_OUT` | `AuthState.loggedOut` |
| Not a Mona user | - | - | `AuthState.notAMonaUser` |
**Note**: Flutter transaction-specific events are handled via `txnStateStream` - specific transaction events not yet documented.
## Next Steps
1. **Get API Keys**: Contact us to get your merchant public and private keys
2. **Create Backend**: Implement the [create checkout endpoint](/api-reference/checkout/create) on your server
3. **Test Integration**: Use our sandbox environment to test the complete flow
4. **Go Live**: Switch to production keys when ready
Check out our [API Reference](/api-reference/checkout/create) for detailed information about the checkout endpoints.
# Collections
Source: https://docs.mona.ng/components/collections
Scheduled payments and subscription management
Mona Collections allows you to set up recurring payments and subscriptions with flexible scheduling options. Whether you need weekly, monthly, or custom intervals, our collections system handles the complexity of recurring billing while providing your customers with transparent control over their payment schedules.
The system supports both fixed amount and variable collections with flexible scheduling options including weekly, monthly, and quarterly frequencies. Customer consent management ensures transparent terms, while automatic and merchant-triggered debit options give you control over collection timing. Real-time status tracking and webhook notifications keep you informed throughout the collection lifecycle.
## Collection Types
### Scheduled Collections
Perfect for installment payments with predetermined amounts and dates. Customers see exactly when and how much will be debited.
### Subscription Collections
Ideal for recurring services with consistent billing cycles. Set up once and let the system handle ongoing collections.
## Debit Types
### MONA (Auto-scheduled)
Mona automatically handles the scheduling and execution of debits based on your configuration.
### MERCHANT (Manual trigger)
You have full control over when collections are triggered, perfect for event-driven billing. You still cannot debit more than the consented amount or before the intervals your customer agreed to—you simply control the exact timing of collection execution within those boundaries.
## How It Works
The collections process follows these key steps:
1. **Create Collection**: Use the [create collection](/api-reference/collections/create) endpoint to set up a recurring payment schedule
2. **Initialize SDK**: Set up the Mona Collections SDK in your app with your merchant key
3. **Request Consent**: Use the collection ID (accessRequestId) to request user consent for the collection
4. **Monitor Status**: Handle consent responses and collection lifecycle events
## Platform Integration
### Installation
```javascript Web
```
```javascript React Native
// Install via yarn or npm (same as checkout)
yarn add pay-with-mona-react-native
// or
npm install pay-with-mona-react-native
```
```dart Flutter
// Same installation as checkout
dependencies:
pay_with_mona_sdk: ^
// Run
flutter pub get
```
```kotlin Kotlin
// Coming soon - Kotlin Collections SDK
// Add dependency to build.gradle
```
```swift Swift
// Coming soon - Swift Collections SDK
// Add SDK via SPM or CocoaPods
```
### Usage
```javascript Web
// Note: Web Collections SDK integration not yet documented
// Follow similar pattern to Checkout:
// 1. Create collection via API, get collectionId/accessRequestId
// 2. Initialize collections (method not yet documented)
// Expected pattern similar to:
// window.MonaClient.initCollections(accessRequestId, container, ...)
// 3. Handle events (events not yet documented)
// Expected pattern similar to:
// window.addEventListener("monaCollectionConsented", ...)
// window.addEventListener("monaCollectionConsentFailed", ...)
// Complete Web Collections SDK documentation coming soon
```
```javascript React Native
// Wrap your app with the Collections Provider
{/* Your app */}
// Use Collections hook
const {initiate, loading, error} = useCollections({
onError: (error) => {
console.error("Collection setup failed:", error.message);
},
onSuccess: () => {
console.log("Collection setup successful!");
},
});
// To start the collection flow:
// Hook response:
// initiate(accessRequestId: string) - Call to begin collection flow
// loading - Boolean indicating if session is in progress
// error - Returns Error object if error occurs, otherwise null
```
```dart Flutter
// Initialize SDK in main.dart (same as checkout)
void main() async {
await PayWithMona.initialize(merchantKey: {PUBLIC KEY});
runApp(MyApp());
}
// Collections API
final _sdkNotifier = MonaSDKNotifier();
// Create Collection
await MonaSDKNotifier().createCollection(
onSuccess: () { /* Show consent UI */ },
onError: (msg) { /* Show error */ },
);
// Collections Consent
await MonaSDKNotifier().collectionsConsent(
bankId: bankId,
accessRequestId: accessRequestId,
onSuccess: (result) { /* Handle success */ },
onFailure: () { /* Handle failure */ },
);
// Stream listeners (same as checkout)
_sdkNotifier.authStateStream.listen((state) {
// AuthState.loggedIn, AuthState.loggedOut, AuthState.notAMonaUser
});
_sdkNotifier.sdkStateStream.listen((state) {
// MonaSDKState.idle, loading, error, success, transactionInitiated
});
// Note: Full Collections implementation details and UI handling
// are available in the complete Flutter documentation
```
```kotlin Kotlin
// Coming soon - Kotlin Collections SDK
// Follow the same pattern:
// 1. Initialize SDK with merchant key
// 2. Set up Collections provider/manager
// 3. Use collection ID to request consent
// 4. Handle consent callbacks
```
```swift Swift
// Coming soon - Swift Collections SDK
// Follow the same pattern:
// 1. Initialize SDK with merchant key
// 2. Set up Collections manager
// 3. Use collection ID to request consent
// 4. Handle delegate callbacks
```
## Collection Lifecycle
### 1. Create Collection (Backend)
First, create a collection on your backend using the API:
```json
{
"maximumAmount": "600",
"debitType": "MERCHANT",
"startDate": "2025-05-22T05:43:00",
"expiryDate": "2025-06-19T08:42:00",
"schedule": {
"type": "SCHEDULED",
"frequency": "MONTHLY",
"amount": "200"
}
}
```
### 2. Request User Consent (SDK)
Use the returned collection ID to request user consent through the SDK.
### 3. Monitor Collection Status
Track collection status through webhooks or polling:
* `NOT_STARTED` - Collection created, awaiting consent
* `ACTIVE` - Collection consented and active
* `PAUSED` - Collection temporarily paused
* `COMPLETED` - All scheduled payments completed
* `CANCELLED` - Collection cancelled
## State Management
### Collection Events
| Event Description | Web | React Native | Flutter |
| ----------------------------- | ------------------ | ------------------------------------ | ---------------------------------------- |
| Collection consent successful | Not yet documented | Success callback in `useCollections` | Success callback in `createCollection()` |
| Collection consent failed | Not yet documented | Error callback in `useCollections` | Error callback in `createCollection()` |
| Initialize consent flow | Not yet documented | `initiate(accessRequestId)` | `collectionsConsent()` |
| Operation in progress | Not yet documented | `loading` boolean | SDK state streams |
| User authenticated | Not yet documented | - | `AuthState.loggedIn` |
### Platform-Specific APIs
**React Native Hooks:**
* `useCollections()` - Main hook for collection management
* `loading` - Boolean indicating if operation is in progress
* `error` - Error object if operation fails
**Flutter Streams:**
* `authStateStream` - Monitor user authentication status
* `sdkStateStream` - Monitor overall SDK state
## Next Steps
1. **Design Collection Schedule**: Plan your recurring payment frequency and amounts
2. **Implement Backend**: Set up the [create collection endpoint](/api-reference/collections/create)
3. **Integrate SDK**: Choose your platform and implement the consent flow
4. **Test Thoroughly**: Test the complete collection lifecycle in sandbox
5. **Monitor Collections**: Set up webhooks to track collection status changes
Check out our [API Reference](/api-reference/collections/create) for detailed information about creating and managing collections.
# About Mona
Source: https://docs.mona.ng/introduction/about
### What is Mona?
Mona is an all-in-one SDK for Nigerian companies handling identification, authentication, payments and credit.
Mona is an SDK that is available across all popular web and mobile platforms. Its divided in five distinct components, all accessed from the same SDK. All components share the same underlying user model, meaning you can easily add components as your product requires.
To get started, please speak to our partnerships team to perform KYC and obtain your public and private keys.
# Start Here
Source: https://docs.mona.ng/introduction/start-here
Understanding the interplay between backend APIs and client-side SDKs
## How Mona Works
Mona's architecture is built on **Strong Customer Authentication (SCA)** using cryptographic signatures from on-device credentials. Every sensitive operation—whether consenting to future collections or making payments—is cryptographically signed using passkeys or private keys stored securely on the user's device.
This cryptographic foundation provides unparalleled security, but the complexity is completely abstracted away by our SDKs. You get enterprise-grade authentication without any of the implementation complexity.
Our architecture follows a secure two-step pattern that separates backend operations from client-side implementation. This ensures your sensitive API keys never leave your server while providing seamless user experiences in your apps and websites.
## Strong Customer Authentication (SCA)
At the heart of every Mona interaction is **Strong Customer Authentication**. This isn't just about passwords or SMS codes—it's about cryptographic proof that the user is who they claim to be and that they genuinely intend to perform the action.
### 🔐 **Cryptographic Signatures**
* Every payment and collection consent is **cryptographically signed**
* Uses **on-device credentials** like passkeys, biometrics, or secure private keys
* **Cannot be replicated, intercepted, or faked** by malicious actors
* Provides **non-repudiation**: mathematical proof of user intent
### 🛡️ **What Gets Authenticated**
* **Payment Authorization**: Every transaction requires cryptographic consent
* **Collection Consent**: Recurring payment permissions are cryptographically signed
* **Account Linking**: Bank account connections use secure authentication
* **Sensitive Updates**: Any account changes require re-authentication
### ✨ **SDK Abstraction**
The SDKs handle all the cryptographic complexity:
* **Automatic Key Management**: Generate, store, and manage cryptographic keys
* **Secure Signing**: Handle all cryptographic operations transparently
* **Cross-Platform**: Same security level across Web, iOS, Android, Flutter
* **Fallback Handling**: Graceful degradation when hardware security isn't available
* **Compliance**: Built-in PSD2, PCI DSS, and regulatory compliance
**You get bank-level security without writing a single line of cryptographic code.**
## The Two-Key System
### 🔒 **Private API Key** (Backend Only)
* Used for all server-side API calls
* Never exposed to client applications
* Authenticates requests to create transactions, collections, etc.
* Format: `x-api-key: your_private_key`
### 🌐 **Public Key** (Client-Side)
* Used to initialize SDKs in your apps/websites
* Safe to include in client-side code
* Loads your merchant branding and configuration
* Format: `mona_pub_xxxxx`
## The Integration Flow
Every Mona integration follows this secure pattern:
### Step 1: Backend Creates Resource
Your server uses the **private API key** to create a resource and get an ID:
```mermaid
graph LR
A[Your Backend] -->|Private API Key| B[Mona API]
B -->|Returns ID| A
A -->|Pass ID to Client| C[Your App/Website]
```
**Examples:**
* **Checkout**: Create transaction → Get `transactionId`
* **Collections**: Create collection → Get `collectionId`
* **Identification**: Create verification → Get `verificationId`
### Step 2: Client Uses Resource
Your app/website uses the **public key** + **resource ID** to initialize the SDK:
```mermaid
graph LR
A[Your App/Website] -->|Public Key + ID| B[Mona SDK]
B -->|Loads UI & Handles Flow| C[User Interaction]
```
## Practical Examples
### Checkout Flow
```javascript
// 1. Backend: Create transaction
POST /pay/create
Headers: x-api-key: your_private_key
Body: { amount: 5000, phone: "1234567890" }
Response: { transactionId: "txn_abc123", url: "..." }
// 2. Client: Initialize SDK
PayWithMona.initialize({ merchantKey: 'mona_pub_xyz' });
```
### Collections Flow
```javascript
// 1. Backend: Create collection
POST /collections
Headers: x-api-key: your_private_key
Body: {
maximumAmount: "600",
schedule: { type: "SCHEDULED", frequency: "MONTHLY" }
}
Response: { id: "col_def456" }
// 2. Client: Initialize SDK
useCollections({
onSuccess: () => console.log("Collection setup successful!")
});
// Then call: initiate("col_def456")
```
## Getting Your Keys
During onboarding, the Mona team will provide:
1. **Private API Key**: For server-side API calls
* Sandbox: `mona_sk_sandbox_xxxxx`
* Production: `mona_sk_prod_xxxxx`
2. **Public Key**: For client-side SDK initialization
* Sandbox: `mona_pub_sandbox_xxxxx`
* Production: `mona_pub_prod_xxxxx`
## Next Steps
1. **Choose Your Component**: [Checkout](/components/checkout) or [Collections](/components/collections)
2. **Implement Backend**: Use the API reference to create resources
3. **Integrate SDK**: Follow platform-specific guides for your app
4. **Test End-to-End**: Verify the full flow in sandbox environment