interswitch-transfers
SKILL.md
Interswitch Transfers API
Process fund transfers to bank accounts and mobile wallets. Supports account validation, single transfers, bulk transfers, and status checks.
Transfer Flow
- Validate account — Confirm the destination account exists
- Build sender object — Party initiating the transfer
- Build beneficiary object — Receiving party details
- Initiate transfer — Submit transfer request with MAC hash
- Check status — Verify transfer completion
Transfer Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v2/nameenquiry |
POST | Validate bank account |
/api/v2/quickteller/payments/transfers |
POST | Initiate single transfer |
/api/v2/quickteller/payments/transfers/bulk |
POST | Initiate bulk transfer |
/api/v2/quickteller/payments/transfers/{ref} |
GET | Check transfer status |
Account Validation (Name Enquiry)
Always validate the destination account before initiating a transfer:
interface AccountValidationRequest {
bankCode: string; // CBN bank code
accountNumber: string; // 10-digit NUBAN
}
interface AccountValidationResponse {
responseCode: string;
accountName: string;
accountNumber: string;
bankCode: string;
bankName: string;
}
async function validateAccount(
data: AccountValidationRequest
): Promise<AccountValidationResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_BASE_URL}/api/v2/nameenquiry`,
{
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
},
body: JSON.stringify({
bankCode: data.bankCode,
accountId: data.accountNumber,
}),
}
);
if (!response.ok) {
throw new Error(`Account validation failed: ${response.status}`);
}
return response.json();
}
MAC Hash Generation
Transfers require a MAC (Message Authentication Code) for security. The MAC is a SHA-512 hash of concatenated transfer fields:
import crypto from 'crypto';
interface MACFields {
amount: string;
sendCurrency: string;
receiveCurrency: string;
paymentMethod: string;
countryCode: string;
}
function generateMAC(fields: MACFields): string {
// Concatenate fields in order
const data = [
fields.amount,
fields.sendCurrency,
fields.receiveCurrency,
fields.paymentMethod,
fields.countryCode,
].join('');
return crypto
.createHash('sha512')
.update(data)
.digest('hex');
}
Single Transfer
interface TransferParty {
name: string;
accountNumber: string;
bankCode: string;
accountType?: string;
phoneNumber?: string;
email?: string;
}
interface SingleTransferRequest {
mac: string; // SHA-512 MAC hash
beneficiary: TransferParty;
sender: TransferParty;
initiatingEntityCode: string; // Your merchant code
transferAmount: {
amount: number; // In minor currency (kobo)
currency: string; // 'NGN'
};
paymentMethod: string; // 'AC' for account
terminatingEntityCode: string; // Beneficiary bank code
countryCode: string; // 'NG'
transactionRef: string;
}
interface TransferResponse {
responseCode: string;
responseDescription: string;
transactionRef: string;
transferCode: string;
paymentId: string;
}
async function initiateSingleTransfer(
data: SingleTransferRequest
): Promise<TransferResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_BASE_URL}/api/v2/quickteller/payments/transfers`,
{
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
}
);
if (!response.ok) {
throw new Error(`Transfer failed: ${response.status}`);
}
return response.json();
}
Check Transfer Status
async function checkTransferStatus(
transactionRef: string
): Promise<TransferResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_BASE_URL}/api/v2/quickteller/payments/transfers/${encodeURIComponent(transactionRef)}`,
{
method: 'GET',
headers,
}
);
if (!response.ok) {
throw new Error(`Transfer status check failed: ${response.status}`);
}
return response.json();
}
Complete Transfer Flow
// 1. Validate destination account
const validation = await validateAccount({
bankCode: '058', // GTBank
accountNumber: '0123456789',
});
console.log('Account Name:', validation.accountName);
// 2. Generate MAC hash
const mac = generateMAC({
amount: '500000', // ₦5,000
sendCurrency: 'NGN',
receiveCurrency: 'NGN',
paymentMethod: 'AC',
countryCode: 'NG',
});
// 3. Initiate transfer
const transfer = await initiateSingleTransfer({
mac,
sender: {
name: 'Your Business',
accountNumber: '9876543210',
bankCode: '044',
},
beneficiary: {
name: validation.accountName,
accountNumber: '0123456789',
bankCode: '058',
},
initiatingEntityCode: process.env.INTERSWITCH_MERCHANT_CODE!,
transferAmount: {
amount: 500000,
currency: 'NGN',
},
paymentMethod: 'AC',
terminatingEntityCode: '058',
countryCode: 'NG',
transactionRef: `TRF_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`,
});
console.log('Transfer ref:', transfer.transactionRef);
// 4. Check status
const status = await checkTransferStatus(transfer.transactionRef);
console.log('Transfer status:', status.responseCode);
Common Bank Codes
| Bank | Code |
|---|---|
| Access Bank | 044 |
| First Bank | 011 |
| GTBank | 058 |
| UBA | 033 |
| Zenith Bank | 057 |
| Stanbic IBTC | 221 |
| Fidelity Bank | 070 |
| Sterling Bank | 232 |
| Union Bank | 032 |
| Wema Bank | 035 |
Best Practices
- Always validate accounts — Use name enquiry before every transfer
- Confirm account name with the user before proceeding
- Generate unique references — Prevent duplicate transfers
- Check transfer status — Don't assume success from initial response
- Secure MAC generation — Never expose MAC concatenation logic client-side
- Rate limiting — Implement throttling for bulk operations
Weekly Installs
1
Repository
rexedge/interswitchFirst Seen
3 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1