Bonaventure OgetoBy Bonaventure Ogeto|

Splitting Payments for SACCOs and Chamas

Create a Paystack subaccount for each fund (welfare fund, investment fund, operational expenses). When a member contributes, pass a Transaction Split that routes the contribution breakdown to each subaccount. Store each member's contribution in your database. For dividends or loan payouts, use Paystack bulk transfers to pay multiple members at once.

Member Contribution Split

// Monthly contribution: NGN 5,000
// Savings fund: 3,000 (60%)
// Welfare fund: 1,000 (20%)
// Operational: 1,000 (20% stays in main account)

app.post('/api/contributions', async (req, res) => {
  var { memberId, email } = req.body;
  var group = await db.groups.findByMemberId(memberId);

  var response = await fetch('https://api.paystack.co/transaction/initialize', {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email,
      amount: 500000, // NGN 5,000 in kobo
      split_code: group.contribution_split_code, // Pre-created split group
      metadata: {
        member_id: memberId,
        group_id: group.id,
        contribution_month: new Date().toISOString().slice(0, 7),
      },
    }),
  });

  var data = await response.json();
  res.json({ authorization_url: data.data.authorization_url });
});
// On charge.success: record the contribution
if (event.event === 'charge.success') {
  var meta = event.data.metadata;
  if (meta?.member_id) {
    await db.contributions.create({
      member_id: meta.member_id,
      group_id: meta.group_id,
      month: meta.contribution_month,
      amount: event.data.amount / 100,
      reference: event.data.reference,
      status: 'paid',
    });
    // Update member's total savings balance
    await db.memberBalances.increment({ member_id: meta.member_id, amount: 3000 }); // Savings portion
  }
}

Dividend Bulk Payout to Members

// Quarterly dividend payout via bulk transfer
async function payDividends(groupId, dividendPerMember) {
  var members = await db.members.findAll({ where: { group_id: groupId, status: 'active' } });

  var transfers = members.map(member => ({
    amount: Math.round(dividendPerMember * 100),
    reference: 'div_' + groupId + '_' + member.id + '_' + Date.now(),
    reason: 'Q2 2026 dividend',
    recipient: member.paystack_recipient_code,
  }));

  var response = await fetch('https://api.paystack.co/transfer/bulk', {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ currency: 'NGN', source: 'balance', transfers }),
  });

  var data = await response.json();
  return data;
}

Learn More

Key Takeaways

  • Create subaccounts for each chama fund: welfare, savings/investment, and operational — each with its own bank account.
  • Member contributions are split across funds using a Transaction Split group with flat kobo amounts.
  • Track each member's contribution balance in your database for loan eligibility and dividend calculation.
  • Use Paystack bulk transfers (POST /transfer/bulk) for dividend payouts to multiple members in one API call.
  • Automate monthly contribution reminders — members often forget. Send SMS 3 days before contribution due date.
  • Store member bank account details as Paystack transfer recipients for easy recurring payouts.

Frequently Asked Questions

Do SACCOs need regulatory approval to use Paystack?
In Kenya, SACCOs regulated by SASRA (SACCO Societies Regulatory Authority) may have requirements around digital payment systems. In Nigeria, cooperatives regulated by the Cooperatives Societies Law may need state government approval. Check with the relevant regulator before deploying a financial application for a regulated cooperative.
How do I track loan repayments for SACCO members using Paystack?
Create a separate transaction flow for loan repayments: a different API endpoint that routes to the loan fund subaccount and records the repayment in a loan_repayments table. Track outstanding loan balance per member. Do not mix contribution and loan repayment flows in the same transaction.
What is the cheapest way to run monthly chama payouts?
Use Paystack bulk transfers for dividend or merry-go-round payouts — they are more efficient than individual transfers. For monthly merry-go-round (one member receives the month's pot), send a single transfer to the selected member. Bulk transfers save API calls when paying multiple members.
Can members contribute via M-Pesa instead of card?
Paystack in Kenya supports M-Pesa as a payment channel. When initializing the contribution transaction, do not restrict payment channels — allow the Paystack checkout to show all supported methods including M-Pesa for Kenyan members. Nigerian members can use bank transfer or USSD.

Ready to build real-world apps?

Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.

Apply to the McTaba Marathon