Private preview
Capture a payment multiple times Private preview
Capture a card-present payment multiple times, up to the authorized amount.
Multicapture lets you capture a card-present PaymentIntent multiple times, up to the full authorized amount. You can use this to authorize a total amount and capture funds as you fulfill part of the order.
IC+ feature
We offer multicapture to users on IC+ pricing. If you’re on standard Stripe pricing and want access to this feature, contact us using the form at Stripe support.
Interested in getting early access to multicapture on Terminal?
Enter your email to request access.
Availability
When using multicapture on Terminal, be aware of the following requirements:
- It only applies to card _ present payments. Learn more about online card payments support .
- Use capture_method set to manual . Multicapture requires manual capture so that you can perform multiple partial captures on the PaymentIntent.
- It’s available on American Express, Cartes Bancaires, Diners Club, Discover, Japan Credit Bureau (JCB), Mastercard, and Visa.
- Multicapture isn’t supported for separate charges and transfers fund flows using source_transaction .
JCB multicapture is only available in Australia, Canada, New Zealand, and the United States.
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
- Multicapture on Terminal adheres to the card-present authorization validity windows. The card-present authorization validity window can be shorter than for online payments (card-not-present). Make sure to capture the payment within the authorization validity window, to prevent the funds from releasing and the payment status changing to canceled. If you use the API, the payment_method_details.card.capture_before attribute on the charge indicates when the authorization expires.
- When using multicapture to send separate shipments for one order, proactively notify your customer with the details of each shipment. This can avoid inquiries 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 you comply with all applicable rules, which vary by network.
Request multicapture support Client-side Server-side
When creating or updating a PaymentIntent, you can request the ability to multicapture. Set the payment_method_options.card_present.request_multicapture to if_available and the capture_method to manual.
Command Line
Select a language
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
You can also provide request_multicapture when confirming the PaymentIntent.
Check eligibility after confirmation Client-side
Confirm the PaymentIntent and verify payment_method_details.card_present.multicapture.status on the latest_charge to determine if multicapture is available for that payment.
{
"id": "pi_xxx",
"status": "requires_capture",
"latest_charge": {
"id": "ch_xxx",
"payment_method_details": {
"type": "card_present",
"card_present": {
"multicapture": {
"status": "available"
}
}
}
}
}
Not all PaymentIntents are eligible for multicapture. If the status is unavailable, use a single capture as usual.
Capture the PaymentIntent Server-side
For a PaymentIntent in the requires_capture state where multicapture.status is available, you can capture part of the authorized amount by setting the amount_to_capture to the desired amount and final_capture to false. Instruct Stripe not to release the remaining uncaptured funds by setting final_capture to false.
Note
Stripe allows up to 50 non-final captures for a single PaymentIntent. You can then perform one additional final capture to complete the payment.
Command Line
Select a language
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
Each partial capture updates the PaymentIntent fields:
- amount _ capturable decreases
- amount _ received increases
- status remains requires _ capture until final capture
Final capture Server-side
To complete the payment and release any remaining uncaptured amount, set final_capture to true. You can also omit it, because true is the default.
Command Line
Select a language
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
After final capture, the PaymentIntent transitions to succeeded.
Optional Release uncaptured funds Server-side
Testing
You can test multicapture for card-present payments in a sandbox. Set the payment_method_options.card_present.request_multicapture to if_available, and verify the multicapture.status after confirmation before attempting partial captures.
Refunds
For a PaymentIntent in requires_capture state, you can refund any number of times up to the total captured amount minus the total refunded amount, which is the amount_received — amount_refunded. The charge.refunded field transitions to true only when the final capture has been performed and the entire amount_received is refunded.
Stripe doesn’t support partial refunds with refund_application_fee=true or reverse_transfer=true. Instead, you can perform partial fee refunds by manually performing partial fee refunds and transfer reversals using the application fee refund and transfer reversal 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 with the source_transaction parameter. The application_fee_amount and 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 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 and transfer reversal endpoints.
Webhooks
Charge updated webhooks
We send a 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.
// 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 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.
// 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 event for final captures or at the end of the authorization window to reverse the authorization of the uncaptured amount. The captured field for a charge only becomes true after a final capture or authorization reversal.
For example, if we do a capture with amount=0 and final_capture=true, the captured attribute on the charge changes from false to true.
// 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 event. For connected accounts, we also send application_fee.refunded events when we refund application fees and transfer.reversed events when we reverse transfers.
