Place a hold on a card

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

    Overview

    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 want to 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 funds are guaranteed by the card issuer and the amount is held on the customer’s card for up to seven days. If the payment is not captured within this time, the PaymentIntent and authorization are both canceled and 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 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 change this 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 change this 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 change this 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 change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    paymentintentParams.put("capture_method", "manual");
    
    PaymentIntent.create(paymentintentParams);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        capture_method: 'manual',
      });
    })();
    
    // Set your secret key: remember to change this 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("manual"),
    }
    paymentintent.New(params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCreateOptions
    {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" },
      CaptureMethod = "manual",
    };
    var intent = service.Create(options);
    

    2 Capture the funds

    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_Y4U008uFiUxB6U9aQPHr/capture \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount_to_capture=750
    
    # Set your secret key: remember to change this 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_Y4U008uFiUxB6U9aQPHr',
      {
        amount_to_capture: 750,
      }
    )
    
    # Set your secret key: remember to change this 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_Y4U008uFiUxB6U9aQPHr',
      amount_to_capture=750
    )
    
    // Set your secret key: remember to change this 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_Y4U008uFiUxB6U9aQPHr');
    $intent->capture(['amount_to_capture' => 750]);
    
    // Set your secret key: remember to change this 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_Y4U008uFiUxB6U9aQPHr");
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount_to_capture", 750);
    intent.capture(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      await stripe.paymentIntents.capture('pi_Y4U008uFiUxB6U9aQPHr', {
        amount_to_capture: 750,
      })
    })();
    
    // Set your secret key: remember to change this 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),
    }
    intent, err := paymentintent.Capture("pi_Y4U008uFiUxB6U9aQPHr", params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCaptureOptions
    {
      AmountToCapture = 750,
    };
    var intent = service.Capture("pi_Y4U008uFiUxB6U9aQPHr", 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?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page