Transfer Funds Between Accounts
NextAPI lets you move funds between any two accounts within your partner hierarchy instantly — without going through external rails. Use this for:
- Sweeping collected funds from a merchant account to a central settlement account
- Funding a merchant's disbursement account before a payout run
- Moving platform commission from a merchant account to your platform account
- Rebalancing liquidity across merchant accounts
Internal transfers settle immediately and create ledger postings on both accounts.
Prerequisites
- Source and destination account IDs (
acct_xxx) - Sufficient available balance in the source account
- Both accounts must be within your partner hierarchy
- Sandbox credentials from /sandbox
Create a transfer
- cURL
- Node.js
- Python
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-X POST "https://api.partners.nextpay.world/v2/accounts/acct_01HXYZ/transfer" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: sweep-merchant-a-20251115-v1" \
-d '{
"destination_account_id": "acct_01HABC",
"amount": 5000000,
"description": "Daily settlement sweep",
"reference": "sweep-merchant-a-20251115"
}'
async function transferFunds(sourceAccountId, destAccountId, amountCentavos, reference) {
const response = await fetch(
`https://api.partners.nextpay.world/v2/accounts/${sourceAccountId}/transfer`,
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64'),
'Content-Type': 'application/json',
'X-Idempotency-Key': `${reference}-v1`,
},
body: JSON.stringify({
destination_account_id: destAccountId,
amount: amountCentavos,
description: 'Daily settlement sweep',
reference: reference,
}),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(`Transfer failed: ${error.message}`);
}
return response.json();
}
import requests
import base64
def transfer_funds(source_account_id, dest_account_id, amount_centavos, reference):
credentials = base64.b64encode(b'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').decode()
response = requests.post(
f'https://api.partners.nextpay.world/v2/accounts/{source_account_id}/transfer',
headers={
'Authorization': f'Basic {credentials}',
'Content-Type': 'application/json',
'X-Idempotency-Key': f'{reference}-v1',
},
json={
'destination_account_id': dest_account_id,
'amount': amount_centavos,
'description': 'Daily settlement sweep',
'reference': reference,
}
)
response.raise_for_status()
return response.json()
Response
{
"id": "txn_01HABC",
"type": "transfer",
"status": "completed",
"source_account_id": "acct_01HXYZ",
"destination_account_id": "acct_01HABC",
"amount": 5000000,
"description": "Daily settlement sweep",
"reference": "sweep-merchant-a-20251115",
"postings": [
{
"id": "post_001",
"account_id": "acct_01HXYZ",
"direction": "debit",
"amount": 5000000
},
{
"id": "post_002",
"account_id": "acct_01HABC",
"direction": "credit",
"amount": 5000000
}
],
"created_at": "2025-11-15T18:00:00Z"
}
Internal transfers complete immediately (status: "completed"). Both postings appear in the respective account ledgers.
Verify the transfer
Check the source account balance after the transfer:
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/accounts/acct_01HXYZ/balances"
Check the destination account postings to confirm receipt:
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/accounts/acct_01HABC/postings?limit=5"
Common patterns
Daily settlement sweep
Collect merchant revenue throughout the day, then sweep at end of day to a central settlement account:
async function dailySettlementSweep(merchantAccounts, settlementAccountId) {
const today = new Date().toISOString().split('T')[0];
for (const merchantAccountId of merchantAccounts) {
const balanceRes = await fetch(
`https://api.partners.nextpay.world/v2/accounts/${merchantAccountId}/balances`,
{ headers: { 'Authorization': 'Basic ...' } }
);
const { available } = await balanceRes.json();
if (available > 0) {
await transferFunds(
merchantAccountId,
settlementAccountId,
available,
`sweep-${merchantAccountId}-${today}`
);
}
}
}
Commission split after collection
When a merchant collects a payment, split the proceeds between the merchant's net amount and your platform fee:
// After receiving payment_intent.paid webhook
async function splitPayment(merchantAccountId, platformAccountId, totalAmount, commissionRate) {
const commission = Math.floor(totalAmount * commissionRate);
if (commission > 0) {
await transferFunds(
merchantAccountId,
platformAccountId,
commission,
`commission-${Date.now()}`
);
}
}
Pre-fund a payroll account
Before running batch payouts, ensure the disbursement account has sufficient funds:
async function prefundPayrollAccount(fundingAccountId, payrollAccountId, totalPayroll) {
await transferFunds(
fundingAccountId,
payrollAccountId,
totalPayroll,
`payroll-prefund-${Date.now()}`
);
}
Balance constraints
- Available balance only. You cannot transfer funds that are
pendingorreserved. - Same currency. All NextAPI accounts are PHP — cross-currency transfers are not supported.
- Hierarchy constraint. Both accounts must be within your partner hierarchy. You cannot transfer to accounts belonging to another partner.
- Minimum amount. Transfers must be at least 1 centavo (PHP 0.01).
Key points
- Idempotency key prevents duplicate transfers if your request fails and you retry.
- Immediate settlement. Internal transfers don't go through bank rails — they're instant ledger operations.
- No fees. Internal account-to-account transfers within your hierarchy have no transaction fee.
- Audit trail. Every transfer creates postings on both accounts, visible in
GET /v2/accounts/{id}/postings.
Related
- Wallet Structure — understanding the account hierarchy
- Reconcile Transactions — using postings for reconciliation
- Run Mass Payroll — pre-funding and batch disbursement