# Capture a payment multiple times Capture a PaymentIntent multiple times, up to the authorised amount. # Advanced integration Multicapture allows you to [capture a PaymentIntent](https://docs.stripe.com/api/payment_intents/capture.md) multiple times for a single authorisation, up to the full [amount of the PaymentIntent](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount). You can use it when you have orders with multiple shipments, and want to capture funds as you fulfil parts of the order. > #### IC+ feature > > Multicapture is part of the functionality we offer to users on *IC+ pricing* (A pricing plan where businesses pay the variable network cost for each transaction plus the Stripe fee rather than a flat rate for all transactions. This pricing model provides more visibility into payments costs). If you’re on blended Stripe pricing and want access to this feature, contact us using the form at [Stripe support](https://support.stripe.com). ## Availability When using multicapture, be aware of the following restrictions: - It only supports online card payments - Use [capture_method](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-capture_method) set to `manual`. Multicapture requires manual capture so that you can perform multiple partial captures on the PaymentIntent. - It’s available with Amex, Visa, Discover, Mastercard, Cartes Bancaires, Diners Club, China UnionPay (CUP), and Japan Credit Bureau (JCB) - [Separate charges and transfers](https://docs.stripe.com/connect/separate-charges-and-transfers.md) fund flows using [source_transaction](https://docs.stripe.com/api/transfers/create.md#create_transfer-source_transaction) aren’t supported - Stripe allows you to capture up to 50 times for a single [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) > #### CUP and JCB support > > CUP multicapture is only available in the United States. JCB multicapture is only available in the United States, Canada, Australia, and New Zealand. > #### Automatic capture methods > > The API currently accepts `request_multicapture="if_available"` when `capture_method` is set to `automatic` or `automatic_async` without returning an error. In this case, `multicapture.status` on the charge may show `available`, but you can’t perform multiple captures because the PaymentIntent is automatically captured in full. Always set `capture_method` to `manual` when you intend to use multicapture. A future API version may return a validation error for this combination. ## Best practices When sending separate shipments for one order, proactively notify your end customer with the details of each shipment. Doing so avoids enquiries and chargebacks from customers because of confusion with seeing multiple transactions on their bank statement. Use the following best practices when notifying customers: - Inform them of the estimated delivery date and transaction amount for each shipment at the time of checkout, before purchase. - Notify them upon each shipment, along with the transaction amount. - Disclose your full refund and cancellation policy. > #### Compliance > > You’re responsible for your compliance with all applicable laws, regulations, and network rules when using multicapture. Consult the rules for the card networks that you want to use this feature with to make sure your sales comply with all applicable rules, which vary by network. For example, most card networks restrict multicapture usage to card-not-present transactions for the sale of goods that ship separately. Certain card networks permit multicapture for businesses based on their industry (for example, travel), while some don’t permit multicapture for instalment or deposit workflows. > > The information provided on this page relating to your compliance with these requirements is for your general guidance, and isn’t legal, tax, accounting, or other professional advice. Consult a professional if you’re unsure about your obligations. ## Create and confirm an uncaptured PaymentIntent To indicate that you want separate authorisation and capture, specify the [capture_method](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-capture_method) as `manual` when creating the PaymentIntent. To learn more about separate authorisation and capture, see [how to place a hold on a payment method](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md). Use the `if_available` or `never` parameters to request multicapture for this payment. - `if_available`: The created PaymentIntent will allow multiple captures, if the payment method supports it. - `never`: The created PaymentIntent won’t allow for multiple captures. ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1000 \ -d currency=usd \ -d "payment_method_types[]=card" \ -d payment_method=pm_card_visa \ -d confirm=true \ -d capture_method=manual \ -d "expand[]=latest_charge" \ -d "payment_method_options[card][request_multicapture]=if_available" ``` In the response, the `payment_method_details.card.multicapture.status` field on the [latest_charge](https://docs.stripe.com/api/charges/object.md) contains `available` or `unavailable` based on the customer’s payment method. ```json // PaymentIntent Response { "id": "pi_xxx", "object": "payment_intent","amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded "latest_charge": { "id": "ch_xxx", "object": "charge","amount": 1000, "amount_captured": 0, "amount_refunded": 0, "payment_method_details": { "card": { "multicapture": {"status": "available" // or "unavailable" } } } ... } ... } ``` ## Capture the PaymentIntent For a PaymentIntent in a [requires_capture state](https://docs.stripe.com/payments/paymentintents/lifecycle.md) where multicapture is `available`, specifying the optional `final_capture` parameter to be `false` tells Stripe not to release the remaining uncaptured funds when calling the capture API. For example, if you confirm a 10 USD payment intent, capturing 7 USD with `final_capture=false` keeps the remaining 3 USD authorised. ```curl curl https://api.stripe.com/v1/payment_intents/pi_xxx/capture \ -u "<>:" \ -d amount_to_capture=700 \ -d final_capture=false \ -d "expand[]=latest_charge" ``` In the PI capture response, the [amount_capturable](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_capturable) and [amount_received](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_received) fields update accordingly. ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent","amount": 1000, "amount_capturable": 300, // 1000 - 700 = 300 "amount_received": 700, // if latest_charge is expanded "latest_charge": { "id": "ch_xxx", "object": "charge","amount": 1000, "amount_captured": 700, "amount_refunded": 0, ... } ... } ``` ## Final capture The PaymentIntent remains in a `requires_capture` state until you do one of the following: - Set `final_capture` to `true`. - Make a capture without the `final_capture` parameter (because `final_capture` defaults to `true`). - The authorisation window expires. At this point, Stripe releases any remaining funds and transitions the PaymentIntent to a `succeeded` state. ```curl curl https://api.stripe.com/v1/payment_intents/pi_xxx/capture \ -u "<>:" \ -d amount_to_capture=200 \ -d final_capture=true \ -d "expand[]=latest_charge" ``` In the PI capture response, the [amount_capturable](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_capturable) and [amount_received](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_received) fields will be updated accordingly. ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent","amount": 1000, "amount_capturable": 0, // not 100 due to final_capture=true "amount_received": 900, // 700 + 200 = 900 // if latest_charge is expanded "latest_charge": { "id": "ch_xxx", "object": "charge","amount": 1000, "amount_captured": 900, "amount_refunded": 0, ... } ... } ``` Uncaptured PaymentIntents transition to `canceled`, while partially captured PaymentIntents transition to `succeeded`. ## Optional: Release uncaptured funds If you want to release the uncaptured funds for a partially captured payment, set the amount to 0 and set `final_capture` to `true`. ```curl curl https://api.stripe.com/v1/payment_intents/pi_xxx/capture \ -u "<>:" \ -d amount_to_capture=0 \ -d final_capture=true ``` This transitions the PaymentIntent to `succeeded` and releases any uncaptured funds back to the cardholder. ## Test your integration Use a Stripe test card with any CVC, postal code, and future expiry date to test multicapture payments. | Number | Payment Method | Description | | ---------------- | ---------------------------------------------- | -------------------------------------------------------------- | | 4242424242424242 | `pm_card_visa` | Visa test card that supports multicapture. | | 4000002500001001 | `pm_card_visa_cartesBancaires` | Cartes Bancaires or Visa test card that supports multicapture. | | 4000008400000076 | `pm_card_credit_disableEnterpriseCardFeatures` | Visa test card that doesn’t support multicapture. | ## Refunds For a PaymentIntent in `requires_capture` state, you can [refund](https://docs.stripe.com/api/refunds.md) any number of times up to the total captured amount minus the total refunded amount, which is the [amount_received](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_received) - [amount_refunded](https://docs.stripe.com/api/charges/object.md#charge_object-amount_refunded). The [charge.refunded](https://docs.stripe.com/api/charges/object.md#charge_object-refunded) field transitions to `true` only when the final capture has been performed and the entire [amount_received](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount_received) is refunded. Stripe doesn’t support *partial refunds* (A partial refund is any refund in which less than the remaining refundable amount is refunded in a single request. The remaining refundable amount is the payment_intent.amount_received - charge.amount_refunded) with [refund_application_fee=true](https://docs.stripe.com/api/refunds/create.md#create_refund-refund_application_fee) or [reverse_transfer=true](https://docs.stripe.com/api/refunds/create.md#create_refund-reverse_transfer). Instead, you can perform partial fee refunds by manually performing partial fee refunds and transfer reversals using the [application fee refund](https://docs.stripe.com/api/fee_refunds.md) and [transfer reversal](https://docs.stripe.com/api/transfer_reversals.md) endpoints. After using the application fee refund or transfer reversal endpoints, Stripe doesn’t support any further refunds with `refund_application_fee=true` or `reverse_transfer=true` respectively. ## Connect Multicapture supports all Connect use cases, with the exception of [Separate Charges and Transfers](https://docs.stripe.com/connect/separate-charges-and-transfers.md) with the [source_transaction](https://docs.stripe.com/api/transfers/create.md#create_transfer-source_transaction) parameter. The [application_fee_amount](https://docs.stripe.com/api/payment_intents/capture.md#capture_payment_intent-application_fee_amount) and [transfer_data[amount]](https://docs.stripe.com/api/payment_intents/capture.md#capture_payment_intent-transfer_data-amount) parameters have some additional validations. Consider the following validations when implementing multicapture with Connect: - Setting `application_fee_amount` or `transfer_data[amount]` on the first capture makes it required for all subsequent captures. Each `application_fee_amount` and `transfer_data[amount]` passed at capture time overrides the values passed in on PaymentIntent creation, confirmation, and update. - Stripe doesn’t support *partial refunds* (A partial refund is any refund in which less than the remaining refundable amount is refunded in a single request. The remaining refundable amount is the payment_intent.amount_received - charge.amount_refunded) on multicapture payments with refund_application_fee=true or reverse_transfer=true. You can perform partial fee refunds or transfer reversals using the [application fee refund](https://docs.stripe.com/api/fee_refunds.md) and [transfer reversal](https://docs.stripe.com/api/transfer_reversals.md) endpoints. ## Webhooks ### Charge updated webhooks We send a [charge.updated](https://docs.stripe.com/api/events/types.md#event_types-charge.updated) webhook each time you capture a payment. For example, on the first capture of a destination charge multicapture payment with an `application_fee_amount`, we update these fields from empty to non-empty values. ```json // charge.updated { "data": { "id": "ch_xxx", "object": "charge", "amount": 1000,"balance_transaction": "txn_xxx", // applicable to all charges "transfer": "tr_xxx", // applicable to destination charges only "application_fee": "fee_xxx", // applicable to Connect only ... }, "previous_attributes": {"balance_transaction": null, // applicable to all charges "transfer": null, // applicable to destination charges only "application_fee": null, // applicable to Connect only } } ``` ### payment_intent.amount_capturable_updated We send [payment_intent.amount_capturable_updated](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.amount_capturable_updated) on every capture, regardless of `amount_to_capture` and `final_capture` values. For example, if we capture 1 USD from a PaymentIntent with an amount of 10 USD, the PaymentIntent’s amount_capturable field updates to 9 USD. ```json // payment_intent.amount_capturable_updated { "data": { "id": "pi_xxx", "object": "payment_intent", "amount": 1000,"amount_capturable": 900 // 1000 - 100 = 900 ... }, "previous_attributes": {"amount_capturable": 1000 } } ``` ### Charge captured events We send a [charge.captured](https://docs.stripe.com/api/events/types.md#event_types-charge.captured) event for final captures or at the end of the authorisation window to reverse the authorisation of the uncaptured amount. The [captured](https://docs.stripe.com/api/charges/object.md#charge_object-captured) field for a charge only becomes `true` after a final capture or authorisation reversal. For example, if we do a capture with `amount=0` and `final_capture=true`, the [captured](https://docs.stripe.com/api/charges/object.md#charge_object-captured) attribute on the charge changes from false to true. ```json // charge.captured { "data": { "id": "ch_xxx", "object": "charge","captured": true ... }, "previous_attributes": {"captured": false } } ``` ### Refund webhooks Multicapture refund webhooks are no different than non-multicapture refund webhooks. During each partial refund, we send a [refund.created](https://docs.stripe.com/api/events/types.md#event_types-refund.created) event. For connected accounts, we also send [application_fee.refunded](https://docs.stripe.com/api/events/types.md#event_types-application_fee.refunded) events when we refund application fees and [transfer.reversed](https://docs.stripe.com/api/events/types.md#event_types-transfer.reversed) events when we reverse transfers.