Skip to main content

Transfers

The iNPAY Developer API supports two types of transfers: PayID-to-PayID transfers for instant payments between PayIDs, and External Bank Transfers for sending money to any Nigerian bank account.

🚀 Transfer Types

1. PayID-to-PayID Transfers

  • Instant transfers between PayIDs
  • No bank details required - just PayID addresses
  • Real-time completion - transfers happen immediately
  • Perfect for: Peer-to-peer payments, merchant payments, internal transfers

2. External Bank Transfers

  • Send to any Nigerian bank account
  • Account verification before transfer
  • Standard bank processing times
  • Perfect for: Supplier payments, salary payments, external disbursements

🔑 Understanding Transfer Variables

Source PayID (fromPayId)

  • Must be a wallet PayID created by your iNPAY account
  • Cannot be verified using the verify PayID endpoint
  • Store in environment variables for easy access
  • Funds are debited from this wallet during transfers
// Store your wallet PayID in environment variables
const WALLET_PAYID = process.env.INPAY_WALLET_PAYID; // e.g., "mybusiness123.wallet"

Destination PayID (toPayId)

  • Any valid PayID as destination for PayID-to-PayID transfers
  • Always verify before sending money
  • Can be dynamic or static PayIDs
// Always verify destination PayID first
const verification = await transferManager.verifyPayId('customer456.dpid');
if (!verification.success) {
throw new Error('Invalid destination PayID');
}

Bank Account Details (External Transfers)

  • accountNumber: Destination bank account number
  • bankCode: Bank code (use get bank list API)
  • accountName: Account holder name (for verification)
// Get bank list to find bank codes
const bankList = await transferManager.getBankList();
const gtbank = bankList.data.banks.find(bank => bank.bankName === 'GTBank');
console.log('GTBank code:', gtbank.bankCode); // "058"

Amount Format

  • All amounts in kobo (1 Naira = 100 kobo)
  • ₦100.00 = 10000 kobo
  • ₦500.00 = 50000 kobo
  • ₦1000.00 = 100000 kobo
// Convert naira to kobo
const amountInKobo = nairaAmount * 100;
// Example: ₦250.00 = 25000 kobo

💸 PayID-to-PayID Transfers

How It Works

  1. Verify source PayID - Ensure you have sufficient funds
  2. Verify destination PayID - Confirm the recipient PayID is active
  3. Initiate transfer - Send money instantly between PayIDs
  4. Get confirmation - Receive transaction details and status

Transfer Between PayIDs

REST API

curl -X POST https://api.inpaycheckout.com/api/v1/developer/transfer/payid \
-H "Authorization: Bearer sk_live_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"fromPayId": "mywallet123.wallet",
"toPayId": "customer456.dpid",
"amount": 5000,
"narration": "Payment for order #12345",
"reference": "TXN-789"
}'

GraphQL

mutation TransferPayId($input: PayIdTransferInput!) {
transferPayId(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toPayId
amount
narration
status
completedAt
destinationAccountName
}
}
}

Variables:

{
"input": {
"fromPayId": "mywallet123.wallet",
"toPayId": "customer456.dpid",
"amount": 5000,
"narration": "Payment for order #12345",
"reference": "TXN-789"
}
}

Response Example

{
"success": true,
"message": "Transfer completed successfully",
"data": {
"transactionId": "iNPAY-1234567890",
"reference": "TXN-789",
"fromPayId": "mywallet123.wallet",
"toPayId": "customer456.dpid",
"amount": 5000,
"narration": "Payment for order #12345",
"status": "completed",
"completedAt": "2025-09-14T10:30:00.000Z",
"destinationAccountName": "Customer Name"
}
}

🏦 External Bank Transfers

How It Works

  1. Verify external account - Confirm bank account details
  2. Check bank support - Ensure bank is supported for transfers
  3. Initiate transfer - Send money to external bank account
  4. Track transaction - Monitor transfer status

Verify External Account First

REST API

curl -X POST https://api.inpaycheckout.com/api/v1/developer/transfer/external/verify \
-H "Authorization: Bearer sk_live_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"accountNumber": "1234567890",
"bankCode": "058"
}'

GraphQL

mutation VerifyExternalAccount($input: VerifyExternalAccountInput!) {
verifyExternalAccount(input: $input) {
success
message
data {
accountNumber
accountName
bankCode
bankName
bankLogo
verified
}
}
}

Variables:

{
"input": {
"accountNumber": "1234567890",
"bankCode": "058"
}
}

