Paystack Subaccount Settlement Missing
Paystack subaccount settlements go missing for five reasons: the subaccount bank details are wrong or outdated, the settlement schedule has not triggered yet (Paystack settles on a schedule, not instantly), the split was not applied to the transaction, the subaccount was deactivated, or there is an outstanding compliance hold on the account. Check the subaccount status via the API, verify bank details match the account holder, confirm the split was applied to the transaction, and check the settlement schedule in your dashboard.
How Paystack Subaccount Settlements Work
When a customer pays and a split is applied, Paystack calculates each party's share at the transaction level. But the money does not move to bank accounts immediately. Paystack batches settlements and sends them on a schedule.
Here is the timeline:
- Transaction succeeds. The customer's payment is confirmed. The split allocates shares to the main account and each subaccount.
- Settlement window. Paystack accumulates successful transactions throughout the day. At the end of the settlement period (usually T+1 for most accounts), Paystack calculates the total amount owed to each party.
- Bank transfer. Paystack initiates transfers to each subaccount's registered bank account. This transfer goes through the standard banking system.
- Funds arrive. The subaccount holder sees the money in their bank account, typically within a few hours of the settlement batch.
When a settlement is "missing," one of these steps failed. Either the share was never calculated (split not applied), the settlement was delayed (schedule not triggered yet), or the bank transfer failed (wrong details, bank issues).
Cause 1: Wrong or Outdated Bank Details
This is the most common cause. The subaccount was created with bank details that are now wrong. Maybe the vendor changed banks, or there was a typo in the original account number, or the bank merged and the bank code changed.
When Paystack tries to settle to an invalid bank account, the transfer fails. The money stays in Paystack's system (it does not disappear), but the subaccount holder does not receive it.
const axios = require('axios');
const headers = {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
};
// Check current subaccount bank details
async function checkSubaccountBankDetails(subaccountCode) {
const response = await axios.get(
`https://api.paystack.co/subaccount/${subaccountCode}`,
{ headers }
);
const sub = response.data.data;
console.log('Business name:', sub.business_name);
console.log('Bank:', sub.settlement_bank);
console.log('Account number:', sub.account_number);
console.log('Verified:', sub.is_verified);
return sub;
}
// Update bank details if they changed
async function updateSubaccountBankDetails(subaccountCode, newBankCode, newAccountNumber) {
// First, resolve the account to verify it is valid
const resolveResponse = await axios.get(
`https://api.paystack.co/bank/resolve?account_number=${newAccountNumber}&bank_code=${newBankCode}`,
{ headers }
);
console.log('Resolved account name:', resolveResponse.data.data.account_name);
// Update the subaccount
const updateResponse = await axios.put(
`https://api.paystack.co/subaccount/${subaccountCode}`,
{
settlement_bank: newBankCode,
account_number: newAccountNumber,
},
{ headers }
);
console.log('Updated:', updateResponse.data.data.business_name);
console.log('New bank:', updateResponse.data.data.settlement_bank);
console.log('New account:', updateResponse.data.data.account_number);
}
// Example: check and update
checkSubaccountBankDetails('ACCT_xxxxxxxx').catch(console.error);
Always resolve the account number against the bank before updating. The Paystack Bank Resolve API (GET /bank/resolve) confirms that the account number exists at that bank and returns the account holder's name. This prevents typos from causing future settlement failures.
Cause 2: Settlement Schedule Has Not Triggered Yet
Paystack does not settle in real time. The standard settlement schedule is T+1, meaning transactions from Monday settle on Tuesday, Tuesday settles on Wednesday, and so on. But there are important exceptions:
- Friday transactions settle on Monday (next business day).
- Saturday and Sunday transactions also settle on Monday.
- Public holidays push settlements to the next business day.
- Some accounts are on weekly or monthly settlement schedules.
If your vendor says "I was paid on Friday but the money has not arrived," the answer might simply be that settlement happens on Monday.
Check your settlement schedule in the Paystack dashboard under Settings > Settlement. You can also check programmatically:
// Check recent settlements
async function checkSettlements() {
const response = await axios.get(
'https://api.paystack.co/settlement',
{
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
},
params: {
perPage: 10,
},
}
);
const settlements = response.data.data;
for (const settlement of settlements) {
console.log('Settlement ID:', settlement.id);
console.log('Amount:', settlement.total_amount / 100, 'NGN');
console.log('Status:', settlement.status);
console.log('Date:', settlement.settled_date || 'Pending');
console.log('---');
}
}
checkSettlements().catch(console.error);
If the settlement shows as "pending," it has not been sent to the bank yet. This is normal within the settlement window. If it shows as "failed," there is a problem with the bank details or Paystack has flagged the account.
Cause 3: The Split Was Not Applied to the Transaction
The transaction succeeded, but the split was never applied. The entire amount went to your main account, and the subaccount got nothing. This feels like a "missing settlement" from the vendor's perspective, but it is actually a split configuration issue.
Verify whether the split was applied by checking the transaction:
async function checkTransactionSplit(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:', reference);
console.log('Status:', data.status);
console.log('Amount:', data.amount / 100, 'NGN');
if (data.split) {
console.log('Split applied: YES');
console.log('Split code:', data.split.split_code);
} else if (data.subaccount) {
console.log('Subaccount transaction: YES');
console.log('Subaccount:', data.subaccount.subaccount_code);
} else {
console.log('Split applied: NO');
console.log('Full amount went to main account.');
console.log('Fix: include split_code when initializing transactions.');
}
}
checkTransactionSplit('REF_xxxxx').catch(console.error);
If the split was not applied, the fix is in your transaction initialization code, not in the subaccount or settlement configuration. See our guide on Paystack Split Not Applied to Transaction for the full troubleshooting process.
Cause 4: Subaccount Deactivated
Subaccounts can be deactivated for several reasons: you manually deactivated it, Paystack flagged it for compliance, or the bank verification failed. A deactivated subaccount will not receive settlements, even if transactions with its split_code continue to succeed (the money accumulates but does not settle).
// Check if subaccount is active
async function isSubaccountActive(subaccountCode) {
const response = await axios.get(
`https://api.paystack.co/subaccount/${subaccountCode}`,
{
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
},
}
);
const sub = response.data.data;
if (!sub.active) {
console.warn(`Subaccount ${subaccountCode} is INACTIVE.`);
console.warn('Reason: Check Paystack dashboard for details.');
console.warn('Settlements are paused until reactivated.');
return false;
}
console.log(`Subaccount ${subaccountCode} is active.`);
return true;
}
If the subaccount was deactivated by Paystack for compliance reasons, you will need to resolve the issue through the Paystack dashboard or by contacting their support. Common compliance triggers include:
- Volume exceeding the tier limit for the business type
- Missing or incomplete KYC documentation
- High chargeback or dispute rates on transactions involving that subaccount
- Suspicion of fraudulent activity
Cause 5: Compliance or Regulatory Holds
Paystack is regulated by the CBN (Central Bank of Nigeria) and other financial regulators in the countries it operates. Occasionally, settlements are held for compliance review. This is not common, but when it happens, it can freeze settlements for days or weeks.
Signs of a compliance hold:
- Transactions are succeeding normally, but no settlements are going out
- The Paystack dashboard shows a banner or notification about account verification
- You received an email from Paystack requesting additional documentation
There is no API to check for compliance holds. You need to log into the Paystack dashboard and look for notifications, or contact Paystack support directly.
To prevent compliance issues:
- Complete all KYC requirements during onboarding, not later
- Keep your business documentation up to date (CAC registration, valid ID, proof of address)
- Monitor your chargeback rate. High dispute rates trigger compliance reviews
- If you are a marketplace, ensure your vendors also meet Paystack's compliance requirements
Building a Settlement Tracking Tool for Your Vendors
If you run a marketplace or platform with multiple subaccounts, you will get settlement questions from vendors constantly. Build an internal tool that answers the most common questions without requiring you to log into the Paystack dashboard.
const axios = require('axios');
const headers = {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
};
async function getVendorSettlementSummary(subaccountCode) {
// 1. Get subaccount details
const subResponse = await axios.get(
`https://api.paystack.co/subaccount/${subaccountCode}`,
{ headers }
);
const sub = subResponse.data.data;
// 2. Get recent transactions for this subaccount
const txnResponse = await axios.get(
'https://api.paystack.co/transaction',
{
headers,
params: {
subaccount: subaccountCode,
status: 'success',
perPage: 50,
from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), // Last 7 days
},
}
);
const transactions = txnResponse.data.data;
const totalAmount = transactions.reduce((sum, t) => sum + t.amount, 0);
console.log('=== Vendor Settlement Summary ===');
console.log('Business:', sub.business_name);
console.log('Active:', sub.active ? 'Yes' : 'NO - settlements paused');
console.log('Bank:', sub.settlement_bank, sub.account_number);
console.log('Verified:', sub.is_verified ? 'Yes' : 'NO - bank details need verification');
console.log('');
console.log('Last 7 days:');
console.log(' Transactions:', transactions.length);
console.log(' Total amount:', totalAmount / 100, 'NGN');
console.log('');
// 3. List individual transactions
for (const txn of transactions.slice(0, 10)) {
console.log(` ${txn.created_at} - ${txn.amount / 100} NGN - ${txn.reference}`);
}
if (!sub.active) {
console.warn('\nACTION REQUIRED: Subaccount is inactive. Check Paystack dashboard.');
}
if (!sub.is_verified) {
console.warn('\nACTION REQUIRED: Bank details not verified. Update and verify.');
}
}
getVendorSettlementSummary('ACCT_xxxxxxxx').catch(console.error);
Expose this as an internal admin endpoint so your support team can look up any vendor's settlement status in seconds. Add the ability to cross-reference with your own database to spot discrepancies between Paystack records and what you have credited internally.
What to Tell Vendors When They Ask About Missing Settlements
Vendors who are not receiving money get frustrated quickly. Clear, honest communication makes a big difference.
If the settlement is within the normal window (T+1):
"Settlements are processed on the next business day. If your transaction was yesterday, the settlement will arrive today. Weekend transactions settle on Monday."
If bank details are wrong:
"Your bank details on file do not match a valid account. Please confirm your account number and bank name, and we will update your profile. Once updated, pending settlements will be released."
If the subaccount is inactive:
"Your vendor account is currently on hold. We need [specific documentation or action] to reactivate it. Please [contact support / upload documents / etc]."
If the split was not applied:
"We identified that some recent transactions were processed without the revenue split. We are correcting this and will transfer your share manually. This will arrive within [your SLA]."
For the manual transfer case, use the Paystack Transfer API to send the vendor their share from your main account balance.
How to Verify the Settlement Issue Is Resolved
After fixing the root cause, confirm everything works end to end.
- Check subaccount status. Call
GET /subaccount/{code}. Confirmactive: trueandis_verified: true. - Verify bank details. Call
GET /bank/resolvewith the subaccount's bank code and account number. Confirm the account name matches the expected vendor. - Run a test transaction. In sandbox, initialize a transaction with the split_code, complete it, and verify the split was applied.
- Check the settlement. After the settlement window, verify the settlement was sent. In sandbox, check the dashboard. In live, wait for the T+1 window and confirm with the vendor.
- Set up monitoring. Create an alert that fires when settlement failures occur or when a subaccount becomes inactive.
For any settlements that were missed during the period the subaccount was broken, you may need to manually transfer the funds using the Transfer API. Calculate the total owed by summing the subaccount shares from all affected transactions, and initiate a bulk transfer.
Key Takeaways
- ✓Paystack does not settle instantly. Standard settlement is T+1 (next business day). Weekends and holidays delay settlements further.
- ✓Wrong bank details are the top cause. If the account number or bank code changed after subaccount creation, settlements will fail or go to the wrong account.
- ✓A "successful transaction" does not mean the split was applied. Verify the transaction details to confirm the subaccount share was calculated.
- ✓Deactivated subaccounts do not receive settlements. Check the subaccount status via the API and reactivate if needed.
- ✓Paystack may hold settlements for compliance reasons (KYC issues, suspicious activity, or exceeding volume thresholds). Check the dashboard for any notifications.
- ✓Build an internal tool that checks subaccount settlement status so you can answer vendor inquiries quickly without logging into the Paystack dashboard every time.
Frequently Asked Questions
- How long does Paystack take to settle subaccounts?
- Standard settlement is T+1, meaning transactions from one business day settle the next business day. Friday, Saturday, and Sunday transactions settle on Monday. Some accounts may be on weekly or monthly schedules depending on their agreement with Paystack.
- Can I change a subaccount bank details after creation?
- Yes. Use the PUT /subaccount/{code} endpoint to update the settlement_bank and account_number. Always resolve the new account number first using GET /bank/resolve to verify it is valid. After updating, future settlements will go to the new account.
- What happens to money if the subaccount bank transfer fails?
- The money does not disappear. Failed settlement transfers stay in Paystack system. Paystack will retry the settlement, or you can contact support to have the funds released once the bank details are corrected.
- Can I manually settle a subaccount outside the normal schedule?
- Paystack does not currently offer on-demand settlement for subaccounts via the API. If you need to pay a vendor immediately, you can use the Transfer API to send funds from your main account balance to their bank account directly. This is separate from the automatic settlement process.
- How do I prevent settlement issues for new subaccounts?
- Always resolve the bank account before creating the subaccount. Use the GET /bank/resolve endpoint to verify the account number and bank code. Confirm the returned account name matches your vendor. After creating the subaccount, run a small test transaction with a split to verify the full flow before processing real payments.
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