WooCommerce stores that need to protect against no-shows, damage, or unreturned equipment usually reach for one of two mechanisms: charge the customer upfront and refund them later, or place a Stripe authorization hold that reserves funds without moving them. The two are often treated as interchangeable. They aren’t, and the difference matters for how a store handles refund timing and what shows up on the customer’s own bank statement.
This article lays out the distinction in plain terms, gives store owners and developers a framework for choosing between the two, and points to more detailed guides for the parts that deserve a deeper technical treatment.
The problem: WooCommerce core has no built-in security-deposit workflow
WooCommerce does not ship with a dedicated security-deposit feature. What it does have is a generic “On hold” order status, and its own documentation is explicit about why it exists: a store sees “On hold” when it uses a payment gateway that has an option to separate the authorization and capture of funds. In other words, WooCommerce core recognizes that authorization and capture can happen at different times, but it has no concept of a deposit amount, no handling for an authorization’s expiry window, and no interface for capturing or releasing funds beyond whatever the payment gateway itself provides or a manual order-status change.
That gap is exactly why “how do I handle security deposits in WooCommerce” doesn’t have a single built-in answer. It has two competing implementation strategies, and the right one depends on the gateway’s capabilities and the store’s use case.
Four terms that get conflated: payment, refund, security deposit, authorization hold
Part of the confusion comes from treating these four words as synonyms for “money-related event.” They aren’t. Two describe payment operations, and two describe business concepts that can be implemented with different payment operations.
Payment and refund: moving money
A payment (a captured charge) moves funds from the customer’s card issuer to the merchant. A refund moves previously captured funds back. Both are settlement events. WooCommerce’s order statuses track these loosely rather than one to one: “Processing” generally follows a received payment, “Refunded” specifically marks a refund that’s been issued, and “Completed” marks that the order has been fulfilled, a fulfillment state rather than strictly a payment event in itself.
Security deposit: a business requirement, not a payment type
A “security deposit” isn’t a Stripe object or a WooCommerce order status. It’s a business requirement: reserve a sum against possible damage, non-return, or no-show, and give it back if nothing goes wrong. Nothing in that requirement dictates how the money should move. It can be implemented as a captured payment that gets refunded, or as a hold that’s simply released. The requirement is the same; the mechanism is a separate decision.
Authorization hold: a reservation mechanism, not a transaction
An authorization hold, technically an uncaptured PaymentIntent with capture_method: manual, reserves an amount on the customer’s payment method without transferring it. Stripe’s own documentation describes it plainly: authorizing a payment guarantees the amount by holding funds on the customer’s payment method. No money moves at authorization time. Money only moves if and when the merchant explicitly captures it.
Method 1: Charge and refund
How it works in WooCommerce
The store charges the deposit amount as a normal payment at checkout (or as a separate order or fee), the charge is captured immediately, and the funds settle into the merchant’s account. If the deposit needs to be returned, the merchant issues a refund through WooCommerce or directly through the payment gateway. From the customer’s side, this is two distinct transactions: a charge, followed later by a refund.
Trade-offs
Recording a refund against an order is a native, built-in WooCommerce action, so that part requires no special setup. Whether that refund actually returns money to the customer automatically is a separate question: it depends on whether the connected payment gateway supports refunds through its own API (Stripe does) and has that capability properly configured. Without that, the store has to return the funds manually outside WooCommerce and record the refund after the fact so the order reflects reality.
On the customer-experience side, the trade-off is more consistent regardless of which path the refund takes: the customer’s card is charged the full deposit amount immediately, and getting that money back requires a completed refund, which itself takes time to reach the customer’s statement, typically several business days, depending on their card issuer. The deposit briefly reads as real spending on the customer’s account even when nothing goes wrong.
Method 2: Stripe authorization hold
Why it isn’t “charge now, refund later” under the hood
An authorization hold and a charge-then-refund sequence can look similar from a distance: in both cases, if all goes well, the customer ends up paying nothing extra. But the underlying mechanics differ. A charge is a completed transfer of funds, full stop; reversing it requires a second, separate transfer (the refund). A hold is not a transfer at all. Stripe’s PaymentIntent stays in a requires_capture state, with money set aside but not moved. Canceling it releases that reservation rather than reversing a completed transfer; Stripe’s own API documentation notes that for a PaymentIntent in requires_capture, canceling it means the remaining amount_capturable is automatically refunded on Stripe’s side, a technical release of the hold, not a customer-facing refund of settled spend. Exactly when that release shows up on the customer’s own statement can still depend on how their card issuer processes it, since that part happens outside Stripe.
Duration limits
An authorization hold is not indefinite. Stripe cancels uncaptured PaymentIntents automatically after a fixed window if the merchant doesn’t act, 7 days by default. The exact window depends on the payment method, the card network, and whether the transaction is card-present or card-not-present.
For online (card-not-present) transactions, Visa merchant-initiated authorizations run about 5 days while Visa, Mastercard, American Express and Discover customer-initiated authorizations run about 7 days. Card-present (terminal) transactions are shorter: about 5 days for Visa, about 2 days for Mastercard, American Express and Discover. Japan-based accounts get an exception, with JPY transactions on major networks held for up to 30 days. See the full breakdown in how long Stripe holds actually last.
If the merchant doesn’t capture or cancel before expiry, Stripe cancels the PaymentIntent automatically. In WooCommerce, the official Stripe extension reflects this by moving the order from “On hold” to “Failed” once the authorization lapses, and the held funds become available to the customer again, though they can no longer be captured.
Stripe also offers an extended-authorization option for certain eligible online and terminal use cases, which can lengthen this window beyond the default. It isn’t available across the board; eligibility depends on the payment method and use case, so it’s worth checking directly with Stripe if a business’s holding period regularly runs longer than a week.
Capture, partial capture and release
Once authorized, a PaymentIntent sits in requires_capture until the merchant takes action:
- Capture converts some or all of the authorized amount into an actual charge. The full authorized amount is captured by default; passing a smaller
amount_to_captureperforms a partial capture. - Stripe is explicit that a partial capture automatically releases the remaining amount. For most transactions, only one capture attempt is allowed per authorization (some card payments are eligible for Stripe’s multicapture feature, which permits more than one). This matches what WooCommerce’s own Stripe extension documentation states for its authorize-and-capture setting: you can only capture once per order.
- Release (canceling the PaymentIntent instead of capturing it) frees the entire hold with no charge ever created.
Side-by-side: charge-and-refund vs. authorization hold
| Charge and refund | Authorization hold | |
|---|---|---|
| Movement of funds | Funds transfer to the merchant at charge time, then transfer back at refund time: two separate money movements. | No funds move at authorization. Money only moves if the merchant captures. |
| Customer bank experience | A full charge appears, followed later by a separate refund line. | A pending authorization appears; if released without capture, the reservation is lifted without a separate refund transaction, though exactly when it disappears from the customer’s own statement can still depend on their bank. |
| Refund timing | The refund must be processed and typically takes several business days to reach the customer, depending on their card issuer. | Since no charge was ever settled, there is no refund to process on Stripe’s side when a hold is released, though the timing of when funds show as available again can still depend on the customer’s card issuer. |
| Authorization expiry | Not applicable: a completed charge doesn’t expire. | Expires automatically if not captured (network and method-dependent window, 7 days by default for most online card payments). |
| Partial capture | A captured charge can be partially refunded. | A partial capture is generally a one-time action; the uncaptured remainder is released automatically. |
| Typical use case | Deposits where funds need to settle immediately, or where the holding period may exceed a card’s authorization window. | Short-term rentals, bookings, and situations where the deposit is expected to be released, not spent, within about a week. |
Decision framework: which one fits your store
When a hold is the better fit
Authorization holds work well when the holding period is short and predictable: equipment rentals, short-term stays, event bookings, no-show protection, and when the store expects that, most of the time, nothing will need to be captured at all. The customer never sees a charge-then-refund round trip for a deposit that was never meant to be spent.
When charge-and-refund still makes sense
If the holding period is likely to exceed the authorization window (a multi-week rental, for example), or the store needs the deposit funds settled and available immediately rather than merely reserved, a captured charge with a refund on return is more predictable than repeatedly re-authorizing an expiring hold.
Constraints to check first
Before committing to either model, confirm two things. First, that the payment method in use actually supports separate authorization and capture: Stripe notes that cards and several wallets do, while ACH and iDEAL, among others, do not. Second, for stores serving customers in the European Economic Area, Strong Customer Authentication (SCA) requirements apply to card payments and may require 3D Secure authentication at confirmation time; this affects how and when a PaymentIntent can be confirmed, independently of whether it’s captured immediately or later.
What this means for developers
The Stripe objects involved
The core object is the PaymentIntent, created with capture_method: manual (or, for Checkout, payment_intent_data[capture_method] = manual). Authorizing the card moves its status to requires_capture, at which point amount_capturable reflects what’s available to capture. A capture request (optionally with amount_to_capture for a partial capture) moves it to succeeded; a cancel request releases it. The payment_intent.amount_capturable_updated webhook fires when an authorization completes, and it’s the natural trigger for updating order state.
Where this touches the WooCommerce order lifecycle
As noted earlier, WooCommerce’s own order-status documentation confirms that “On hold” is the status used when a gateway separates authorization from capture. Concretely: an order sits “On hold” while the PaymentIntent is requires_capture; a successful capture should move it to “Processing” or “Completed”; a canceled or expired authorization should move it to “Failed” or “Cancelled.” None of this state mapping happens automatically in WooCommerce core. A gateway integration (or custom code) has to listen for the relevant Stripe events and drive the order-status transitions itself.
What you’d need to build vs. what a plugin automates
Building this from scratch means creating PaymentIntents with manual capture, persisting the PaymentIntent ID against the WooCommerce order, exposing a capture or release action somewhere in the admin (or in the order-status transition itself), handling the webhook events that signal authorization, capture, and cancellation, and tracking the authorization’s expiry so the store doesn’t get caught by a hold lapsing unnoticed. A plugin built specifically for this generally wraps all of that into the standard WooCommerce order screen, so a store manager can capture or release a deposit without touching the Stripe Dashboard or writing code.
Implementation options
Stores have two realistic paths.
Custom implementation: a developer can integrate the Stripe API directly, creating manual-capture PaymentIntents, wiring up webhook handling, and building whatever admin interface the store needs. This gives full control over the deposit workflow but requires ongoing maintenance as Stripe’s API and WooCommerce’s order lifecycle evolve.
An existing plugin: several WooCommerce extensions, including the official WooCommerce Stripe Gateway’s own authorize-and-capture setting, and dedicated deposit-focused plugins, expose this workflow through the order admin without custom development. SecureHold WP is one example of a plugin built specifically around Stripe authorization holds for WooCommerce deposits, exposing capture, partial capture, and release directly from the order screen. It illustrates the pattern described above rather than replacing the need to understand it.
Which path makes sense depends on how central deposit handling is to the store’s operations, and how much control the development team wants over the exact behavior.
Related reading
For the mechanics behind each piece of this article, see:
- What Is a Stripe Authorization Hold?, the base definition and how it differs from a charge.
- Stripe Hold vs Charge: What’s the Difference?, a narrower technical comparison.
- How Stripe Pre-Authorization Works, the full authorization lifecycle, step by step.
- How Long Does a Stripe Authorization Hold Last?, a deeper look at expiration timing.
- How to Capture or Release a Stripe Authorization Hold in WooCommerce, the practical, step-by-step guide.
- Stripe Security Deposit vs Traditional Deposit, the customer-experience angle in more depth.
FAQ
-
Does an uncaptured authorization show up as revenue in WooCommerce reports?
No. Since the order sits in "On hold" rather than "Processing" or "Completed," and no charge has been captured, it does not get counted as completed revenue. Reporting reflects the captured amount, not the authorized amount. -
Can a store combine both models on the same order, for example charging for the product and holding for the deposit?
Yes, conceptually. Nothing prevents charging one PaymentIntent immediately for the purchase while creating a second, separate manual-capture PaymentIntent for the deposit portion. The two are independent objects with independent lifecycles. -
What happens if the store tries to capture after the authorization window has already closed?
The capture request only works while the PaymentIntent is still in a capturable state. Once the authorization has expired, Stripe has already canceled it automatically, so the capture attempt returns an error, since there is no held amount left to convert into a payment. At that point the merchant needs to request a new payment from the customer rather than retry the capture. -
Do authorization holds work the same way for recurring or subscription-based bookings?
Not directly. Authorize-then-capture, as described here, is built around a single reservation-and-settle cycle per PaymentIntent. Recurring billing in Stripe runs through separate Subscription and Invoicing tooling that creates its own payment collection for each cycle, rather than re-using one held authorization across multiple charges. -
Does the customer's bank distinguish a hold from a captured charge on their statement?
Not always clearly. Some card issuers and payment interfaces do not distinguish between authorizations and captured (settled) payments, which can sometimes make a pending hold look, at a glance, like an actual charge to the customer.

