# Capture a payment multiple times

Capture a PaymentIntent multiple times, up to the authorized amount.

# Advanced integration


Multicapture allows you to [capture a PaymentIntent](https://docs.stripe.com/api/payment_intents/capture.md) multiple times for a single authorization, 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 fulfill 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

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 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 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 installment 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 with a professional if you’re unsure about your obligations.

## Create and confirm an uncaptured PaymentIntent

To indicate that you want separate authorization 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 authorization 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 "<<YOUR_SECRET_KEY>>:" \
  -d amount=1000 \
  -d currency=usd \
  -d payment_method=pm_card_visa \
  -d confirm=true \
  -d capture_method=manual \
  --data-urlencode "return_url=https://example.com/return" \
  -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 authorized.

> #### 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.

```curl
curl https://api.stripe.com/v1/payment_intents/pi_xxx/capture \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d amount_to_capture=700 \
  -d final_capture=false \
  -d "expand[]=latest_charge"
```

In the `PaymentIntent` 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 authorization 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 "<<YOUR_SECRET_KEY>>:" \
  -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 performed at least one capture and want to release the remaining uncaptured funds, set the amount to `0` and set `final_capture` to `true`.

```curl
curl https://api.stripe.com/v1/payment_intents/pi_xxx/capture \
  -u "<<YOUR_SECRET_KEY>>:" \
  -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 expiration 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 authorization window to reverse the authorization 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 authorization 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.

