Reusable vs Non-Reusable Paystack Authorizations
Reusable authorizations (reusable: true) come from card payments and can be charged again via charge_authorization. Non-reusable authorizations (reusable: false) come from bank transfers, USSD, and some mobile money channels. They are one-time records that cannot be used for future charges. Always check the reusable field before storing an authorization for recurring billing.
The Reusable Field Explained
Every Paystack authorization object has a reusable field. It is a boolean: true or false. This single field determines whether you can charge the customer again using that authorization.
{
"authorization_code": "AUTH_xxxxxxxxxxxxx",
"bin": "408408",
"last4": "4081",
"channel": "card",
"card_type": "visa",
"reusable": true
}
When reusable is true, you can call charge_authorization with this code any number of times. Each call charges the customer's card without requiring them to re-enter details or authenticate again.
When reusable is false, the authorization is a record of the payment method used, but you cannot charge it again. Calling charge_authorization with a non-reusable code will fail.
This distinction exists because different payment channels have different capabilities. Card networks (Visa, Mastercard, Verve) support tokenization and merchant-initiated transactions. Bank transfers, USSD, and some mobile money providers do not. The reusable field reflects the underlying channel's capability.
This article is part of the subscriptions and recurring billing guide.
Which Payment Channels Produce Which Type
Here is how the major Paystack payment channels map to authorization reusability:
| Channel | Reusable | Notes |
|---|---|---|
| Card (Visa, Mastercard, Verve) | Yes | The primary path for recurring billing |
| Bank Transfer | No | Each transfer must be initiated by the customer |
| USSD | No | Session-based, no tokenization possible |
| Mobile Money (Ghana) | Varies | Some providers may support recurring; check Paystack docs for current status |
| QR Code | No | One-time payment method |
| Apple Pay | Varies | Depends on Paystack's current implementation |
The card channel is the only universally reliable path to recurring billing on Paystack across all supported countries. If your product depends on recurring charges, you need customers to pay with cards.
This creates a tension in African markets. Many customers prefer bank transfers or USSD because they do not have cards or are uncomfortable entering card details online. Your onboarding flow needs to handle this gracefully: accept the first payment through any channel, then guide the customer to add a card if they want to set up recurring billing.
Checking the Reusable Flag in Your Code
Check the reusable field at two points: when processing the first payment webhook and when attempting to set up recurring billing.
During webhook processing:
app.post('/webhooks/paystack', function(req, res) {
var event = req.body;
if (event.event === 'charge.success') {
var auth = event.data.authorization;
var customer = event.data.customer;
if (auth.reusable) {
// Safe to store for recurring billing
saveReusableAuthorization({
userId: customer.email,
authorizationCode: auth.authorization_code,
last4: auth.last4,
cardType: auth.card_type,
expMonth: auth.exp_month,
expYear: auth.exp_year,
bank: auth.bank,
channel: auth.channel,
signature: auth.signature,
});
console.log('Stored reusable auth for ' + customer.email);
} else {
console.log('Non-reusable auth from ' + auth.channel + ' for ' + customer.email);
// Do NOT store for recurring billing
// Optionally: prompt customer to add a card
flagForCardPrompt(customer.email);
}
}
res.sendStatus(200);
});
Before setting up a subscription or recurring charge:
async function setupRecurringBilling(userId) {
var paymentMethod = await getDefaultPaymentMethod(userId);
if (!paymentMethod) {
return {
success: false,
reason: 'no_payment_method',
message: 'No payment method on file. Customer needs to make a card payment first.',
};
}
if (!paymentMethod.is_reusable) {
return {
success: false,
reason: 'not_reusable',
message: 'Current payment method (' + paymentMethod.channel + ') does not support recurring charges. Customer needs to add a card.',
};
}
// Proceed with subscription creation or recurring charge setup
return { success: true, authorizationCode: paymentMethod.authorization_code };
}
Handling Customers with Non-Reusable Authorizations
A customer paid via bank transfer. Your product needs recurring billing. What now?
You have the customer's money for this payment, but you cannot charge them automatically in the future. Here are the patterns that work:
Pattern 1: Prompt for card during onboarding
After the bank transfer succeeds, show the customer a message: "To enable automatic billing, please add a card." Direct them to a payment page that collects card details through Paystack Checkout. This creates a reusable authorization you can store.
async function createCardCollectionTransaction(email) {
// Charge a small amount (or zero if Paystack allows) to collect card details
var response = await axios.post(
'https://api.paystack.co/transaction/initialize',
{
email: email,
amount: 5000, // Small verification charge (50 NGN)
callback_url: 'https://yoursite.com/card-added',
metadata: {
purpose: 'card_collection',
note: 'This small charge verifies your card for future billing.',
},
},
{
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
}
);
return response.data.data.authorization_url;
}
Pattern 2: Send recurring payment reminders
If the customer chooses not to add a card, send them a payment link before each billing cycle. They click the link and pay manually. Not truly "recurring" but it works for customers who prefer bank transfers.
Pattern 3: Accept non-recurring as a business decision
Some products are fine with manual payments. The customer pays each month through your checkout page. You do not need recurring billing for every use case. Just make sure your product handles the gap between billing cycles gracefully (reminders, grace periods, access control).
Edge Cases Across African Markets
Payment channel behavior varies by country. Here are the patterns to watch for:
Nigeria
Cards are the main reusable channel. Bank transfer is popular but non-reusable. USSD (via *737#, *966#, etc.) is non-reusable. Verve cards (Nigeria's domestic card scheme) produce reusable authorizations just like Visa and Mastercard.
Ghana
Mobile money (MTN MoMo, Vodafone Cash, AirtelTigo Money) is the dominant payment method. Mobile money authorization reusability depends on the provider and Paystack's current integration status. Check the Paystack documentation for the latest. Card payments remain the reliable path for recurring billing.
South Africa
Card payments produce reusable authorizations. The card ecosystem is more mature here, so a higher percentage of customers have cards suitable for recurring billing.
Kenya
Paystack supports card payments in KES. M-Pesa integration (where available) does not produce reusable Paystack authorizations in the same way. For M-Pesa recurring billing, you typically need to use M-Pesa's own STK Push on a schedule, which is a different integration from Paystack. See the complete Paystack guide for more on multi-country strategies.
The practical takeaway: if your product operates across multiple African countries, build your recurring billing system on card authorizations and treat other channels as one-time payment options. Display clear messaging about which payment methods support automatic billing.
The Signature Field and Card Deduplication
Both reusable and non-reusable authorizations have a signature field. For reusable (card) authorizations, the signature identifies the physical card. Two authorization codes with the same signature represent the same card.
Use signatures to deduplicate when a customer pays with the same card multiple times:
async function handleNewAuthorization(userId, auth) {
if (!auth.reusable) {
// Non-reusable. Log it but do not store for recurring.
console.log('Non-reusable auth from channel: ' + auth.channel);
return;
}
// Check if we already have this card
var existing = await db.query(
'SELECT id, authorization_code_encrypted FROM payment_methods WHERE user_id = $1 AND paystack_signature = $2 AND deactivated_at IS NULL',
[userId, auth.signature]
);
if (existing.rows.length > 0) {
// Same card, new authorization code. Update it.
// The newer auth code might have updated expiry info.
console.log('Updating existing card (same signature)');
await updateAuthorization(existing.rows[0].id, auth);
return;
}
// New card. Save it.
console.log('New card added: ' + auth.card_type + ' ending in ' + auth.last4);
await saveNewAuthorization(userId, auth);
// If this is the first card, make it the default
var cardCount = await db.query(
'SELECT COUNT(*) as count FROM payment_methods WHERE user_id = $1 AND is_reusable = true AND deactivated_at IS NULL',
[userId]
);
if (parseInt(cardCount.rows[0].count) === 1) {
await setDefaultPaymentMethod(userId, auth.signature);
}
}
For non-reusable authorizations, the signature may not be as useful since you cannot charge them again. But it can still help you identify the payment source for reporting purposes.
Building a Payment Method Picker for Your UI
When a customer has multiple saved cards, let them choose which one to use. Only show reusable, non-expired authorizations.
async function getPaymentMethodsForDisplay(userId) {
var now = new Date();
var currentYear = now.getFullYear();
var currentMonth = now.getMonth() + 1;
var methods = await db.query(
'SELECT id, card_last4, card_type, card_bank, exp_month, exp_year, is_default FROM payment_methods WHERE user_id = $1 AND is_reusable = true AND deactivated_at IS NULL ORDER BY is_default DESC, created_at DESC',
[userId]
);
var results = [];
for (var i = 0; i < methods.rows.length; i++) {
var method = methods.rows[i];
var isExpired = method.exp_year < currentYear ||
(method.exp_year === currentYear && method.exp_month < currentMonth);
var isExpiringSoon = !isExpired && (
(method.exp_year === currentYear && method.exp_month <= currentMonth + 2) ||
(method.exp_year === currentYear + 1 && currentMonth >= 11 && method.exp_month <= (currentMonth + 2 - 12))
);
results.push({
id: method.id,
display: method.card_type + ' ending in ' + method.card_last4,
bank: method.card_bank,
expiry: method.exp_month + '/' + method.exp_year,
isDefault: method.is_default,
isExpired: isExpired,
isExpiringSoon: isExpiringSoon,
});
}
return results;
}
In your UI, mark expired cards and cards expiring soon. Let the customer remove cards, set a new default, and add new cards. The "add card" flow sends them through Paystack Checkout, which creates a new reusable authorization.
Testing with Both Authorization Types
In Paystack's test environment, you can simulate both reusable and non-reusable authorizations.
Card test payments (using Paystack's test card numbers) produce reusable authorizations. Bank transfer test payments produce non-reusable ones. Use both in your integration tests to verify that your code handles the distinction correctly.
// Integration test: verify reusable check works
async function testNonReusableHandling() {
// Simulate a bank transfer authorization
var bankAuth = {
authorization_code: 'AUTH_test_bank_xxx',
channel: 'bank',
reusable: false,
last4: '0000',
card_type: null,
bank: 'Test Bank',
};
var result = await setupRecurringBilling(bankAuth);
// Should return an error indicating card is needed
console.log('Non-reusable test result:', result.success === false ? 'PASS' : 'FAIL');
console.log('Message:', result.message);
}
async function testReusableHandling() {
// Simulate a card authorization
var cardAuth = {
authorization_code: 'AUTH_test_card_xxx',
channel: 'card',
reusable: true,
last4: '4081',
card_type: 'visa',
bank: 'TEST BANK',
exp_month: '12',
exp_year: '2030',
signature: 'SIG_test_xxx',
};
var result = await setupRecurringBilling(cardAuth);
console.log('Reusable test result:', result.success === true ? 'PASS' : 'FAIL');
}
Make sure your test suite covers the complete flow: webhook processing, authorization storage, reusable check, and charge attempt. Edge cases to test include a customer with only non-reusable authorizations trying to subscribe, and a customer updating from a non-reusable to a reusable payment method.
Key Takeaways
- ✓The reusable field on a Paystack authorization tells you whether it can be charged again. Only reusable: true authorizations work with charge_authorization.
- ✓Card payments almost always produce reusable authorizations. This is the only reliable path to recurring billing on Paystack.
- ✓Bank transfer payments produce non-reusable authorizations. The customer must initiate each transfer manually.
- ✓USSD payments typically produce non-reusable authorizations. You cannot auto-debit a customer through their USSD channel.
- ✓Mobile money reusability varies by country and provider. Check the Paystack documentation for your specific market.
- ✓When a customer pays with a non-reusable channel and you need recurring billing, prompt them to add a card for future charges.
- ✓Always check reusable before storing an authorization for recurring use. Failing to check causes charge failures later.
Frequently Asked Questions
- Can I make a bank transfer authorization reusable?
- No. The reusable flag is determined by the payment channel at the time of the transaction. Bank transfers do not support tokenization, so the authorization is always non-reusable. The customer needs to make a card payment to get a reusable authorization.
- What happens if I try to charge a non-reusable authorization?
- The charge_authorization API call will fail. Paystack returns an error indicating the authorization cannot be used for recurring charges. Your code should check the reusable field before attempting a charge to avoid this error.
- Do Verve cards produce reusable authorizations?
- Yes. Verve is a card network, and card payments on Paystack produce reusable authorizations regardless of whether the card is Visa, Mastercard, or Verve. The tokenization happens at the card network level.
- Can mobile money produce reusable authorizations on Paystack?
- It depends on the country and the mobile money provider. Some providers support recurring debit mandates, but this is not universal. Check the Paystack documentation for your specific market. Card payments remain the most reliable path for recurring billing across all Paystack-supported countries.
- If a customer adds a card after paying with bank transfer, do they have two authorizations?
- Yes. The bank transfer created a non-reusable authorization, and the card payment creates a new reusable authorization. Both exist on the customer's Paystack record. Your application should use the reusable one for recurring billing and ignore the non-reusable one for charging purposes.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon