System Wallets

System wallets are organization-level wallets that allow partners to hold operational float, collect fees, manage settlements, and store revenue. Partners can transfer funds between their system wallets and their users' wallets.

Overview

Unlike user wallets which belong to individual users, system wallets belong to your partner organization. They serve different operational purposes and help you manage your platform's finances.

Wallet Purposes

You can use any custom purpose string for your system wallets. Common purposes include:

PurposeDescriptionUse Case
OPERATIONALOperational float for disbursementsPre-fund to disburse to users instantly
FEESCollection of transaction feesPlatform fees from user transactions
SETTLEMENTPool for settlements to usersBatch payouts to merchants/users
ESCROWHolds funds during pending transactionsMarketplace escrow, dispute holds
COMMISSIONCommission earningsAgent/affiliate commissions
REVENUEGeneral revenue/profit storageConsolidated platform earnings

Custom Purposes

You can create wallets with custom purposes for specific use cases. Purpose must be uppercase letters, numbers, and underscores only (2-50 characters). Examples:

  • ESCROW_ORDER_12345 - Escrow for a specific order
  • ESCROW_DISPUTE_789 - Funds held for a dispute
  • PROJECT_ALPHA_FUND - Project-specific funding pool
  • VENDOR_PAYOUTS_Q1 - Quarterly vendor payment pool

Account Number Format

System wallet account numbers follow the format: PSW-{PARTNER_ID}-{PURPOSE}

For example: PSW-A1B2C3D4-OPS

Permissions

System wallet operations require specific permissions on your API key:

  • system-wallets:create - Create system wallets
  • system-wallets:read - View system wallets and balances
  • system-wallets:manage - Transfer funds to/from user wallets

API Reference

Create System Wallet

List System Wallets

Get System Wallet

Get System Wallet Balance

Get System Wallet Transactions

Transfer to User Wallet

Transfer Between System Wallets

Webhooks

System wallet operations trigger the following webhook events:

Use Cases

Disbursement Platform

Use an OPERATIONAL wallet as float to instantly pay out to users without waiting for external funding:

  1. Fund your operational wallet via bank transfer or M-Pesa
  2. When a payout is triggered, transfer from operational wallet to user
  3. Monitor balance and top up as needed

Marketplace with Escrow

Use an ESCROW wallet to hold funds during transactions:

  1. When buyer pays, transfer from their wallet to escrow (FROM_USER)
  2. When order is delivered/confirmed, transfer from escrow to seller (TO_USER)
  3. If disputed, hold in escrow until resolution

Multi-Wallet Fund Management

Use system-to-system transfers to manage funds across different purposes:

  1. Collect fees from transactions into FEES wallet
  2. Move accumulated fees to REVENUE wallet periodically
  3. Transfer from REVENUE to OPERATIONAL to replenish float
  4. Move funds from order-specific ESCROW_ORDER_123 to SETTLEMENT when orders complete

Fee Collection

Use a FEES wallet to collect platform fees:

  1. Configure fees on transactions (via split payments or manual)
  2. Fees automatically accumulate in the fees wallet
  3. Periodically withdraw to your bank account

Code Examples

Create Wallet and Disburse to User

system-wallet-disburse.js
1const API_KEY = process.env.WASAAPAY_API_KEY;
2const BASE_URL = 'https://api.wasaapay.com/api/v1/partner';
3
4// 1. Create an operational wallet
5const createRes = await fetch(`${BASE_URL}/system-wallets`, {
6 method: 'POST',
7 headers: {
8 'Content-Type': 'application/json',
9 'X-API-Key': API_KEY,
10 'X-Idempotency-Key': 'create-ops-wallet-001',
11 },
12 body: JSON.stringify({
13 purpose: 'OPERATIONAL',
14 name: 'Main Float Account',
15 currency: 'KES',
16 }),
17});
18const { data: wallet } = await createRes.json();
19console.log('Wallet ID:', wallet.id);
20
21// 2. Disburse funds to a user wallet
22const transferRes = await fetch(
23 `${BASE_URL}/system-wallets/${wallet.id}/transfer`,
24 {
25 method: 'POST',
26 headers: {
27 'Content-Type': 'application/json',
28 'X-API-Key': API_KEY,
29 'X-Idempotency-Key': 'disburse-reward-001',
30 },
31 body: JSON.stringify({
32 direction: 'TO_USER',
33 userWalletId: 'wallet_user123',
34 amount: 5000,
35 narration: 'Cashback reward',
36 externalReference: 'reward_jan_001',
37 }),
38 }
39);
40const { data: transfer } = await transferRes.json();
41console.log('Transfer status:', transfer.status);

Escrow Workflow

escrow-workflow.js
1const API_KEY = process.env.WASAAPAY_API_KEY;
2const BASE_URL = 'https://api.wasaapay.com/api/v1/partner';
3
4async function createOrderEscrow(orderId, buyerWalletId, amount) {
5 // 1. Create a per-order escrow wallet
6 const createRes = await fetch(`${BASE_URL}/system-wallets`, {
7 method: 'POST',
8 headers: {
9 'Content-Type': 'application/json',
10 'X-API-Key': API_KEY,
11 'X-Idempotency-Key': `create-escrow-${orderId}`,
12 },
13 body: JSON.stringify({
14 purpose: `ESCROW_ORDER_${orderId}`,
15 name: `Escrow for Order #${orderId}`,
16 currency: 'KES',
17 metadata: { orderId },
18 }),
19 });
20 const { data: escrow } = await createRes.json();
21
22 // 2. Move buyer funds into escrow (FROM_USER)
23 await fetch(`${BASE_URL}/system-wallets/${escrow.id}/transfer`, {
24 method: 'POST',
25 headers: {
26 'Content-Type': 'application/json',
27 'X-API-Key': API_KEY,
28 'X-Idempotency-Key': `collect-${orderId}`,
29 },
30 body: JSON.stringify({
31 direction: 'FROM_USER',
32 userWalletId: buyerWalletId,
33 amount,
34 narration: `Payment for order #${orderId}`,
35 }),
36 });
37
38 return escrow.id;
39}
40
41async function releaseEscrow(escrowWalletId, sellerWalletId, amount, orderId) {
42 // Release funds to seller once order is confirmed
43 await fetch(`${BASE_URL}/system-wallets/${escrowWalletId}/transfer`, {
44 method: 'POST',
45 headers: {
46 'Content-Type': 'application/json',
47 'X-API-Key': API_KEY,
48 'X-Idempotency-Key': `release-${orderId}`,
49 },
50 body: JSON.stringify({
51 direction: 'TO_USER',
52 userWalletId: sellerWalletId,
53 amount,
54 narration: `Order #${orderId} payment released`,
55 }),
56 });
57}