Official TypeScript SDK for Monime - a modern, type-safe client library for Sierra Leone's leading payment platform. Provides comprehensive API coverage with predictable response patterns and excellent developer experience.
Package: monime-package
- Features
- Installation
- Environment Variables
- Quick Start
- API Reference
- Configuration
- Complete Examples
- TypeScript Types
- Idempotency
- Pagination
- Migration from Old Helpers
- Error Handling
- Security
- Contributing
- Support
- License
- Typed request/response objects for safer integrations
- Predictable return shape:
{ success, data?, error? } - Client-based auth: set credentials once per instance
- Zero dependencies (using native
fetch) for maximum performance and portability - Full API coverage for all Monime endpoints
- Tree-shaking support - only bundle what you use
- Dual module output - works with both CommonJS and ES modules
- Mobile Money support (Africell, Orange, etc.)
- Bank transfers and digital wallet integrations
- Checkout sessions for hosted payment pages
npm install monime-package
# or
pnpm add monime-package
# or
yarn add monime-packageRequirements:
- Node.js >= 14
- TypeScript >= 4.5 (for type safety)
- Modern bundler that supports ES modules and tree-shaking
Recommended to store credentials in .env:
MONIME_SPACE_ID=space_XXXXXXXX
MONIME_ACCESS_TOKEN=sk_live_xxx
MONIME_VERSION=caph.2025-08-23 # Optional, defaults to latestThe MonimeClient will automatically look for these variables if no options are passed to the constructor.
You can initialize the client by passing credentials directly:
import { createClient } from "monime-package";
const client = createClient({
monimeSpaceId: "your_space_id",
accessToken: "your_access_token",
monimeVersion: "caph.2025-08-23", // Optional
});If you have a .env file, you can initialize the client even more simply:
import "dotenv/config";
import { createClient } from "monime-package";
// Client will automatically use MONIME_SPACE_ID and MONIME_ACCESS_TOKEN from process.env
const client = createClient({});Now all methods use the client’s credentials automatically.
// ESM / TypeScript
import { createClient, type DestinationOption } from "monime-package";
// CommonJS
// const { createClient } = require("monime-package");All methods return the same envelope:
type Result<T> = {
success: boolean;
data?: T;
error?: Error;
};The client exposes namespaced APIs under client.<module>. Below is the complete API reference:
Manage all incoming payments (payins).
// Retrieve payment details
client.payment.retrieve(paymentId: string): Promise<Result<RetrievePaymentResponse>>
// List payments
client.payment.list(): Promise<Result<ListPaymentsResponse>>
// Update payment
client.payment.update(paymentId: string, body: any): Promise<Result<UpdatePaymentResponse>>Manage webhooks for real-time notifications.
// Create webhook
client.webhook.create(body: CreateWebhookRequest): Promise<Result<CreateWebhookResponse>>
// Retrieve webhook
client.webhook.retrieve(webhookId: string): Promise<Result<GetWebhookResponse>>
// List webhooks
client.webhook.list(): Promise<Result<ListWebhooksResponse>>
// Update webhook
client.webhook.update(webhookId: string, body: UpdateWebhookRequest): Promise<Result<UpdateWebhookResponse>>
// Delete webhook
client.webhook.delete(webhookId: string): Promise<Result<void>>Manage payment receipts.
// Retrieve receipt
client.receipt.retrieve(orderNumber: string): Promise<Result<GetReceiptResponse>>
// Redeem receipt
client.receipt.redeem(orderNumber: string, body: any): Promise<Result<RedeemReceiptResponse>>Generate USSD OTPs.
// Create USSD OTP
client.ussdOtp.create(body: CreateUssdOtpRequest): Promise<Result<CreateUssdOtpResponse>>Get provider KYC details.
// Retrieve provider KYC
client.providerKyc.retrieve(providerId: string): Promise<Result<GetProviderKycResponse>>Manage digital wallets and financial accounts.
// Create a new financial account
client.financialAccount.create({
accountName: string,
currency: "USD" | "SLE",
description?: string,
metadata?: Record<string, any>
}): Promise<Result<CreateFinancialAccountResponse>>
// Retrieve account details by ID
client.financialAccount.retrieve(financialAccountId: string): Promise<Result<RetrieveFinancialAccountResponse>>
// List all financial accounts
client.financialAccount.list(): Promise<Result<ListFinancialAccountsResponse>>Parameters:
name: Account name (required)financialAccountId: Unique account identifier (required)
Example:
// Create account
const account = await client.financialAccount.create({
accountName: "My Wallet",
currency: "SLE"
});
if (account.success) {
console.log("Account ID:", account.data.id);
}
// Retrieve account details
const details = await client.financialAccount.retrieve("fa-123456");Transfer funds between your financial accounts.
// Create internal transfer
client.internalTransfer.create({
sourceAccount: string,
destinationAccount: string,
amount: number,
description?: string
}): Promise<Result<CreateInternalTransferResponse>>
// Retrieve transfer details
client.internalTransfer.retrieve(internalTransferId: string): Promise<Result<RetrieveInternalTransferResponse>>
// List all transfers
client.internalTransfer.list(): Promise<Result<ListInternalTransfersResponse>>
// Cancel/delete a transfer
client.internalTransfer.delete(internalTransferId: string): Promise<Result<void>>Parameters:
sourceAccount: Source financial account ID (required)destinationAccount: Destination financial account ID (required)amount: Transfer amount in SLE (required, must be > 0)internalTransferId: Transfer ID for get/delete operations (required)
Example:
// Transfer 1000 SLE between accounts
const transfer = await client.internalTransfer.create({
sourceAccount: "fa-source",
destinationAccount: "fa-dest",
amount: 1000
});
if (transfer.success) {
console.log("Transfer ID:", transfer.data.id);
console.log("Status:", transfer.data.status);
}Generate USSD payment codes for mobile money transactions.
// Create payment code
client.paymentCode.create({
paymentName: string,
amount: number,
financialAccountId: string,
name: string,
phoneNumber: string,
}): Promise<Result<CreatePaymentCodeResponse>>
// Retrieve payment code details
client.paymentCode.retrieve(paymentCodeId: string): Promise<Result<RetrievePaymentCodeResponse>>
// List all payment codes
client.paymentCode.list(): Promise<Result<ListPaymentCodesResponse>>
// Delete payment code
client.paymentCode.delete(paymentCodeId: string): Promise<Result<void>>Parameters:
paymentName: Description for the payment (required)amount: Payment amount in SLE (required, must be > 0)financialAccount: Target financial account ID (required)username: Customer name (required)phoneNumber: Authorized phone number (required)paymentCodeId: Payment code ID for get/delete operations (required)
Example:
// Create USSD payment code
const paymentCode = await client.paymentCode.create({
paymentName: "Order #12345",
amount: 5000, // 50.00 SLE
financialAccountId: "fa-123456",
name: "John Doe",
phoneNumber: "0771234567"
});
if (paymentCode.success) {
console.log("USSD Code:", paymentCode.data.ussdCode);
console.log("Expires at:", paymentCode.data.expireTime);
}Send money to mobile money providers, banks, or wallets.
// Create payout
client.payout.create({
amount: number,
destination: DestinationOption,
sourceAccount: string,
}): Promise<Result<CreatePayoutResponse>>
// List all payouts
client.payout.list(): Promise<Result<ListPayoutsResponse>>
// Retrieve specific payout
client.payout.retrieve(payoutId: string): Promise<Result<RetrievePayoutResponse>>
// Cancel payout
client.payout.delete(payoutId: string): Promise<Result<void>>Destination Types:
type DestinationOption =
| { type: "momo"; providerId: "m17" | "m18"; phoneNumber: string }
| { type: "bank"; providerId: "b01" | "b02" | "b03"; accountNumber: string }
| { type: "wallet"; providerId: "w01" | "w02"; walletId: string };Parameters:
amount: Payout amount in SLE (required, must be > 0)destination: Payout destination (required)sourceAccount: Source financial account ID (required)payoutId: Payout ID for get/delete operations (required)
Example:
// Mobile money payout
const mobileMoneyPayout = await client.payout.create({
amount: 10000, // 100.00 SLE
destination: { type: "momo", providerId: "m17", phoneNumber: "0771234567" },
sourceAccount: "fa-123456"
});
// Bank transfer payout
const bankPayout = await client.payout.create({
amount: 50000, // 500.00 SLE
destination: { type: "bank", providerId: "b01", accountNumber: "1234567890" },
sourceAccount: "fa-123456"
});Query transaction history and details.
// Retrieve transaction details
client.financialTransaction.retrieve(transactionId: string): Promise<Result<RetrieveTransactionResponse>>
// List all transactions
client.financialTransaction.list(): Promise<Result<ListTransactionsResponse>>Parameters:
transactionId: Transaction ID (required)
Example:
// List all transactions
const transactions = await client.financialTransaction.list();
if (transactions.success) {
transactions.data.forEach(tx => {
console.log(`${tx.type}: ${tx.amount.value} ${tx.amount.currency}`);
});
}Create hosted payment pages for seamless customer payments.
// Create checkout session
client.checkoutSession.create({
name: string,
amount: number,
quantity: number,
successUrl: string,
cancelUrl: string,
description?: string,
financialAccountId?: string,
primaryColor?: string,
images?: string[],
}): Promise<Result<CreateCheckoutResponse>>
// List all checkout sessions
client.checkoutSession.list(): Promise<Result<ListCheckoutsResponse>>
// Retrieve specific checkout session
client.checkoutSession.retrieve(checkoutId: string): Promise<Result<RetrieveCheckoutResponse>>
// Delete checkout session
client.checkoutSession.delete(checkoutId: string): Promise<Result<void>>Parameters:
name: Product/service name (required)amount: Price per item in SLE (required)quantity: Number of items (required)successUrl: Redirect URL after successful payment (required)cancelUrl: Redirect URL when payment is cancelled (required)description: Product description (optional)financialAccountId: Target account for payments (optional)primaryColor: Brand color in hex format (optional)images: Product image URLs (optional)checkoutId: Checkout session ID for get/delete operations (required)
Example:
// Create checkout for e-commerce
const checkout = await client.checkoutSession.create({
name: "Premium Subscription",
amount: 2500, // 25.00 SLE per month
quantity: 1,
successUrl: "https://myapp.com/success",
cancelUrl: "https://myapp.com/cancel",
description: "Monthly premium subscription",
financialAccountId: "fa-123456",
primaryColor: "#3B82F6", // Blue color
images: ["https://myapp.com/images/premium.jpg"]
});
if (checkout.success) {
// Redirect customer to checkout page
console.log("Checkout URL:", checkout.data.redirectUrl);
console.log("Order Number:", checkout.data.orderNumber);
}The client accepts the following options (see src/client.ts):
type ClientOptions = {
monimeSpaceId: string; // Your Monime Space ID
accessToken: string; // Your Monime API token
monimeVersion?: "caph.2025-08-23" | "caph.2025-06-20"; // API Version
};- Authentication: Both values are required. Prefer environment variables.
- Headers: SDK automatically sets
AuthorizationandMonime-Space-Idfor each call.
This package uses modern tooling for development and building:
- tsup for fast TypeScript compilation with dual CJS/ESM output
- Biome for code formatting and linting
- Vitest for testing framework
# Build the package
pnpm build
# Run tests
pnpm test
# Format and lint code
pnpm lint-formatThe package is organized for maximum simplicity:
src/resources/: All API resource implementations (e.g.,payment.ts,payout.ts)src/types/: Consolidated TypeScript interface definitionssrc/client.ts: The mainMonimeCliententry pointsrc/http.ts: Shared nativefetchlogic and telemetry
Here are comprehensive examples showing real-world usage patterns:
import { createClient, type DestinationOption } from "monime-package";
// Initialize client
const client = createClient({
monimeSpaceId: process.env.MONIME_SPACE_ID!,
accessToken: process.env.MONIME_ACCESS_TOKEN!,
});
// Create business account
const businessAccount = await client.financialAccount.create("E-commerce Store", "SLE");
if (!businessAccount.success) {
throw new Error(`Failed to create account: ${businessAccount.error?.message}`);
}
const accountId = businessAccount.data!.id;
console.log(`Created account: ${accountId}`);
console.log(`Balance: ${businessAccount.data!.balance.available.value} SLE`);
// Create checkout session for customer
const checkout = await client.checkoutSession.create(
"Digital Camera",
45000, // 450.00 SLE
1,
"https://store.com/success",
"https://store.com/cancel",
{
description: "Professional DSLR Camera with lens kit",
financialAccountId: accountId,
primaryColor: "#2563EB", // Brand blue
images: ["https://store.com/camera.jpg"]
}
);
if (checkout.success) {
console.log(`Checkout created: ${checkout.data!.id}`);
console.log(`Payment URL: ${checkout.data!.redirectUrl}`);
console.log(`Order: ${checkout.data!.orderNumber}`);
}// 1. Generate USSD payment code for customer
const paymentCode = await client.paymentCode.create(
"Invoice #INV-2024-001",
15000, // 150.00 SLE
accountId,
"Customer Name",
"0771234567"
);
if (paymentCode.success) {
console.log(`USSD Code: ${paymentCode.data!.ussdCode}`);
console.log(`Expires: ${paymentCode.data!.expireTime}`);
// Send USSD code to customer via SMS/email
await sendToCustomer(paymentCode.data!.ussdCode);
}
// 2. Monitor payment status
const checkPaymentStatus = async (codeId: string) => {
const status = await client.paymentCode.retrieve(codeId);
if (status.success) {
console.log(`Payment Status: ${status.data!.status}`);
return status.data!.status === 'completed';
}
return false;
};
// 3. Process payout to supplier after payment received
const paySupplier = async () => {
const payout = await client.payout.create(
8000, // 80.00 SLE to supplier
{
type: "momo",
providerId: "m17",
phoneNumber: "0779876543"
},
accountId
);
if (payout.success) {
console.log(`Payout ID: ${payout.data!.id}`);
console.log(`Status: ${payout.data!.status}`);
console.log(`Fees: ${payout.data!.fees.map(f => `${f.code}: ${f.amount.value}`)}`);
}
};// Create multiple accounts for different purposes
const accounts = await Promise.all([
client.financialAccount.create("Sales Revenue", "SLE"),
client.financialAccount.create("Operating Expenses", "SLE"),
client.financialAccount.create("Tax Reserve", "SLE"),
]);
// Check if all accounts were created successfully
if (accounts.every(acc => acc.success)) {
const [salesAccount, expensesAccount, taxAccount] = accounts.map(acc => acc.data!.id);
// Distribute revenue: 70% operations, 30% tax reserve
const revenue = 100000; // 1000.00 SLE
const transfers = await Promise.all([
client.internalTransfer.create(salesAccount, expensesAccount, revenue * 0.7),
client.internalTransfer.create(salesAccount, taxAccount, revenue * 0.3),
]);
transfers.forEach((transfer, index) => {
const purpose = index === 0 ? 'operations' : 'tax reserve';
if (transfer.success) {
console.log(`${purpose} transfer: ${transfer.data!.id}`);
}
});
}// List all transactions for reporting
const transactions = await client.financialTransaction.list();
if (transactions.success) {
const txs = transactions.data!.result;
// Group transactions by type
const summary = txs.reduce((acc, tx) => {
acc[tx.type] = (acc[tx.type] || 0) + tx.amount.value;
return acc;
}, {} as Record<string, number>);
console.log('Transaction Summary:', summary);
// Find large transactions (> 50,000 SLE)
const largeTransactions = txs.filter(tx => Math.abs(tx.amount.value) > 50000);
console.log(`Large transactions: ${largeTransactions.length}`);
// Check account balances after transactions
const accountIds = [...new Set(txs.map(tx => tx.financialAccount.id))];
for (const accountId of accountIds) {
const account = await client.financialAccount.retrieve(accountId);
if (account.success) {
console.log(`Account ${accountId}: ${account.data!.balance.available.value} SLE`);
}
}
}// Robust error handling with retries
const createTransferWithRetry = async (
sourceAccount: string,
destinationAccount: string,
amount: number,
maxRetries = 3
) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const transfer = await client.internalTransfer.create(sourceAccount, destinationAccount, amount);
if (transfer.success) {
return transfer;
}
// Log the error
console.error(`Transfer attempt ${attempt} failed:`, transfer.error?.message);
// Don't retry on validation errors
if (transfer.error?.message?.includes('validation')) {
throw transfer.error;
}
// Wait before retrying (exponential backoff)
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
throw new Error(`Transfer failed after ${maxRetries} attempts`);
};
// Usage
try {
const transfer = await createTransferWithRetry("fa-source", "fa-dest", 10000);
console.log("Transfer successful:", transfer.data!.id);
} catch (error) {
console.error("Transfer failed permanently:", error.message);
}For POST endpoints, the SDK automatically attaches an Idempotency-Key header. This helps prevent duplicate requests if you retry the same call. Keys are generated per module instance.
List endpoints return a pagination object in data?.pagination when available, including a next cursor/URL. The SDK currently returns this information as-is; use the next value to fetch subsequent pages if needed.
Previously, you called standalone helpers and passed credentials on every call:
// old (example)
createFinancialAccount("name", MONIME_SPACE_ID, MONIME_ACCESS_TOKEN);Now, instantiate a client once and use namespaced methods. Credentials are stored internally:
const client = createClient({ monimeSpaceId, accessToken });
await client.financialAccount.create("name");- Standard envelope: every call returns
{ success, data?, error? }. - Validation: inputs are validated (e.g. non-empty IDs, positive amounts) and will short-circuit with
success: false+MonimeValidationError. - MonimeError: remote errors are returned as
MonimeErrorobjects, which include:status: HTTP status code (e.g. 401, 404)requestId: The unique request ID from Monime's serversdetails: Rich error details from the API
- Do not commit tokens. Use environment variables or a secret manager.
- Restrict tokens to the least privileges necessary.
This project follows semantic versioning (SemVer). See releases for notable changes.
- File issues and feature requests at the repository:
https://github.com/Walon-Foundation/monime-package/issues. - For production incidents, rotate credentials if you suspect exposure.
All result payload types are exported from the package for complete type safety:
import type {
// Core types
ClientOptions,
// Payment types
RetrievePaymentResponse,
ListPaymentsResponse,
UpdatePaymentResponse,
// Webhook types
CreateWebhookRequest,
CreateWebhookResponse,
GetWebhookResponse,
ListWebhooksResponse,
UpdateWebhookRequest,
UpdateWebhookResponse,
// Receipt types
GetReceiptResponse,
RedeemReceiptResponse,
// USSD OTP types
CreateUssdOtpRequest,
CreateUssdOtpResponse,
// Provider KYC types
GetProviderKycResponse,
// Financial Account types
CreateFinancialAccountResponse,
RetrieveFinancialAccountResponse,
ListFinancialAccountsResponse,
// Internal Transfer types
CreateInternalTransferResponse,
RetrieveInternalTransferResponse,
ListInternalTransfersResponse,
// Payment Code types
CreatePaymentCodeResponse,
ListPaymentCodesResponse,
RetrievePaymentCodeResponse,
// Payout types
DestinationOption,
CreatePayoutResponse,
ListPayoutsResponse,
RetrievePayoutResponse,
// Financial Transaction types
RetrieveTransactionResponse,
ListTransactionsResponse,
// Checkout Session types
CreateCheckoutResponse,
ListCheckoutsResponse,
RetrieveCheckoutResponse,
} from "monime-package";All API responses follow this consistent pattern:
type Result<T> = {
success: boolean;
data?: T;
error?: Error | MonimeError;
};type ClientOptions = {
monimeSpaceId: string; // Your Monime Space ID
accessToken: string; // Your API access token
};type DestinationOption =
| {
type: "momo";
providerId: "m17" | "m18"; // MTN, Orange Money
phoneNumber: string;
}
| {
type: "bank";
providerId: "b01" | "b02" | "b03"; // Bank codes
accountNumber: string;
}
| {
type: "wallet";
providerId: "w01" | "w02"; // Wallet provider codes
walletId: string;
};// Account creation/retrieval response
interface CreateFinancialAccount {
id: string; // Unique account ID
uvan: string; // Internal identifier
name: string; // Account name
currency: string; // Always "SLE"
reference: string; // Account reference
description: string; // Account description
balance: {
available: {
currency: string;
value: number; // Balance in cents (SLE)
};
};
createTime: string; // ISO timestamp
updateTime: string; // ISO timestamp
}interface CreateInternalTransferResponse {
id: string; // Transfer ID
status: string; // Transfer status
amount: {
currency: string;
value: number; // Amount in cents
};
sourceFinancialAccount: { id: string };
destinationFinancialAccount: { id: string };
financialTransactionReference: string;
description: string;
failureDetail: {
code: string;
message: string;
};
ownershipGraph: {
owner: {
id: string;
type: string;
owner: {
id: string;
type: string;
};
};
};
createTime: string;
updateTime: string;
}interface CreatePaymentCodeResponse {
id: string;
mode: string; // "recurrent"
status: string; // Payment status
name: string; // Payment name
amount: {
currency: string;
value: number; // Amount in cents
};
enable: boolean;
expireTime: string; // ISO timestamp
customer: { name: string };
ussdCode: string; // USSD code for payment
reference: string;
authorizedProviders: string[];
authorizedPhoneNumber: string;
recurrentPaymentTarget: {
expectedPaymentCount: number;
expectedPaymentTotal: {
currency: string;
value: number;
};
};
financialAccountId: string;
processedPaymentData: {
amount: { currency: string; value: number };
orderId: string;
paymentId: string;
orderNumber: string;
channelData: {
providerId: string;
accountId: string;
reference: string;
};
financialTransactionReference: string;
};
createTime: string;
updateTime: string;
ownershipGraph: OwnershipGraph;
}interface CreateCheckoutResponse {
id: string;
status: string;
name: string;
orderNumber: string; // Generated order number
reference: string;
description: string;
redirectUrl: string; // Checkout page URL
cancelUrl: string;
successUrl: string;
lineItems: {
data: Array<{
type: string;
id: string;
name: string;
price: { currency: string; value: number };
quantity: number;
reference: string;
description: string;
images: string[];
}>;
};
financialAccountId: string;
brandingOptions: {
primaryColor: string;
};
expireTime: string;
createTime: string;
ownershipGraph: OwnershipGraph;
}// Pagination for list responses
interface Pagination {
count: number; // Total count
next: string; // Next page URL/cursor
}
// Ownership information
interface OwnershipGraph {
owner: {
id: string;
type: string;
owner: {
id: string;
type: string;
};
};
}
// Amount representation
interface Amount {
currency: string; // Always "SLE"
value: number; // Amount in cents (multiply by 100 for SLE)
}// Type-safe account creation
const createAccountTyped = async (name: string): Promise<CreateFinancialAccountResponse | null> => {
const result = await client.financialAccount.create({
accountName: name,
currency: "SLE"
});
return result.success ? result.data! : null;
};
// Type-safe payout with validation
const createMobileMoneyPayout = async (
amount: number,
phoneNumber: string,
sourceAccount: string
): Promise<CreatePayoutResponse | null> => {
const result = await client.payout.create({
amount,
sourceAccount,
destination: {
type: "momo",
providerId: "m17",
phoneNumber,
}
});
return result.success ? result.data! : null;
};
// Type-safe transaction processing
const processTransactions = async (): Promise<void> => {
const txResult = await client.financialTransaction.list();
if (txResult.success && txResult.data) {
const transactions: ListTransactionsResponse = txResult.data;
transactions.result.forEach((tx: RetrieveTransactionResponse) => {
console.log(`Transaction ${tx.id}: ${tx.amount.value / 100} ${tx.amount.currency}`);
});
}
};We welcome contributions.
- Fork the repository on GitHub
- Clone your fork locally
- Install dependencies with
pnpm install - Create a feature branch from
main - Make your changes following our coding conventions
- Run linting with
pnpm lint-format - Test your changes with
pnpm test - Build the package with
pnpm build - Submit a pull request with a clear description
For detailed contribution guidelines, see CONTRIBUTING.md
MIT — see LICENSE.