Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
Overview
About Stripe payments
Upgrade your integration
Payments analytics
Online payments
OverviewFind your use caseManaged Payments
Use Payment Links
Build a checkout page
Build an advanced integration
Build an in-app integration
Payment methods
Add payment methods
Manage payment methods
Faster checkout with Link
Payment interfaces
Payment Links
Checkout
Web Elements
In-app Elements
Payment scenarios
Handle multiple currencies
Custom payment flows
Flexible acquiring
    Overview
    Capture a payment multiple times
    Capture more than the authorized amount on a payment
    Place an extended hold on an online card payment
    Increment an authorization
    Partially authorize a payment
    Migrate from beta
Orchestration
In-person payments
Terminal
Beyond payments
Incorporate your company
Crypto
Financial Connections
Climate
HomePaymentsFlexible acquiring

Place an extended hold on an online card payment

Learn how to use extended authorizations to capture online card payments up to 30 days after authorization.

Extended authorizations have a longer authorization validity period, which allows you to hold customer funds for longer than standard authorization validity windows. For most card networks, the default authorization validity period is 7 days for online payments and 2 days for in-person Terminal payments, whereas extended validity periods can go up to 30 days depending on the card network. For more information about authorization validity windows, see place a hold on a payment method.

Availability

When you use extended authorizations, there are no regional restrictions. However, be aware of the following limitations:

  • They’re only available with Visa, Mastercard, American Express, and Discover.
  • Certain card brands have merchant category restrictions. Refer to the network availability table below.
  • This page describes extended authorizations for online card payments. For in-person card payments using extended authorizations, refer to the Terminal documentation.
  • mode is set to payment and capture_method is set to manual on the CheckoutSession.

IC+ Feature

We offer extended authorizations to users on IC+ pricing. If you’re on blended Stripe pricing and want access to this feature, contact us at support.stripe.com.

Availability by card network and merchant category

Every card network has different rules that determine which payments have extended authorizations available, and how long they’re valid. The following table shows the validity windows and transaction types that extended authorization is available for using Visa, Mastercard, American Express, and Discover. However, we recommend that you rely on the capture_before field to confirm the validity window for any given payment because these rules can change without prior notice.

Card brand Merchant category Extended authorization validity window

Visa

Hotel, lodging, vehicle rental, and cruise line

All other merchant categories*

30 days**

Mastercard (not including Maestro and Cirrus cards)All merchant categories30 days
American ExpressLodging and vehicle rental30 days***
DiscoverAirline, bus charter/tour, car rental, cruise line, local/suburban commuter, passenger transportation including ferries, hotel, lodging, and passenger railway30 days

* For other merchant categories, Stripe charges an additional 0.08% fee per transaction. The extended window only applies to Customer-Initiated Transactions and doesn’t apply to transactions with merchants in JP.
** The exact extended authorization window for Visa is 29 days and 18 hours, to allow time for clearing processes.
*** Although your validity window is extended to 30 days, you must capture the authorized funds no later than the end of your customer’s stay or rental.

Networks with limited support (beta)

Recent changes to availability

Best Practices

Customers see their funds held longer when you use extended authorizations. Use clear statement descriptors to avoid increased disputes from unrecognized payments.

You can use the custom_text field when creating a new CheckoutSession to display additional text on the checkout page to help meet compliance requirements.

Compliance

You’re responsible for your compliance with all applicable laws, regulations, and network rules when using extended authorization. Consult the network specifications for the card networks that you plan to accept using this feature with to make sure your sales are compliant with the applicable rules, which vary by network. For instance, for many networks extended validity windows are only for cases where you don’t know the final amount that you’ll capture at the time of authorization.

The information provided on this page relating to your compliance with these requirements is for your general guidance, and is not legal, tax, accounting, or other professional advice. Consult with a professional if you’re unsure about your obligations.

Create a CheckoutSession

From your server, create a Checkout Session and set the ui_mode to embedded. You can configure the Checkout Session with line items to include, and options such as currency.

To return customers to a custom page that you host on your website, specify that page’s URL in the return_url parameter. Include the {CHECKOUT_SESSION_ID} template variable in the URL to retrieve the session’s status on the return page. Checkout automatically substitutes the variable with the Checkout Session ID before redirecting.

Read more about configuring the return page and other options for customizing redirect behavior.

After you create the Checkout Session, use the client_secret returned in the response to mount Checkout.

