McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Paystack Split Not Applied to Transaction
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Paystack Split Not Applied to Transaction

Paystack splits fail to apply for four main reasons: the split_code was not included in the transaction initialization call, the subaccount in the split is inactive or has invalid bank details, the split was created but not set as the default split for your integration, or the transaction was initialized before the split was created. Verify the split exists via the API, confirm the subaccount is active, and include the split_code in every transaction initialization request.

In this article

  1. 1. How Paystack Transaction Splits Work
  2. 2. Cause 1: split_code Not Passed in Transaction Initialization
  3. 3. Cause 2: Subaccount Is Inactive or Has Invalid Bank Details
  4. 4. Cause 3: Split Configuration Errors
  5. 5. Using a Default Split Instead of Per-Transaction split_code
  6. 6. Creating a Split Correctly from Scratch
  7. 7. Verifying the Split Was Actually Applied
  8. 8. Split Debugging Checklist
  9. 9. How to Verify Your Fix

How Paystack Transaction Splits Work

Paystack transaction splits let you automatically divide payment proceeds between multiple parties. A marketplace that takes a commission, a platform that pays vendors, a service that shares revenue with partners. Splits handle the accounting at the payment layer so you do not have to calculate and transfer funds manually.

The flow works like this:

  1. You create one or more subaccounts. Each subaccount represents a party that receives a share of the payment.
  2. You create a split configuration that defines how money is divided: percentage-based, flat amount, or a combination.
  3. When initializing a transaction, you include the split_code in the request. Paystack applies the split when the payment succeeds.
  4. After settlement, each party receives their share directly from Paystack. You do not need to transfer funds yourself.

When a split "does not apply," it means the full amount settled to your main account as if the split did not exist. The customer paid the correct amount, but the money was not divided. This is a configuration problem, not a payment problem.

Cause 1: split_code Not Passed in Transaction Initialization

This is the most common reason. You created the split in the dashboard, but you did not include the split_code when initializing the transaction. Paystack does not know to apply it.

Unless you have set a default split (more on that below), you must explicitly pass the split_code in every transaction initialization request.

const axios = require('axios');

