interswitch-transactions
SKILL.md
Interswitch Transactions API
Manage wallet debits, transaction status checks, reversals, and requery operations.
Transaction Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/transaction/transact |
POST | Debit a wallet |
/api/v1/transaction/reverse |
POST | Reverse a transaction |
/api/v1/transaction/{reference} |
GET | Get transaction by reference |
/collections/api/v1/gettransaction.json |
GET | Requery a web checkout payment |
Debit Wallet
interface DebitWalletDto {
customerId: string; // Wallet PAN or ID
amount: number; // In minor currency (kobo)
currency: string; // '566' for NGN
transactionRef: string; // Unique transaction reference
pin: string; // Wallet 4-digit PIN
requestorId?: string; // Merchant/partner identifier
terminalId?: string;
paymentCode?: string;
}
interface TransactionResponse {
responseCode: string;
responseDescription: string;
amount: number;
transactionRef: string;
paymentId: string;
remittanceAmount?: number;
}
async function debitWallet(
data: DebitWalletDto
): Promise<TransactionResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_WALLET_BASE_URL}/api/v1/transaction/transact`,
{
method: 'POST',
headers,
body: JSON.stringify(data),
}
);
if (!response.ok) {
throw new Error(`Debit failed: ${response.status}`);
}
return response.json();
}
Get Transaction by Reference
async function getTransactionByReference(
reference: string
): Promise<TransactionResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_WALLET_BASE_URL}/api/v1/transaction/${encodeURIComponent(reference)}`,
{
method: 'GET',
headers,
}
);
if (!response.ok) {
throw new Error(`Transaction lookup failed: ${response.status}`);
}
return response.json();
}
Reverse Transaction
interface ReverseTransactionDto {
transactionRef: string; // Original transaction reference
amount: number; // Amount to reverse (kobo)
reversalRef?: string; // Unique reversal reference
}
async function reverseTransaction(
data: ReverseTransactionDto
): Promise<TransactionResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${process.env.INTERSWITCH_WALLET_BASE_URL}/api/v1/transaction/reverse`,
{
method: 'POST',
headers,
body: JSON.stringify(data),
}
);
if (!response.ok) {
throw new Error(`Reversal failed: ${response.status}`);
}
return response.json();
}
Transaction Requery (Web Checkout Payments)
CRITICAL: Always requery transactions server-side after web checkout. Never trust client-side callbacks alone.
interface RequeryResponse {
Amount: number;
ResponseCode: string;
ResponseDescription: string;
MerchantReference: string;
PaymentReference: string;
TransactionDate: string;
RetrievalReferenceNumber: string;
CardNumber?: string;
}
async function requeryTransaction(
merchantCode: string,
transactionRef: string
): Promise<RequeryResponse> {
const headers = await getAuthHeaders();
const url = new URL(
`${process.env.INTERSWITCH_COLLECTIONS_BASE_URL}/collections/api/v1/gettransaction.json`
);
url.searchParams.set('merchantcode', merchantCode);
url.searchParams.set('transactionreference', transactionRef);
url.searchParams.set('amount', '0'); // 0 returns any amount
const response = await fetch(url.toString(), {
method: 'GET',
headers,
});
if (!response.ok) {
throw new Error(`Requery failed: ${response.status}`);
}
return response.json();
}
Response Codes
| Code | Description | Action |
|---|---|---|
00 |
Approved / Successful | Transaction completed |
Z0 |
Transaction not found | Verify reference and retry |
Z1 |
Pending | Check again later |
Z6 |
Pending reversal | Monitor for completion |
T0 |
OTP required | Prompt for OTP validation |
T1 |
3D Secure required | Redirect to 3DS page |
51 |
Insufficient funds | Notify customer |
91 |
Issuer unavailable | Retry later |
06 |
Transaction error | Investigate and contact support |
Complete Transaction Flow
// 1. Initiate debit
const txn = await debitWallet({
customerId: walletPan,
amount: 50000, // ₦500.00
currency: '566',
transactionRef: `TXN_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`,
pin: customerPin,
});
// 2. Check response
if (txn.responseCode === '00') {
console.log('Payment successful:', txn.transactionRef);
} else if (txn.responseCode === 'T0') {
// Handle OTP
console.log('OTP required for:', txn.paymentId);
} else {
console.error('Payment failed:', txn.responseDescription);
}
// 3. Always requery to confirm
const confirmed = await getTransactionByReference(txn.transactionRef);
console.log('Confirmed status:', confirmed.responseCode);
// 4. Reverse if needed
if (needsReversal) {
const reversal = await reverseTransaction({
transactionRef: txn.transactionRef,
amount: txn.amount,
});
console.log('Reversal:', reversal.responseCode);
}
Best Practices
- Generate unique transaction refs — Use timestamps + UUIDs
- Always requery — Never rely solely on initial response
- Implement idempotency — Store refs to prevent duplicate charges
- Handle all response codes — Map codes to user-friendly messages
- Log transactions securely — Never log PINs or full card numbers
Weekly Installs
1
Repository
rexedge/interswitchFirst Seen
3 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1