When a Paystack authorization has reusable set to false, the card cannot be charged again using the authorization code. This happens because the card type does not support tokenization (prepaid cards, some virtual cards), the issuing bank does not allow recurring charges, or the customer used a one-time card. Check the reusable field in the authorization object after the first charge. If it is false, do not attempt to charge that authorization code. Instead, ask the customer to pay again through the checkout popup, or offer alternative payment methods.
After a successful Paystack charge, the transaction data includes an authorization object. This object contains the card details and, critically, a reusable field:
// Authorization object from a successful transaction
{
"authorization_code": "AUTH_abc123def",
"bin": "408408",
"last4": "4081",
"exp_month": "12",
"exp_year": "2028",
"channel": "card",
"card_type": "visa",
"bank": "GTBank",
"country_code": "NG",
"brand": "visa",
"reusable": false, // This card CANNOT be charged again
"signature": "SIG_xyz789",
"account_name": null
}
When reusable is false, calling /transaction/charge_authorization with this authorization code will fail. Paystack will return an error indicating the authorization cannot be used for recurring charges.
This is different from an expired card or an invalid authorization code. The authorization itself is valid for verification purposes. It just cannot be used to initiate a new charge without the cardholder being present.
The reusable flag is determined by the card issuer and card type, not by Paystack. Paystack simply reports what the card network tells it.
Prepaid cards. Cards loaded with a fixed amount (like gift cards or prepaid Visa/Mastercards) do not support tokenization. The card issuer blocks recurring charges because the card may not have funds when the next charge comes through.
Virtual cards. Many virtual cards issued by fintech apps (like Chipper Cash, Kuda virtual cards, some Carbon cards) are designed for one-time online purchases. They do not support being stored for future charges.
Bank policy restrictions. Some Nigerian banks restrict recurring charges on certain account tiers. A student savings account debit card might process a one-time payment fine but return reusable: false because the bank does not allow that account type to be set up for recurring debits.
International cards with restrictions. Some international card issuers block cross-border recurring charges. A US Visa card might process a one-time payment to a Nigerian merchant on Paystack but refuse to be tokenized for future charges.
Card network rules. Certain card BINs (the first 6 digits of the card number) are registered as non-reusable at the network level. Paystack cannot override this.
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
Always check the reusable field before storing an authorization for future use. Here is the proper flow:
// After a successful charge, check if the card is reusable
async function handleSuccessfulCharge(transactionReference: string) {
const res = await fetch(
`https://api.paystack.co/transaction/verify/${transactionReference}`,
{
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
},
}
);
const data = await res.json();
if (data.data.status !== 'success') {
throw new Error('Transaction was not successful');
}
const authorization = data.data.authorization;
if (authorization.reusable) {
// Safe to store for future charges
await saveAuthorization({
customerId: data.data.customer.id,
authorizationCode: authorization.authorization_code,
last4: authorization.last4,
expMonth: authorization.exp_month,
expYear: authorization.exp_year,
bank: authorization.bank,
cardType: authorization.card_type,
reusable: true,
});
return { canChargeAgain: true };
} else {
// Do NOT store for recurring charges
console.log(
'Card ending in ' + authorization.last4 + ' from ' + authorization.bank + ' is not reusable. ' +
'Will not store for future charges.'
);
return { canChargeAgain: false };
}
}
If you have already stored non-reusable authorizations, clean them up. Query your database for authorizations where reusable = false and either delete them or mark them as inactive.
If you ignore the reusable flag and call /transaction/charge_authorization anyway, Paystack returns an error:
// Attempting to charge a non-reusable authorization
const res = await fetch('https://api.paystack.co/transaction/charge_authorization', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
authorization_code: 'AUTH_abc123def',
email: 'customer@example.com',
amount: 250000,
}),
});
// Response:
{
"status": false,
"message": "Authorization is not reusable"
}
This does not charge the customer. No money moves. But it clutters your logs with failed charge attempts and, worse, it might trigger your system to mark the customer as having a failed payment when the real issue is a card type problem.
If you are running a subscription service, these failed charges create a cascade: the subscription renewal fails, the customer gets a "payment failed" email, the customer contacts support confused because their card "worked fine last month" (it did, for the one-time charge), and your support team has to explain a technical limitation that should have been handled in code.
When a customer's card is not reusable, you have several options depending on your business model:
1. Redirect to checkout each time
Instead of charging the authorization code, redirect the customer to the Paystack checkout popup for each payment. The customer enters their card details each time. This works for all card types.
// For non-reusable cards, always use the checkout flow
async function chargeCustomer(customerId: string, amount: number) {
const customer = await getCustomer(customerId);
const savedAuth = await getSavedAuthorization(customerId);
if (savedAuth && savedAuth.reusable) {
// Charge using saved authorization
return chargeAuthorization(savedAuth.authorizationCode, customer.email, amount);
}
// No reusable authorization: initialize a new transaction
// and redirect the customer to checkout
const res = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: customer.email,
amount,
callback_url: 'https://yoursite.com/payment/callback',
metadata: {
custom_fields: [
{ display_name: 'Customer ID', variable_name: 'customer_id', value: customerId },
],
},
}),
});
const data = await res.json();
return { redirect: true, url: data.data.authorization_url };
}
2. Offer alternative payment channels
Mobile money (M-Pesa), bank transfers, and USSD do not rely on card tokenization. For subscription services in Kenya, M-Pesa is often more reliable than card for recurring payments because M-Pesa does not have the reusable restriction.
3. Ask the customer to use a different card
Politely let the customer know that their current card does not support automatic renewals. Suggest using a different card (a regular debit or credit card from a major bank rather than a prepaid or virtual card).
Customers do not understand payment tokenization. They do not know what "reusable" means. They just know their card worked once and now it does not. Your messaging needs to translate the technical problem into plain language.
Good messages:
Bad messages:
// Email template for non-reusable card notification
function getNonReusableCardEmail(customerName: string, last4: string) {
return {
subject: 'Action needed: Update your payment method',
body: `Hi ${customerName},
Your card ending in ${last4} does not support automatic payments.
This means we cannot charge it automatically for your subscription renewals.
You have two options:
1. Pay manually each month when we send you a payment link
2. Add a different card that supports automatic payments
(most regular bank debit and credit cards work)
To update your payment method, visit:
https://yoursite.com/account/billing
If you have any questions, reply to this email.
Best,
The Payments Team`,
};
}
If you are building a subscription system on Paystack, non-reusable cards are a recurring (pun intended) problem. Here is how to architect your subscription billing to handle them gracefully:
// Subscription billing with reusable card check
async function processSubscriptionRenewal(subscriptionId: string) {
const subscription = await getSubscription(subscriptionId);
const authorization = await getSavedAuthorization(subscription.customerId);
// Case 1: No saved authorization
if (!authorization) {
await sendPaymentLink(subscription);
return { status: 'payment_link_sent' };
}
// Case 2: Authorization exists but is not reusable
if (!authorization.reusable) {
await sendPaymentLink(subscription);
await notifyCardNotReusable(subscription.customerId, authorization.last4);
return { status: 'payment_link_sent', reason: 'card_not_reusable' };
}
// Case 3: Authorization exists and is reusable
try {
const charge = await chargeAuthorization(
authorization.authorizationCode,
subscription.customerEmail,
subscription.amount
);
if (charge.data.status === 'success') {
await extendSubscription(subscriptionId, subscription.interval);
return { status: 'charged', reference: charge.data.reference };
}
// Charge failed for other reasons (expired card, insufficient funds)
await sendPaymentLink(subscription);
return { status: 'payment_link_sent', reason: 'charge_failed' };
} catch (err) {
await sendPaymentLink(subscription);
return { status: 'payment_link_sent', reason: 'charge_error' };
}
}
async function sendPaymentLink(subscription: any) {
const res = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: subscription.customerEmail,
amount: subscription.amount,
callback_url: `https://yoursite.com/subscription/${subscription.id}/renew-callback`,
}),
});
const data = await res.json();
await sendRenewalEmail(subscription.customerEmail, data.data.authorization_url);
}
The payment link fallback ensures every customer can still pay, even if their card is not reusable. The customer experience is slightly worse (they have to click a link and enter details) but the alternative is a failed renewal and a churned customer.
Test each scenario before going live:
reusable field from the authorization object and stores it correctly. In test mode, Paystack test cards typically return reusable: true, so you may need to manually test the false path by mocking the response.reusable field to false in your database. Trigger a subscription renewal. Confirm that your system sends a payment link instead of trying to charge the authorization.reusable: false. If you have been storing non-reusable authorizations, clean them up.For a complete guide to subscription billing with Paystack, including handling all card failure scenarios, see the Paystack Subscription Not Charging troubleshooting guide.
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course