// WRONG: No split_code - entire amount goes to main account
async function initializeWithoutSplit() {
  const response = await axios.post(
    'https://api.paystack.co/transaction/initialize',
    {
      email: 'customer@example.com',
      amount: 1000000, // 10,000 NGN in kobo
    },
    {
      headers: {
        Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );
  return response.data;
}

// CORRECT: split_code included - payment will be split
async function initializeWithSplit() {
  const response = await axios.post(
    'https://api.paystack.co/transaction/initialize',
    {
      email: 'customer@example.com',
      amount: 1000000, // 10,000 NGN in kobo
      split_code: 'SPL_xxxxxxxxxxxxxxx', // Your split code
    },
    {
      headers: {
        Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );
  return response.data;
}

If you are using the Popup or Inline JS to initialize (not the server-side API), you cannot pass split_code from the frontend. You must initialize the transaction on your server, get the access_code, and pass that to the popup. The split_code goes in the server-side initialization call, not in the frontend JavaScript.

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Cause 2: Subaccount Is Inactive or Has Invalid Bank Details

Every subaccount in a split must be active and have valid, verified bank details. If a subaccount is inactive (because bank verification failed, or it was manually deactivated), the split will not apply.

Check the status of your subaccounts:

async function checkSubaccountStatus(subaccountCode) {
  try {
    const response = await axios.get(
      `https://api.paystack.co/subaccount/${subaccountCode}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
        },
      }
    );

    const sub = response.data.data;
    console.log('Subaccount:', sub.business_name);
    console.log('Active:', sub.is_verified);  // Must be true
    console.log('Bank:', sub.settlement_bank);
    console.log('Account number:', sub.account_number);
    console.log('Percentage charge:', sub.percentage_charge);

    if (!sub.is_verified) {
      console.warn('This subaccount is NOT verified. Splits using it will fail.');
    }

    return sub;
  } catch (error) {
    if (error.response?.status === 404) {
      console.error('Subaccount not found. Check the subaccount code.');
    }
    throw error;
  }
}

Common bank detail problems:

  • The account number does not match the account name at the bank. Paystack verifies this during subaccount creation.
  • The bank code is wrong. Each bank has a specific code (e.g., 057 for Zenith, 033 for UBA). Using the wrong code causes verification failure.
  • The account was closed or frozen at the bank after the subaccount was created in Paystack.

Cause 3: Split Configuration Errors

Even if you pass the split_code and the subaccounts are active, the split can fail if the configuration itself is invalid.

Percentage splits must add up correctly. If you create a percentage split where the shares exceed 100%, or where there is an unaccounted remainder, the split behavior may be unpredictable.

Flat splits must not exceed the transaction amount. If you have a flat split that takes 5,000 NGN from each transaction, but a customer pays only 3,000 NGN, the split cannot be applied because there is not enough money.

// Verify your split configuration
async function verifySplitConfig(splitCode) {
  try {
    const response = await axios.get(
      `https://api.paystack.co/split/${splitCode}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
        },
      }
    );

    const split = response.data.data;
    console.log('Split name:', split.name);
    console.log('Split type:', split.type); // "percentage" or "flat"
    console.log('Currency:', split.currency);
    console.log('Active:', split.active);
    console.log('Bearer type:', split.bearer_type); // "all", "account", or "subaccount"
    console.log('Bearer subaccount:', split.bearer_subaccount);

    console.log('\nSubaccounts in this split:');
    for (const sub of split.subaccounts) {
      console.log(`  - ${sub.subaccount.business_name}: ${sub.share} (${split.type})`);
    }

    // Check for issues
    if (split.type === 'percentage') {
      const totalShare = split.subaccounts.reduce((sum, s) => sum + s.share, 0);
      console.log(`\nTotal percentage allocated: ${totalShare}%`);
      if (totalShare > 100) {
        console.warn('Total exceeds 100%. This split is misconfigured.');
      }
    }

    return split;
  } catch (error) {
    console.error('Failed to fetch split:', error.response?.data || error.message);
    throw error;
  }
}

Also check the bearer_type. This determines who pays the Paystack transaction fee:

  • "all": The fee is split proportionally among all parties.
  • "account": Your main account absorbs the entire fee.
  • "subaccount": A specific subaccount absorbs the fee.

Using a Default Split Instead of Per-Transaction split_code

If every transaction on your integration should use the same split, you can set a default split in the Paystack dashboard. Go to Settings > Preferences > Transaction Split, and select your split configuration. Once set, every transaction on that integration is automatically split without needing split_code in the API call.

This is convenient but comes with a catch: if you need different splits for different transactions (e.g., different vendor shares for different products), a default split will not work. You need per-transaction split_code values.

When to use a default split:

  • Simple marketplace with one standard commission rate
  • Revenue sharing with a single partner at a fixed percentage
  • Platform fee that is the same for every transaction

When to use per-transaction split_code:

  • Multi-vendor marketplace where each vendor has a different split
  • Variable commission rates based on product category
  • Transactions where some should be split and others should not

If you have a default split set but also pass a split_code in the transaction, the per-transaction split_code takes precedence. This lets you override the default for specific transactions.

Creating a Split Correctly from Scratch

If your split is not working, sometimes the fastest fix is to create a new one from scratch, verifying each step.

const axios = require('axios');

const PAYSTACK_SECRET = process.env.PAYSTACK_SECRET_KEY;
const headers = {
  Authorization: `Bearer ${PAYSTACK_SECRET}`,
  'Content-Type': 'application/json',
};

async function setupSplitFromScratch() {
  // Step 1: Create subaccount (or use existing one)
  const subaccountResponse = await axios.post(
    'https://api.paystack.co/subaccount',
    {
      business_name: 'Vendor Store',
      bank_code: '057',     // Zenith Bank
      account_number: '2190209948',
      percentage_charge: 80, // Vendor gets 80% (used if no split overrides)
    },
    { headers }
  );

  const subaccountCode = subaccountResponse.data.data.subaccount_code;
  console.log('Subaccount created:', subaccountCode);

  // Step 2: Create the split
  const splitResponse = await axios.post(
    'https://api.paystack.co/split',
    {
      name: 'Platform 20/80 Split',
      type: 'percentage',
      currency: 'NGN',
      subaccounts: [
        {
          subaccount: subaccountCode,
          share: 80, // 80% to vendor
        },
      ],
      bearer_type: 'account',    // Main account pays the fee
      bearer_subaccount: '',
    },
    { headers }
  );

  const splitCode = splitResponse.data.data.split_code;
  console.log('Split created:', splitCode);

  // Step 3: Test with a transaction
  const txnResponse = await axios.post(
    'https://api.paystack.co/transaction/initialize',
    {
      email: 'buyer@example.com',
      amount: 1000000, // 10,000 NGN
      split_code: splitCode,
    },
    { headers }
  );

  console.log('Transaction initialized:', txnResponse.data.data.reference);
  console.log('Checkout URL:', txnResponse.data.data.authorization_url);

  return { subaccountCode, splitCode, reference: txnResponse.data.data.reference };
}

setupSplitFromScratch().catch(console.error);

After the test transaction completes (use test card 4084 0840 8408 4081 in sandbox), verify the split was applied by checking the transaction details.

Verifying the Split Was Actually Applied

After a transaction completes, verify the split through the API. Do not assume it worked just because the payment succeeded.

async function verifySplitApplied(reference) {
  const response = await axios.get(
    `https://api.paystack.co/transaction/verify/${reference}`,
    {
      headers: {
        Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
      },
    }
  );

  const data = response.data.data;

  console.log('Transaction status:', data.status);
  console.log('Total amount:', data.amount / 100, 'NGN');
  console.log('Fees:', data.fees / 100, 'NGN');

  if (data.split) {
    console.log('\nSplit applied: YES');
    console.log('Split code:', data.split.split_code);

    // Check each share
    if (data.subaccount) {
      console.log('Subaccount:', data.subaccount.business_name);
      console.log('Subaccount share:', data.subaccount.share);
    }
  } else {
    console.warn('\nSplit applied: NO');
    console.warn('The full amount went to the main account.');
    console.warn('Check that split_code was included in the initialization request.');
  }
}

verifySplitApplied('your_transaction_reference').catch(console.error);

You can also check in the Paystack dashboard. Go to Transactions, find the transaction, and click on it. The transaction details page shows the split breakdown including each party's share and the fee allocation.

Split Debugging Checklist

Run through this list before contacting support.

  1. Is split_code in the initialize request? Log the request body just before sending it. Confirm split_code is present and not undefined or null.
  2. Is the split_code valid? Call GET /split/{split_code} and confirm it returns a valid response. A 404 means the code is wrong.
  3. Are all subaccounts active? For each subaccount in the split, call GET /subaccount/{code} and verify is_verified is true.
  4. Does the split currency match the transaction currency? A split configured for NGN will not apply to a GHS transaction.
  5. For flat splits: is the total share less than the transaction amount? The split cannot take more than the customer paid.
  6. For percentage splits: do the shares add up to 100% or less? Shares exceeding 100% make the split invalid.
  7. Was the split created before the transaction? Splits are not retroactive. The split must exist before the transaction is initialized.
  8. Is there a default split overriding your per-transaction split? Check Settings > Preferences in the dashboard.

How to Verify Your Fix

After fixing the split configuration, run this verification flow.

  1. Fetch the split via GET /split/{split_code} and confirm it is active with the correct subaccounts and shares.
  2. Initialize a test transaction with the split_code included.
  3. Complete the payment using test card 4084 0840 8408 4081.
  4. Call GET /transaction/verify/{reference} and confirm the split field is present in the response.
  5. Check the Paystack dashboard transaction details page. The split breakdown should show each party's share.
  6. If you are using webhooks, verify the charge.success event payload includes split information.

Once confirmed in sandbox, deploy the same configuration to live mode. Remember that live mode subaccounts and splits are separate from test mode ones. You need to recreate them (or create them via API) in live mode with real bank details.

Key Takeaways

  • ✓The most common cause is forgetting to pass split_code when initializing the transaction. Splits do not apply automatically unless you set a default split in the dashboard.
  • ✓Subaccounts in a split must be active with verified bank details. If any subaccount in a multi-split is inactive, the entire split may fail silently.
  • ✓You can set a default split in the Paystack dashboard under Settings > Preferences. This applies the split to all transactions without needing to pass split_code each time.
  • ✓Always verify the transaction after payment to confirm the split was applied. The verify response includes split details and individual settlement amounts.
  • ✓Flat splits use fixed amounts (e.g., 500 NGN to subaccount A). Percentage splits use ratios. Make sure your split type matches your business logic.
  • ✓Splits created after a transaction was initialized will not apply retroactively. The split must exist before the transaction is created.
  • ✓Test splits in sandbox mode first. Create test subaccounts, run a test transaction with the split_code, and verify the settlement breakdown.

Frequently Asked Questions

Can I apply a split to a transaction after it has already been paid?
No. Splits must be configured before the transaction is initialized. Once a payment is completed without a split, the full amount settles to your main account. You would need to manually transfer the split share using the Transfer API.
What happens if a subaccount in my split becomes inactive after I create the split?
The split may fail silently for new transactions. Paystack will not apply a split if any subaccount in it has invalid or unverified bank details. Periodically check your subaccount statuses and update bank details if they change.
Can I have different splits for different products on the same Paystack integration?
Yes. Create multiple split configurations, each with its own split_code. When initializing a transaction, pass the appropriate split_code for that product or vendor. Do not use a default split if you need this flexibility.
How does Paystack handle transaction fees with splits?
The bearer_type field in the split configuration determines who pays the fee. "all" splits the fee proportionally, "account" makes your main account pay the entire fee, and "subaccount" assigns the fee to a specific subaccount. Choose based on your business model.
Do splits work with all payment channels (card, bank transfer, USSD)?
Yes. Splits apply regardless of the payment channel. Whether the customer pays by card, bank transfer, USSD, or mobile money, the split is applied at the settlement level after the payment succeeds.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Paystack Errors and Troubleshooting: The Complete Reference

Every Paystack error you will hit in production, what causes it, and how to fix it. Authentication failures, webhook signature problems, transaction errors, transfer issues, and frontend bugs. Code-first solutions for each one.

Read more

Paystack Currency Not Supported Error

Paystack returns "Currency not supported" when you try to charge in a currency that is not enabled for your account. This guide explains which currencies each country supports, how to check and enable currencies, and common format mistakes that trigger this error.

Read more

Paystack Transfer Failed: Reasons and Recovery

Paystack transfers fail for specific, diagnosable reasons. This guide covers every failure reason, the exact webhook payload for each, and a production-ready recovery strategy with code.

Read more

Paystack Rate Limit and 429 Handling

Paystack returns 429 Too Many Requests when you exceed their API rate limit. This guide covers the actual limits, how to implement exponential backoff, when to cache responses, and how to batch operations to avoid hitting the limit.

Read more

Queueing Paystack Webhook Work with Laravel Queues

Handle Paystack webhooks in Laravel by verifying the signature in a controller, dispatching a queued job, and returning 200 immediately. The queue worker processes payment events in the background with automatic retries.

Read more

Chaos Testing Payment Failure Paths

Chaos testing asks: what happens to my payment system when something unexpected fails? Paystack goes down, the database rejects a write, the webhook arrives twice, or the verification call times out. This guide shows how to simulate these failure scenarios and what correct behavior looks like.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.