Response Example

{
"success": true,
"message": "Account verification successful",
"data": {
"accountNumber": "1234567890",
"accountName": "John Doe",
"bankCode": "058",
"bankName": "GTBank",
"bankLogo": "https://...",
"verified": true
}
}

Transfer to External Bank Account

REST API

curl -X POST https://api.inpaycheckout.com/api/v1/developer/transfer/external \
-H "Authorization: Bearer sk_live_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"fromPayId": "mywallet123.wallet",
"accountNumber": "1234567890",
"bankCode": "058",
"amount": 10000,
"narration": "Payment to supplier",
"reference": "PAY-456",
"accountName": "John Doe"
}'

GraphQL

mutation TransferExternal($input: ExternalTransferInput!) {
transferExternal(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toAccountNumber
toAccountName
bankCode
bankName
amount
narration
status
completedAt
}
}
}

Variables:

{
"input": {
"fromPayId": "mywallet123.wallet",
"accountNumber": "1234567890",
"bankCode": "058",
"amount": 10000,
"narration": "Payment to supplier",
"reference": "PAY-456",
"accountName": "John Doe"
}
}

Response Example

{
"success": true,
"message": "External transfer completed successfully",
"data": {
"transactionId": "iNPAY-0987654321",
"reference": "PAY-456",
"fromPayId": "mywallet123.wallet",
"toAccountNumber": "1234567890",
"toAccountName": "John Doe",
"bankCode": "058",
"bankName": "GTBank",
"amount": 10000,
"narration": "Payment to supplier",
"status": "completed",
"completedAt": "2025-09-14T10:30:00.000Z"
}
}

🏪 Get Bank List

Before making external transfers, you'll need the bank codes. Get the complete list of supported banks:

REST API

curl -X GET https://api.inpaycheckout.com/api/v1/developer/banks \
-H "Authorization: Bearer sk_live_your_secret_key"

GraphQL

query GetBankList {
getBankList {
success
message
data {
banks {
bankCode
bankName
logoUrl
}
total
}
}
}

Response Example

{
"success": true,
"message": "Bank list retrieved successfully",
"data": {
"banks": [
{
"bankCode": "058",
"bankName": "GTBank",
"logoUrl": "https://..."
},
{
"bankCode": "011",
"bankName": "First Bank",
"logoUrl": "https://..."
},
{
"bankCode": "214",
"bankName": "First City Monument Bank",
"logoUrl": "https://..."
}
],
"total": 25
}
}

💻 Code Examples

JavaScript/Node.js

const axios = require('axios');

class TransferManager {
constructor(secretKey, baseUrl = 'https://api.inpaycheckout.com') {
this.secretKey = secretKey;
this.baseUrl = baseUrl;
this.headers = {
'Authorization': `Bearer ${secretKey}`,
'Content-Type': 'application/json'
};
}

// PayID-to-PayID Transfer
async transferPayId(fromPayId, toPayId, amount, narration, reference) {
try {
const response = await axios.post(
`${this.baseUrl}/api/v1/developer/transfer/payid`,
{
fromPayId,
toPayId,
amount,
narration,
reference
},
{ headers: this.headers }
);

return response.data;
} catch (error) {
console.error('Error transferring PayID:', error.response?.data || error.message);
throw error;
}
}

// Verify PayID
async verifyPayId(payId) {
try {
const response = await axios.post(
`${this.baseUrl}/api/v1/developer/payid/verify`,
{ payId },
{ headers: this.headers }
);

return response.data;
} catch (error) {
console.error('Error verifying PayID:', error.response?.data || error.message);
throw error;
}
}

// Verify External Account
async verifyExternalAccount(accountNumber, bankCode) {
try {
const response = await axios.post(
`${this.baseUrl}/api/v1/developer/transfer/external/verify`,
{
accountNumber,
bankCode
},
{ headers: this.headers }
);

return response.data;
} catch (error) {
console.error('Error verifying external account:', error.response?.data || error.message);
throw error;
}
}

// External Bank Transfer
async transferExternal(fromPayId, accountNumber, bankCode, amount, narration, reference, accountName) {
try {
const response = await axios.post(
`${this.baseUrl}/api/v1/developer/transfer/external`,
{
fromPayId,
accountNumber,
bankCode,
amount,
narration,
reference,
accountName
},
{ headers: this.headers }
);

return response.data;
} catch (error) {
console.error('Error transferring external:', error.response?.data || error.message);
throw error;
}
}

// Get Bank List
async getBankList() {
try {
const response = await axios.get(
`${this.baseUrl}/api/v1/developer/banks`,
{ headers: this.headers }
);

return response.data;
} catch (error) {
console.error('Error getting bank list:', error.response?.data || error.message);
throw error;
}
}

// Complete PayID Transfer Flow
async completePayIdTransfer(fromPayId, toPayId, amount, narration, reference) {
try {
// Step 1: Verify source PayID
const sourceVerification = await this.verifyPayId(fromPayId);
if (!sourceVerification.success) {
throw new Error('Source PayID verification failed');
}

// Step 2: Verify destination PayID
const destinationVerification = await this.verifyPayId(toPayId);
if (!destinationVerification.success) {
throw new Error('Destination PayID verification failed');
}

// Step 3: Execute transfer
const transfer = await this.transferPayId(fromPayId, toPayId, amount, narration, reference);

return transfer;
} catch (error) {
console.error('PayID transfer failed:', error.message);
throw error;
}
}

// Complete External Transfer Flow
async completeExternalTransfer(fromPayId, accountNumber, bankCode, amount, narration, reference, accountName) {
try {
// Step 1: Verify external account
const accountVerification = await this.verifyExternalAccount(accountNumber, bankCode);
if (!accountVerification.success || !accountVerification.data.verified) {
throw new Error('External account verification failed');
}

// Step 2: Execute transfer
const transfer = await this.transferExternal(
fromPayId,
accountNumber,
bankCode,
amount,
narration,
reference,
accountName
);

return transfer;
} catch (error) {
console.error('External transfer failed:', error.message);
throw error;
}
}
}

