Place a hold on a card Payment Intents API

Separate authorization and capture to create a charge now, but capture funds later.

Place a hold on a card to reserve funds now but only capture them after your business completes the service. For example, a hotel may authorize a payment in full prior to a guest’s arrival, then move the money when the guest checks out.

When a payment is authorized, the bank guarantees the amount and holds it on the customer’s card for up to seven days. If the payment is not captured in this time, the payment and authorization are both canceled, and the funds are released.

For in-person payments made with Terminal, the PaymentIntent must be captured within 24 hours.

1 Tell Stripe to authorize only

To indicate that you want separate authorization and capture, set the value of capture_method option to manual when creating the PaymentIntent. This parameter instructs Stripe to only authorize the amount on the customer’s card.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1099 \ -d currency=usd \ -d "payment_method_types[]"=card \ -d capture_method=manual
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'usd', payment_method_types: ['card'], capture_method: 'manual', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1099, currency='usd', payment_method_types=['card'], capture_method='manual', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1099, 'currency' => 'usd', 'payment_method_types' => ['card'], 'capture_method' => 'manual', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("usd") .addPaymentMethodType("card") .setCaptureMethod(PaymentIntentCreateParams.CaptureMethod.MANUAL) .build(); PaymentIntent paymentIntent = PaymentIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'usd', payment_method_types: ['card'], capture_method: 'manual', });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(stripe.CurrencyUSD)), PaymentMethodTypes: stripe.StringSlice([]string{ "card", }), CaptureMethod: stripe.String(string(stripe.PaymentIntentCaptureMethodManual)), } pi, _ := paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "usd", PaymentMethodTypes = new List<string> { "card", }, CaptureMethod = "manual", }; var service = new PaymentIntentService(); var intent = service.Create(options);

2 Capture the funds

After the card is authorized, the PaymentIntent status will transition to requires_capture. To capture the authorized funds, make a PaymentIntent capture request. The total authorized amount is captured by default—you can’t capture more than this. To capture less than the initial amount, pass the amount_to_capture option. Partially capturing automatically releases the remaining amount.

The following example demonstrates how to capture $7.50 of the authorized $10.99 payment:

curl https://api.stripe.com/v1/payment_intents/pi_WKReqv2eudWAgBxXXD2h/capture \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount_to_capture=750
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.capture( 'pi_WKReqv2eudWAgBxXXD2h', { amount_to_capture: 750, } )
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = stripe.PaymentIntent.capture( 'pi_WKReqv2eudWAgBxXXD2h', amount_to_capture=750 )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $intent = \Stripe\PaymentIntent::retrieve('pi_WKReqv2eudWAgBxXXD2h'); $intent->capture(['amount_to_capture' => 750]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntent intent = PaymentIntent.retrieve("pi_WKReqv2eudWAgBxXXD2h"); PaymentIntentCaptureParams params = PaymentIntentCaptureParams.builder() .setAmountToCapture(750L) .build(); paymentIntent.capture(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const intent = await stripe.paymentIntents.capture('pi_WKReqv2eudWAgBxXXD2h', { amount_to_capture: 750, })
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentCaptureParams{ AmountToCapture: stripe.Int64(750), } pi, _ := paymentintent.Capture("pi_WKReqv2eudWAgBxXXD2h", params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PaymentIntentCaptureOptions { AmountToCapture = 750, }; var service = new PaymentIntentService(); var paymentIntent = service.Capture("pi_WKReqv2eudWAgBxXXD2h", options);

Authorized payments can only be captured once. If you partially capture a payment, you cannot perform another capture for the difference. Depending on your requirements, you may be better served by saving customer’s card details for later and creating future payments as needed.

Card statements from some issuers do not distinguish between authorizations and captured (settled) payments, which can sometimes confuse customers.

Additionally, when a customer completes the payment process on a PaymentIntent with manual capture, it triggers the payment_intent.amount_capturable_updated event. You can inspect the PaymentIntent’s amount_capturable property to see the total amount that can be captured from the PaymentIntent.

Optional Cancel the authorization

If you need to cancel an authorization, you can cancel the PaymentIntent.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.
You can unsubscribe at any time. Read our privacy policy.