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
- Verify source PayID - Ensure you have sufficient funds
- Verify destination PayID - Confirm the recipient PayID is active
- Initiate transfer - Send money instantly between PayIDs
- 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
- Verify external account - Confirm bank account details
- Check bank support - Ensure bank is supported for transfers
- Initiate transfer - Send money to external bank account
- 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
| Feature | PayID-to-PayID | External Bank Transfer |
|---|---|---|
| Speed | Instant | Standard bank processing |
| Verification | PayID verification | Account verification |
| Cost | Lower fees | Higher fees |
| Use Case | Internal transfers | External payments |
| Requirements | Both PayIDs | Bank account details |
| Limitations | iNPAY network only | Nigerian banks only |
Next Steps:
- Webhooks Guide - Handle real-time transfer notifications
- API Reference - Explore all available endpoints
- GraphQL API - Learn about GraphQL operations