// Usage Examples
const transferManager = new TransferManager(process.env.INPAY_SECRET_KEY);

// PayID-to-PayID Transfer
const payIdTransfer = await transferManager.completePayIdTransfer(
'mywallet123.wallet', // Source PayID
'customer456.dpid', // Destination PayID
5000, // ₦50.00
'Payment for order #12345',
'TXN-789'
);

console.log('PayID Transfer Completed:', payIdTransfer.data.transactionId);

// External Bank Transfer
const externalTransfer = await transferManager.completeExternalTransfer(
'mywallet123.wallet', // Source PayID
'1234567890', // Destination account number
'058', // GTBank code
10000, // ₦100.00
'Payment to supplier',
'PAY-456',
'John Doe' // Account name
);

console.log('External Transfer Completed:', externalTransfer.data.transactionId);

// Get supported banks
const bankList = await transferManager.getBankList();
console.log('Supported Banks:', bankList.data.banks);

Python

import requests
import os

class TransferManager:
def __init__(self, secret_key, base_url='https://api.inpaycheckout.com'):
self.secret_key = secret_key
self.base_url = base_url
self.headers = {
'Authorization': f'Bearer {secret_key}',
'Content-Type': 'application/json'
}

def transfer_payid(self, from_payid, to_payid, amount, narration, reference):
"""Transfer between PayIDs"""
url = f"{self.base_url}/api/v1/developer/transfer/payid"
data = {
'fromPayId': from_payid,
'toPayId': to_payid,
'amount': amount,
'narration': narration,
'reference': reference
}

