Partial authorization
Handle issuer-approved amounts that are less than what you requested, and decide whether to accept, decline, or cover the gap.
When a customer pays with a prepaid or gift card that does not have enough balance to cover the full charge, their issuer may choose to approve as much as the card can cover rather than declining outright. The result is a partial authorization: the requested amount is 5000 (€50.00) but the issuer approves only 3200 (€32.00). As the merchant you must decide whether to accept that partial approval, collect the remaining €18.00 through another payment method, or decline and ask the customer for a different card entirely.
Partial authorization is distinct from partial payments, where the customer deliberately splits a transaction across multiple methods from the start.
When partial authorizations occurAsk
Partial auths are most common on:
- Prepaid debit cards — the card balance is a hard ceiling; the issuer cannot approve beyond it.
- Gift cards — the stored value may be less than the purchase total.
- Daily spend limits — some cards have per-day authorization caps set by the issuer or the cardholder.
The scenario is most prevalent in in-person / POS environments where split-tender (combining cash plus card, for example) is a standard checkout flow. It can also occur in online transactions, particularly for marketplace or top-up scenarios where customers reload prepaid instruments.
Not all issuers support partial authorization. When the card network does not support it, an insufficient-balance card returns a full decline instead of a partial approval.
Enable partial authorization acceptanceAsk
By default VINR requests the exact amount you pass and treats any lesser approval as a decline. To tell the issuer that you are willing to accept a partial approval, set partialAuthorization.accept to true when creating the payment.
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const payment = await vinr.payments.create({
amount: 5000, // €50.00 requested
currency: 'EUR',
description: 'Order #7214',
returnUrl: 'https://yoursite.com/orders/7214',
partialAuthorization: {
accept: true, // opt in to receiving a partial approval
},
metadata: { orderId: '7214' },
});Without accept: true, VINR instructs the network to decline if the full amount cannot be authorized. Opt in only if your checkout flow can handle collecting the remainder.
Do not opt in unless you have implemented a split-tender flow. Accepting a partial auth without collecting the remainder means you fulfil the order at a loss.
Handling the responseAsk
After the customer completes the hosted flow, compare payment.amountApproved with payment.amount. If they differ, the issuer granted a partial authorization.
const payment = await vinr.payments.retrieve('pay_8Xk4r9b');
if (payment.partialAuthorization?.status === 'granted') {
const approved = payment.partialAuthorization.amountApproved; // e.g. 3200
const requested = payment.amount; // e.g. 5000
const gap = requested - approved; // e.g. 1800
console.log(`Partial auth granted: ${approved} of ${requested} approved.`);
console.log(`Remaining gap: ${gap} minor units.`);
}You have two options from here:
Option A — accept the partial amount and collect the gap. Keep the partial authorization and open a second payment for the remainder using another method. See Split tender below.
Option B — void the partial auth and request a new method. If your checkout cannot handle a second payment instrument, void the authorization and prompt the customer for a card with sufficient balance.
if (payment.partialAuthorization?.status === 'granted' && !canSplitTender) {
await vinr.payments.void(payment.id);
// redirect customer to choose a different payment method
}Split tender (covering the gap)Ask
Split tender means the order total is covered across two payment instruments: the partial authorization handles what the first card can cover, and a second payment handles the remainder.
const firstPayment = await vinr.payments.retrieve('pay_8Xk4r9b');
const approved = firstPayment.partialAuthorization!.amountApproved; // 3200
const gap = firstPayment.amount - approved; // 1800
// Capture only the approved amount on the first instrument
await vinr.payments.capture(firstPayment.id, { amount: approved });
// Create a second payment for the gap, linked to the same order
const secondPayment = await vinr.payments.create({
amount: gap, // 1800 — the remaining €18.00
currency: firstPayment.currency,
description: 'Order #7214 — remainder',
returnUrl: 'https://yoursite.com/orders/7214',
metadata: {
orderId: '7214',
relatedPayment: firstPayment.id,
},
});
// redirect the customer to secondPayment.checkoutUrl to pay the gapFor a full treatment of orchestrating multiple payment objects against a single order, see Partial payments.
If the second payment fails or the customer abandons it, void the first (or refund it if it was already captured) to avoid partial fulfilment.
partialAuthorization fieldsAsk
Prop
Type
amountApproved and amountDeclined are only populated when status is granted. When status is none (full approval), read payment.amount directly.
AdvancedAsk
Next stepsAsk
Partial payments
Let customers intentionally split a purchase across multiple payment methods.
Authorize & capture
Reserve funds now and capture them later, with support for partial captures.
Refunds
Return captured funds if split tender fails or the order cannot be fulfilled.
Last updated on