To enable the extended authorization feature, set request_extended_authorization to if_available.

Ruby
# This example sets up an endpoint using the Sinatra framework. # To learn more about Sinatra, watch this video: https://youtu.be/8aA9Enb8NVc. require 'json' require 'sinatra' require 'stripe' # Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
post '/create-checkout-session' do session = Stripe::Checkout::Session.create({ line_items: [{ price_data: { currency: 'usd', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], mode: 'payment', ui_mode: 'embedded', payment_method_options: { card: { request_extended_authorization: 'if_available', }, }, return_url: 'https://example.com/checkout/return?session_id={CHECKOUT_SESSION_ID}' }) {clientSecret: session.client_secret}.to_json end

Rely on the capture_before field to confirm the validity window for a given payment. The validity window won’t change after the CheckoutSession is complete. To determine if the authorization is extended after the CheckoutSession is complete, look at the extended_authorization.status field on the associated Charge.

{ "id": "pi_xxx", "object": "payment_intent", "amount": 1000, "amount_capturable": 1000, "amount_received": 0, "status": "requires_capture", ... // if latest_charge is expanded "latest_charge": { "id": "ch_xxx", "object": "charge", "payment_method_details": { "card": { "amount_authorized": 1000, "capture_before": 1696524701, "extended_authorization": { "status": "enabled", // or "disabled" } } } ... } ... }

Mount Checkout

Checkout is available as part of Stripe.js. Include the Stripe.js script on your page by adding it to the head of your HTML file. Next, create an empty DOM node (container) to use for mounting.

index.html
<head> <script src="https://js.stripe.com/basil/stripe.js"></script> </head> <body> <div id="checkout"> <!-- Checkout will insert the payment form here --> </div> </body>

Initialize Stripe.js with your publishable API key.

Create an asynchronous fetchClientSecret function that makes a request to your server to create the Checkout Session and retrieve the client secret. Pass this function into options when you create the Checkout instance:

index.js
// Initialize Stripe.js const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); initialize(); // Fetch Checkout Session and retrieve the client secret async function initialize() { const fetchClientSecret = async () => { const response = await fetch("/create-checkout-session", { method: "POST", }); const { clientSecret } = await response.json(); return clientSecret; }; // Initialize Checkout const checkout = await stripe.initEmbeddedCheckout({ fetchClientSecret, }); // Mount Checkout checkout.mount('#checkout'); }

Checkout renders in an iframe that securely sends payment information to Stripe over an HTTPS connection.

Common mistake

Avoid placing Checkout within another iframe because some payment methods require redirecting to another page for payment confirmation.

Customize appearance

Customize Checkout to match the design of your site by setting the background color, button color, border radius, and fonts in your account’s branding settings.

By default, Checkout renders with no external padding or margin. We recommend using a container element such as a div to apply your desired margin (for example, 16px on all sides).

Show a return page

After your customer attempts payment, Stripe redirects them to a return page that you host on your site. When you created the Checkout Session, you specified the URL of the return page in the return_url parameter. Read more about other options for customizing redirect behavior.

When rendering your return page, retrieve the Checkout Session status using the Checkout Session ID in the URL. Handle the result according to the session status as follows:

  • complete: The payment succeeded. Use the information from the Checkout Session to render a success page.
  • open: The payment failed or was canceled. Remount Checkout so that your customer can try again.
Ruby
get '/session-status' do session = Stripe::Checkout::Session.retrieve(params[:session_id]) {status: session.status, customer_email: session.customer_details.email}.to_json end
client.js
const session = await fetch(`/session_status?session_id=${session_id}`) if (session.status == 'open') { // Remount embedded Checkout } else if (session.status == 'complete') { // Show success page // Optionally use session.payment_status or session.customer_email // to customize the success page }

Redirect-based payment methods

During payment, some payment methods redirect the customer to an intermediate page, such as a bank authorization page. When they complete that page, Stripe redirects them to your return page.

Learn more about redirect-based payment methods and redirect behavior.

Test your integration

Use the Stripe test cards below with any CVC and future expiration date to request extended authorizations while testing. If extended authorizations are available on payments for a given network while testing, they’re also available for live payments.

Card brandNumberPayment method
Visapm_card_visa
Mastercardpm_card_mastercard
Amexpm_card_amex
Discoverpm_card_discover

See also

  • Place a hold on a payment method
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access program.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc