Skip to main content

Authorization & Capture

Authorization and capture is a two-phase payment model. An authorization places a hold on funds without moving money. A capture (called a settle in AccruPay) completes the transfer. Between those two events, you can inspect the hold, partially capture it, or release it entirely.

When to use it

Use caseWhy auth + capture fits
Hotels and rentalsAuth at booking; capture the final amount at checkout, which may differ from the original hold.
MarketplacesAuth when a buyer commits; capture only after the seller confirms fulfillment.
Delayed shipmentAuth at order placement; capture when goods ship, staying within the provider's capture window.
Variable-amount ordersAuth for an estimated max; capture the exact amount once it is known.

Authorization flows

Via card UI (client session)

The customer enters their card details in the React SDK checkout — identical to a regular payment flow, but using the authorizations namespace.

Server: start the authorization session

import AccruPay, { TRANSACTION_PROVIDER, CURRENCY, COUNTRY_ISO_2 } from '@accrupay/node';

const sdk = new AccruPay({ apiSecret: process.env.ACCRUPAY_API_SECRET });

const session = await sdk.transactions.clientSessions.authorizations.start({
transactionProvider: TRANSACTION_PROVIDER.YOUR_PROVIDER,
data: {
amount: 20000n,
currency: CURRENCY.USD,
merchantInternalCustomerCode: 'customer-123',
merchantInternalTransactionCode: 'auth-456',
billing: {
billingFirstName: 'Jane',
billingLastName: 'Smith',
billingEmail: 'jane@example.com',
billingAddressCountry: COUNTRY_ISO_2.US,
},
},
});
// Send session.id to your frontend

Frontend: render the checkout

import { AccruPay, CardNumber, CardExpiry, CardCVC, SubmitButton } from '@accrupay/react';

function AuthForm({ sessionId }: { sessionId: string }) {
return (
<AccruPay
merchantPublicId="your-merchant-public-id"
transactionSessionId={sessionId}
>
<CardNumber />
<CardExpiry />
<CardCVC />
<SubmitButton>Authorize $200.00</SubmitButton>
</AccruPay>
);
}

Server: verify the authorization

const transaction = await sdk.transactions.clientSessions.authorizations.verify({
id: session.id,
});
// Store transaction.id — you need it to settle or void later

Via stored payment method (server session)

If the customer already has a stored payment method, the entire flow is server-side.

// Start a server-side authorization session
const session = await sdk.transactions.serverSessions.authorizations.paymentMethod.start({
transactionProvider: TRANSACTION_PROVIDER.YOUR_PROVIDER,
data: {
merchantCustomerPaymentMethodId: 'payment-method-id',
amount: 20000n,
currency: CURRENCY.USD,
merchantInternalCustomerCode: 'customer-123',
merchantInternalTransactionCode: 'auth-789',
billing: {
billingFirstName: 'Jane',
billingLastName: 'Smith',
billingEmail: 'jane@example.com',
billingAddressCountry: COUNTRY_ISO_2.US,
},
},
});

const transaction = await sdk.transactions.serverSessions.authorizations.paymentMethod.verify({
id: session.id,
});

Capturing funds (settle)

Call settle() to capture the authorized amount and move funds. You must always pass an explicit amount.

// Full capture — settle the full authorized amount
const settled = await sdk.transactions.authorizations.settle({
id: transaction.id,
data: {
amount: 20000n, // must match or be less than the authorized amount
},
});

Partial capture

Settle with an amount less than what was authorized. The remaining hold is released automatically.

// Partial capture — charge only $150 of the $200 hold
const settled = await sdk.transactions.authorizations.settle({
id: transaction.id,
data: {
amount: 15000n, // $50 hold is released
},
});
warning

settle() requires you to pass amount explicitly. There is no "capture full amount" shorthand — omitting amount is a validation error.

Releasing the hold (void)

Call void() to cancel the authorization and release the full hold. No funds move.

await sdk.transactions.authorizations.void({
id: transaction.id,
});

Status transitions

Auth transaction: PENDING → SUCCEEDED (approved, funds on hold)
├─ settle() → new SETTLE transaction → SUCCEEDED
└─ void() → auth transaction → CANCELED
OutcomeTransaction statusNotes
Authorization approvedSUCCEEDEDFunds reserved, not yet captured
Captured (settled)SUCCEEDED (new SETTLE transaction)settle() creates a separate child transaction
Hold releasedCANCELED (original auth transaction)void() cancels the hold with no charge

The original authorization transaction moves to CANCELED after a void, or remains SUCCEEDED indefinitely after a successful settle (the settle creates its own separate transaction record).

Provider capture windows

All providers enforce a maximum window between authorization and capture. After this window closes, the hold expires automatically and any subsequent settle() call will fail at the provider level. Void the transaction and create a fresh authorization if needed.

Authorization capture windows
Nuvei

7 days from authorization. Authorizations not settled or voided within this window are automatically released by Nuvei.

Stripe

7 days from authorization. Uncaptured PaymentIntents expire after 7 days and Stripe releases the hold automatically.

Other providers

Capture windows vary significantly — from 1 day to 30 days depending on the PSP and card network rules. Consult your payment provider's documentation for the exact limit before designing your capture flow.