What Is a Payment Hold?
A payment hold--also called a pre-authorization or authorization hold--is a temporary reservation of funds on a customer's payment method. When you place a hold, Stripe verifies that the card has sufficient funds available and reserves that amount without actually capturing or charging the money. The held funds remain unavailable for other transactions until the hold is either captured, canceled, or expires.
Payment holds differ from immediate charges in a fundamental way: authorization reserves funds while capture completes the transaction. This two-step process gives businesses flexibility to adjust amounts based on actual usage, consumption, or fulfillment before finalizing the charge. The payment hold mechanism relies on the card authorization system built into credit and debit card networks.
Why Use Payment Holds?
Businesses use payment holds across numerous scenarios where the final transaction amount isn't known at checkout:
- Rental deposits: Car rental companies need to verify customers can cover potential damages before vehicle pickup, authorizing deposit amounts at the counter
- Hotel reservations: Hotels authorize nightly rates plus incidentals during the entire stay, capturing actual charges upon checkout
- Equipment rentals: Service providers hold deposits until equipment returns undamaged, capturing only necessary fees when the rental concludes
- Pre-orders: E-commerce platforms reserve funds for items not yet shipped, capturing when products are ready for fulfillment
- Variable pricing: Service providers charge based on time or materials consumed, authorizing maximum potential amounts and capturing actual totals
For any business model involving variable final amounts or delayed fulfillment, payment holds provide essential flexibility. Our web development services can help you integrate these payment flows seamlessly into your platform. Subscription services sometimes use holds to verify payment method validity before trial periods begin, ensuring smooth transitions to paid billing when trials conclude.
Standard Authorization Duration
Standard card authorizations typically remain valid for five to seven days, depending on the card network and issuing bank. During this window, the held funds remain reserved against the cardholder's available balance. After the authorization period expires, the hold automatically releases unless captured beforehand.
| Card Network | Typical Duration |
|---|---|
| Visa | 7 days |
| Mastercard | 7 days |
| American Express | 5 days |
| Debit Cards | 24-48 hours (varies) |
The exact duration varies by card type and issuer policy. Visa and Mastercard authorizations generally expire after seven days, while some debit cards may release holds sooner. American Express authorizations often have shorter windows, typically around five days. These limitations exist because card networks need to balance merchant needs against consumer cash flow concerns.
For most standard transactions, the seven-day window provides adequate time to capture funds. However, certain business models require longer hold periods. Car rental companies holding deposits for week-long rentals need authorization to remain valid throughout the customer journey. Hotels hosting extended stays need holds lasting the entire reservation. Equipment rentals spanning multiple weeks cannot rely on standard authorizations.
When your business requires longer reservation periods beyond the standard authorization window, Stripe's extended authorization feature extends the hold period significantly to accommodate these use cases.
Extended Authorization: Up to 30 Days
Extended authorization allows businesses to place holds that remain valid for up to 30 days after the initial authorization. This extended timeframe accommodates business models requiring longer reservation periods, such as long-term equipment rentals, advance bookings, or subscription setups with delayed billing cycles.
To use extended authorization, you configure your PaymentIntent to request the extended window by setting extended_authentication and incremental_authorization_supported parameters. The card network and issuing bank must support this feature--most major cards do, but availability can vary by issuer and card type. When enabled, the hold remains active for up to 30 days, giving you additional flexibility to complete the transaction when ready.
Extended authorization works identically to standard authorization from the customer's perspective. The card shows a pending transaction, and the reserved amount remains unavailable for other purchases. The difference lies entirely in the backend configuration that extends the reservation period. The payment element handles the extended window automatically when configured.
Use Cases for Extended Authorization
Long-term rentals benefit significantly from extended authorization windows. A construction equipment rental company lending machinery for several weeks needs funds held throughout the rental period. A boat rental service offering week-long charters requires authorization lasting the entire booking duration. Extended authorization makes these business models possible without requiring customers to re-authorize payments. Implementing automated authorization management through AI-powered automation can help you track and manage holds at scale.
Advance booking scenarios also benefit from extended holds. Event venues booking weddings months in advance may want payment method authorization at booking to guarantee payment upon finalization. Travel agencies arranging trips far in advance can use extended authorization to reserve funds without immediately charging.
Implementation with PaymentIntents
Stripe's PaymentIntents API provides the foundation for implementing payment holds. The key configuration involves setting capture_method to 'manual', which creates a PaymentIntent that authorizes funds without capturing them. This manual capture approach gives you complete control over when funds are actually transferred.
Creating a PaymentIntent for Holds
const paymentIntent = await stripe.paymentIntents.create({
amount: 5000,
currency: 'usd',
capture_method: 'manual',
payment_method_types: ['card'],
automatic_payment_methods: {
enabled: true,
allow_redirects: 'never' // Recommended for holds
}
});
Key Parameters
amount: Maximum amount you might capture (in cents)currency: Transaction currencycapture_method: 'manual': Enables authorization-only flowpayment_method_types: Controls available payment methods
Confirming the Authorization
const { paymentIntent, error } = await stripe.confirmPayment({
clientSecret: paymentIntent.client_secret,
confirm_params: {
return_url: 'https://your-site.com/complete',
payment_method_data: {
type: 'card',
card: cardElement
}
}
});
After successful authorization, the PaymentIntent status changes to requires_capture. The funds are held and unavailable for other transactions.
Capturing the Hold
// Capture full amount
const capture = await stripe.paymentIntents.capture(paymentIntent.id);
// Capture partial amount
const partialCapture = await stripe.paymentIntents.capture(
paymentIntent.id,
{ amount_to_capture: 3500 }
);
Canceling Authorizations
// Cancel to release funds
const canceled = await stripe.paymentIntents.cancel(paymentIntent.id);
For robust payment integration architecture, consider working with our web development team to build secure, scalable payment workflows.
Complete Authorization Workflow
Step 1: Create PaymentIntent
Initialize a PaymentIntent with capture_method: 'manual' to indicate you want to authorize without immediate capture. The PaymentIntent object includes an authorization property containing details about the hold, including its expiration timestamp. Track this expiration time in your database to know when holds will auto-release.
Step 2: Confirm Authorization
Your frontend receives the PaymentIntent's client secret after creation. Use Stripe's payment elements or mobile SDKs to collect payment method details and confirm the PaymentIntent. When confirming with manual capture, the payment element handles the authentication flow while your code specifies capture method preferences.
Step 3: Hold Funds (requires_capture Status)
After successful authorization, the PaymentIntent status changes to requires_capture, indicating funds are authorized and held. This state confirms the reservation against the customer's available balance. The payment intent flows through several states during the authorization lifecycle:
requires_payment_method: Ready for customer payment method entryrequires_confirmation: Awaiting confirmation after method selectionrequires_capture: Authorization successful, funds held
Step 4: Capture or Cancel
- Capture full amount: Complete the transaction for the full authorized sum, status changes to
succeeded - Capture partial amount: Charge less than authorized, releasing the remainder, status changes to
succeeded - Cancel: Release the held funds without charging, status changes to
canceled
The capture request includes an optional amount_to_capture parameter. Omitting this parameter captures the full original amount. Including a smaller amount captures only that portion and releases the remainder immediately to the customer.
Common Use Cases
Rental Deposits and Security Holds
Rental businesses use payment holds to secure against damage, loss, or cleaning costs. For rental deposits:
// Create hold for rental deposit
const depositHold = await stripe.paymentIntents.create({
amount: 50000, // $500 deposit in cents
currency: 'usd',
capture_method: 'manual',
description: 'Equipment rental deposit'
});
// On safe return - capture only cleaning fee
await stripe.paymentIntents.capture(depositHold.id, {
amount_to_capture: 5000 // $50 cleaning fee
});
// If damage occurs - capture full deposit
await stripe.paymentIntents.capture(depositHold.id);
Hotel and Accommodation Authorizations
Hotels authorize card deposits upon check-in, covering potential room charges, minibar consumption, or damages during the stay. Upon checkout, capture actual charges and release any unused portion:
// Hotel check-in authorization
const hotelAuth = await stripe.paymentIntents.create({
amount: 30000, // Nightly rate + buffer
currency: 'usd',
capture_method: 'manual',
description: 'Hotel deposit'
});
// Checkout - capture actual room + incidentals
const finalCharge = roomRate + minibarCharges;
await stripe.paymentIntents.capture(hotelAuth.id, {
amount_to_capture: finalCharge * 100
});
Pre-Orders and Backorder Fulfillment
E-commerce businesses use payment holds for pre-orders where products aren't yet shipped:
// Pre-order authorization
const preorder = await stripe.paymentIntents.create({
amount: productPrice * 100,
currency: 'usd',
capture_method: 'manual',
metadata: { order_type: 'preorder' }
});
// When product ships
await stripe.paymentIntents.capture(preorder.id);
Variable-Price Transactions
For services with variable final amounts, authorize the maximum possible amount:
// Catering - authorize maximum for 100 guests
const cateringHold = await stripe.paymentIntents.create({
amount: 10000, // $100 max per guest
currency: 'usd',
capture_method: 'manual',
description: 'Catering services'
});
// After event - capture actual guest count
const actualCharge = actualGuests * 10000;
await stripe.paymentIntents.capture(cateringHold.id, {
amount_to_capture: actualCharge
});
These payment hold patterns integrate seamlessly with comprehensive web development solutions for rental platforms, hospitality systems, and e-commerce stores.
Choose Amounts Carefully
For fixed-price transactions, authorize the exact amount needed. For variable scenarios, authorize the maximum potential amount--you can capture less, but not more.
Monitor Hold Durations
Track authorization expirations proactively. Build alerts for holds approaching expiration without capture or cancellation.
Communicate Clearly
Explain authorization policies at checkout. Send confirmation emails after authorization and before capture to prevent customer confusion.
Handle Errors Gracefully
Implement retry logic for failed authorizations. Offer alternative payment methods when primary options fail.
Webhooks and Event Handling
Stripe sends webhook events throughout the authorization lifecycle. Subscribe to these events to track authorization status changes and trigger your business logic automatically:
| Event | Description |
|---|---|
payment_intent.succeeded | Successful authorization (requires_capture status) |
payment_intent.canceled | Authorization voided, funds released |
payment_intent.partially_captured | Partial capture completed |
payment_intent.capture_failed | Capture attempt failed |
Webhook Implementation Example
// Handle authorization events
async function handleWebhook(payload) {
const event = stripe.webhooks.constructEvent(
payload,
webhookSecret,
payload.data.object.object
);
switch (event.type) {
case 'payment_intent.succeeded':
// Authorization successful - funds held
const auth = event.data.object;
console.log(`Funds held: $${auth.amount / 100}`);
// Update order status, send confirmation
break;
case 'payment_intent.canceled':
// Authorization voided
console.log('Authorization canceled');
// Release inventory, notify customer
break;
case 'payment_intent.partially_captured':
// Partial capture completed
const partial = event.data.object;
console.log(`Captured: $${partial.amount_received / 100}`);
// Track variable-price transaction
break;
case 'payment_intent.capture_failed':
// Capture failed - may need new authorization
console.error('Capture failed');
// Notify customer, request new payment
break;
}
}
The payment_intent.capture_failed event requires special handling--capture attempts can fail if the authorization expired or became invalid. When capture fails, you may need to request a new authorization from the customer. Build retry logic or fallback workflows to handle these scenarios gracefully. Automating webhook processing through AI automation services can help you manage complex payment event workflows efficiently.
Frequently Asked Questions
How long do payment holds last?
Standard authorizations last 5-7 days depending on the card network. Visa and Mastercard typically allow 7 days, while American Express is often 5 days. Extended authorization extends this to 30 days for supported cards.
Can I capture more than the authorized amount?
No, you can only capture up to the authorized amount. For variable pricing scenarios, authorize the maximum potential amount--you can capture less, but not more.
What happens if I don't capture within the authorization period?
The authorization expires automatically and held funds are released back to the customer's available balance. The exact timing depends on the card network and issuing bank.
Do all payment methods support authorization holds?
Card payments support holds universally. Some alternative payment methods may capture immediately regardless of configuration. Check Stripe's documentation for specific payment method capabilities.
How do I handle authorization failures?
Present clear error messages and offer alternative payment methods. Implement retry logic for transient failures. For persistent failures, consider requesting a different payment method from the customer.