response = requests.post(url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()

def verify_payid(self, pay_id):
"""Verify PayID"""
url = f"{self.base_url}/api/v1/developer/payid/verify"
data = {'payId': pay_id}

response = requests.post(url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()

def verify_external_account(self, account_number, bank_code):
"""Verify external bank account"""
url = f"{self.base_url}/api/v1/developer/transfer/external/verify"
data = {
'accountNumber': account_number,
'bankCode': bank_code
}

response = requests.post(url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()

def transfer_external(self, from_payid, account_number, bank_code, amount, narration, reference, account_name):
"""Transfer to external bank account"""
url = f"{self.base_url}/api/v1/developer/transfer/external"
data = {
'fromPayId': from_payid,
'accountNumber': account_number,
'bankCode': bank_code,
'amount': amount,
'narration': narration,
'reference': reference,
'accountName': account_name
}

response = requests.post(url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()

def get_bank_list(self):
"""Get bank list"""
url = f"{self.base_url}/api/v1/developer/banks"

response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()

def complete_payid_transfer(self, from_payid, to_payid, amount, narration, reference):
"""Complete PayID transfer with verification"""
try:
# Step 1: Verify source PayID
source_verification = self.verify_payid(from_payid)
if not source_verification['success']:
raise Exception('Source PayID verification failed')

# Step 2: Verify destination PayID
destination_verification = self.verify_payid(to_payid)
if not destination_verification['success']:
raise Exception('Destination PayID verification failed')

# Step 3: Execute transfer
transfer = self.transfer_payid(from_payid, to_payid, amount, narration, reference)

return transfer
except Exception as e:
print(f'PayID transfer failed: {str(e)}')
raise

def complete_external_transfer(self, from_payid, account_number, bank_code, amount, narration, reference, account_name):
"""Complete external transfer with verification"""
try:
# Step 1: Verify external account
account_verification = self.verify_external_account(account_number, bank_code)
if not account_verification['success'] or not account_verification['data']['verified']:
raise Exception('External account verification failed')

# Step 2: Execute transfer
transfer = self.transfer_external(
from_payid, account_number, bank_code, amount, narration, reference, account_name
)

return transfer
except Exception as e:
print(f'External transfer failed: {str(e)}')
raise

# Usage Examples
transfer_manager = TransferManager(os.getenv('INPAY_SECRET_KEY'))

# PayID-to-PayID Transfer
payid_transfer = transfer_manager.complete_payid_transfer(
'mywallet123.wallet', # Source PayID
'customer456.dpid', # Destination PayID
5000, # ₦50.00
'Payment for order #12345',
'TXN-789'
)

print(f'PayID Transfer Completed: {payid_transfer["data"]["transactionId"]}')

# External Bank Transfer
external_transfer = transfer_manager.complete_external_transfer(
'mywallet123.wallet', # Source PayID
'1234567890', # Destination account number
'058', # GTBank code
10000, # ₦100.00
'Payment to supplier',
'PAY-456',
'John Doe' # Account name
)

print(f'External Transfer Completed: {external_transfer["data"]["transactionId"]}')

# Get supported banks
bank_list = transfer_manager.get_bank_list()
print(f'Supported Banks: {len(bank_list["data"]["banks"])} banks available')

PHP

<?php
class TransferManager {
private $secretKey;
private $baseUrl;

public function __construct($secretKey, $baseUrl = 'https://api.inpaycheckout.com') {
$this->secretKey = $secretKey;
$this->baseUrl = $baseUrl;
}

private function makeRequest($method, $endpoint, $data = null) {
$url = $this->baseUrl . $endpoint;
$headers = [
'Authorization: Bearer ' . $this->secretKey,
'Content-Type: application/json'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

if ($data && in_array($method, ['POST', 'PUT', 'PATCH'])) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode >= 400) {
throw new Exception('API Error: ' . $response);
}

return json_decode($response, true);
}

public function transferPayId($fromPayId, $toPayId, $amount, $narration, $reference) {
return $this->makeRequest('POST', '/api/v1/developer/transfer/payid', [
'fromPayId' => $fromPayId,
'toPayId' => $toPayId,
'amount' => $amount,
'narration' => $narration,
'reference' => $reference
]);
}

public function verifyPayId($payId) {
return $this->makeRequest('POST', '/api/v1/developer/payid/verify', [
'payId' => $payId
]);
}

public function verifyExternalAccount($accountNumber, $bankCode) {
return $this->makeRequest('POST', '/api/v1/developer/transfer/external/verify', [
'accountNumber' => $accountNumber,
'bankCode' => $bankCode
]);
}

public function transferExternal($fromPayId, $accountNumber, $bankCode, $amount, $narration, $reference, $accountName) {
return $this->makeRequest('POST', '/api/v1/developer/transfer/external', [
'fromPayId' => $fromPayId,
'accountNumber' => $accountNumber,
'bankCode' => $bankCode,
'amount' => $amount,
'narration' => $narration,
'reference' => $reference,
'accountName' => $accountName
]);
}

public function getBankList() {
return $this->makeRequest('GET', '/api/v1/developer/banks');
}

public function completePayIdTransfer($fromPayId, $toPayId, $amount, $narration, $reference) {
try {
// Step 1: Verify source PayID
$sourceVerification = $this->verifyPayId($fromPayId);
if (!$sourceVerification['success']) {
throw new Exception('Source PayID verification failed');
}

// Step 2: Verify destination PayID
$destinationVerification = $this->verifyPayId($toPayId);
if (!$destinationVerification['success']) {
throw new Exception('Destination PayID verification failed');
}

// Step 3: Execute transfer
$transfer = $this->transferPayId($fromPayId, $toPayId, $amount, $narration, $reference);

return $transfer;
} catch (Exception $e) {
error_log('PayID transfer failed: ' . $e->getMessage());
throw $e;
}
}

public function completeExternalTransfer($fromPayId, $accountNumber, $bankCode, $amount, $narration, $reference, $accountName) {
try {
// Step 1: Verify external account
$accountVerification = $this->verifyExternalAccount($accountNumber, $bankCode);
if (!$accountVerification['success'] || !$accountVerification['data']['verified']) {
throw new Exception('External account verification failed');
}

// Step 2: Execute transfer
$transfer = $this->transferExternal(
$fromPayId, $accountNumber, $bankCode, $amount, $narration, $reference, $accountName
);

return $transfer;
} catch (Exception $e) {
error_log('External transfer failed: ' . $e->getMessage());
throw $e;
}
}
}

// Usage Examples
$transferManager = new TransferManager($_ENV['INPAY_SECRET_KEY']);

// PayID-to-PayID Transfer
$payIdTransfer = $transferManager->completePayIdTransfer(
'mywallet123.wallet', // Source PayID
'customer456.dpid', // Destination PayID
5000, // ₦50.00
'Payment for order #12345',
'TXN-789'
);

echo "PayID Transfer Completed: " . $payIdTransfer['data']['transactionId'] . "\n";

// External Bank Transfer
$externalTransfer = $transferManager->completeExternalTransfer(
'mywallet123.wallet', // Source PayID
'1234567890', // Destination account number
'058', // GTBank code
10000, // ₦100.00
'Payment to supplier',
'PAY-456',
'John Doe' // Account name
);

echo "External Transfer Completed: " . $externalTransfer['data']['transactionId'] . "\n";

// Get supported banks
$bankList = $transferManager->getBankList();
echo "Supported Banks: " . count($bankList['data']['banks']) . " banks available\n";
?>

🎯 Practical Use Case Examples

1. E-commerce Refund System

// Refund customer for cancelled order
async function processRefund(orderId, customerPayId, refundAmount) {
try {
// Verify customer PayID before refund
const payIdVerification = await transferManager.verifyPayId(customerPayId);
if (!payIdVerification.success) {
throw new Error('Invalid customer PayID');
}

// Process refund using your wallet
const refund = await transferManager.completePayIdTransfer(
process.env.INPAY_WALLET_PAYID, // Your business wallet
customerPayId, // Customer's PayID
refundAmount * 100, // Convert to kobo
`Refund for order #${orderId}`,
`refund-${orderId}-${Date.now()}`
);

// Update your database
await updateOrderStatus(orderId, 'refunded', refund.data.transactionId);

// Send confirmation email
await sendRefundConfirmation(customerPayId, refundAmount, refund.data.transactionId);

return refund;
} catch (error) {
console.error('Refund failed:', error.message);
throw error;
}
}

2. Supplier Payment System

// Pay suppliers via external bank transfer
async function paySupplier(supplierId, invoiceAmount) {
try {
// Get supplier bank details from your database
const supplier = await getSupplierById(supplierId);

// Verify supplier bank account
const accountVerification = await transferManager.verifyExternalAccount(
supplier.accountNumber,
supplier.bankCode
);

if (!accountVerification.success || !accountVerification.data.verified) {
throw new Error('Invalid supplier bank account');
}

// Process payment
const payment = await transferManager.completeExternalTransfer(
process.env.INPAY_WALLET_PAYID, // Your business wallet
supplier.accountNumber, // Supplier's account
supplier.bankCode, // Supplier's bank code
invoiceAmount * 100, // Convert to kobo
`Payment for supplier ${supplier.name}`,
`supplier-${supplierId}-${Date.now()}`,
supplier.accountName // Supplier's name
);

// Update your records
await updateSupplierPayment(supplierId, 'paid', payment.data.transactionId);

return payment;
} catch (error) {
console.error('Supplier payment failed:', error.message);
throw error;
}
}

3. Peer-to-Peer Payment App

// Send money between users
async function sendMoney(senderUserId, recipientPayId, amount, message) {
try {
// Get sender's wallet PayID from your database
const sender = await getUserById(senderUserId);

// Verify recipient PayID
const recipientVerification = await transferManager.verifyPayId(recipientPayId);
if (!recipientVerification.success) {
throw new Error('Invalid recipient PayID');
}

// Check sender's balance (implement your own balance checking)
const senderBalance = await getWalletBalance(sender.walletPayId);
if (senderBalance < amount) {
throw new Error('Insufficient funds');
}

// Process transfer
const transfer = await transferManager.completePayIdTransfer(
sender.walletPayId, // Sender's wallet
recipientPayId, // Recipient's PayID
amount * 100, // Convert to kobo
message || `Payment from ${sender.name}`,
`p2p-${senderUserId}-${Date.now()}`
);

// Update both users' transaction history
await recordTransaction(senderUserId, 'sent', transfer.data);
await recordTransaction(recipientPayId, 'received', transfer.data);

// Send notifications
await sendTransferNotification(recipientPayId, {
amount: amount,
sender: sender.name,
message: message,
transactionId: transfer.data.transactionId
});

return transfer;
} catch (error) {
console.error('P2P transfer failed:', error.message);
throw error;
}
}

4. Salary Disbursement System

// Pay employee salaries
async function disburseSalary(employeeId, salaryAmount) {
try {
// Get employee bank details
const employee = await getEmployeeById(employeeId);

// Verify employee bank account
const accountVerification = await transferManager.verifyExternalAccount(
employee.accountNumber,
employee.bankCode
);

if (!accountVerification.success) {
throw new Error(`Invalid bank account for ${employee.name}`);
}

// Process salary payment
const salaryPayment = await transferManager.completeExternalTransfer(
process.env.INPAY_WALLET_PAYID, // Company wallet
employee.accountNumber, // Employee's account
employee.bankCode, // Employee's bank
salaryAmount * 100, // Convert to kobo
`Salary payment for ${employee.name}`,
`salary-${employeeId}-${new Date().getMonth()}-${new Date().getFullYear()}`,
employee.accountName // Employee's name
);

// Update payroll records
await updatePayrollRecord(employeeId, 'paid', salaryPayment.data.transactionId);

// Send payslip
await sendPayslip(employee.email, {
amount: salaryAmount,
transactionId: salaryPayment.data.transactionId,
month: new Date().getMonth() + 1,
year: new Date().getFullYear()
});

return salaryPayment;
} catch (error) {
console.error('Salary disbursement failed:', error.message);
throw error;
}
}

🚨 Error Handling

Common Errors

Insufficient Funds

{
"success": false,
"message": "Insufficient funds in source wallet",
"code": "INSUFFICIENT_FUNDS"
}

PayID Not Found

{
"success": false,
"message": "PayID not found or inactive",
"code": "PAYID_NOT_FOUND"
}

External Account Verification Failed

{
"success": false,
"message": "Failed to verify external bank account",
"code": "EXTERNAL_ACCOUNT_VERIFICATION_FAILED"
}

Bank Not Supported

{
"success": false,
"message": "Bank code not supported for transfers",
"code": "BANK_NOT_SUPPORTED"
}

Error Handling Example

try {
const transfer = await transferManager.completePayIdTransfer(
fromPayId, toPayId, amount, narration, reference
);

console.log('Transfer successful:', transfer.data.transactionId);
} catch (error) {
if (error.response?.data?.code === 'INSUFFICIENT_FUNDS') {
console.log('Insufficient funds. Please top up your wallet.');
} else if (error.response?.data?.code === 'PAYID_NOT_FOUND') {
console.log('Invalid PayID. Please check the destination PayID.');
} else if (error.response?.data?.code === 'EXTERNAL_ACCOUNT_VERIFICATION_FAILED') {
console.log('Account verification failed. Please check account details.');
} else {
console.error('Transfer failed:', error.message);
}
}

💡 Best Practices

✅ Do's

  • Always verify before transfer: Verify both PayIDs and external accounts
  • Use meaningful references: Include order IDs, customer info, etc.
  • Handle errors gracefully: Implement proper error handling
  • Monitor transaction status: Track transfer completion
  • Keep transaction records: Store transaction IDs for reference
  • Use unique references: Ensure each transfer has a unique reference

❌ Don'ts

  • Don't skip verification: Always verify accounts before transfers
  • Don't ignore errors: Handle all possible error scenarios
  • Don't reuse references: Each transfer needs a unique reference
  • Don't store sensitive data: Keep account numbers and bank codes secure
  • Don't make transfers without confirmation: Always confirm transfer details

📊 Transfer Comparison

FeaturePayID-to-PayIDExternal Bank Transfer
SpeedInstantStandard bank processing
VerificationPayID verificationAccount verification
CostLower feesHigher fees
Use CaseInternal transfersExternal payments
RequirementsBoth PayIDsBank account details
LimitationsiNPAY network onlyNigerian banks only

Next Steps: