# Migrate to the latest flexible payment scenarios Adapt your beta advanced payment scenarios to the general release. Stripe now supports several flexible payment scenarios for non-card-present transactions. If you’ve already integrated the private beta version of any of these features, this guide provides details to upgrade to the general release. For new integrations, use the following guides for the features that interest you: - [Increment an Authorisation](https://docs.stripe.com/payments/incremental-authorization.md) - [Capture more than the Authorised Amount](https://docs.stripe.com/payments/overcapture.md) - [Place an Extended Hold on an Online Card Payment](https://docs.stripe.com/payments/extended-authorization.md) - [Capture a Payment Multiple Times](https://docs.stripe.com/payments/multicapture.md) We’ve incorporated the following feedback-driven improvements to these features: - Detailed control over the features at the *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) level. - Clearer expectations regarding feature availability and usage after a *confirmation* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) phase. Each of the flexible payment features has different requirements from its private beta integration. Choose the feature you need to upgrade and refer to the note at the top for changes and requirements specific to that feature. # Incremental authorisation > This is a Incremental authorisation for when flex-payment-features is incremental-auth. View the full page at https://docs.stripe.com/payments/flexible-features-migration?flex-payment-features=incremental-auth. > #### Changes from beta > > The first step of this integration is now mandatory. ## Request incremental authorisation Your *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) must include a request for incremental authorisation before confirmation. > This formerly optional step is now mandatory. ### Before ```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_debit_incrementalAuthAuthorized \ -d confirm=true \ -d capture_method=manual \ -d "expand[]=latest_charge" \ -d "payment_method_options[card][request_incremental_authorization_support]=true" ``` ### After ```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_debit_incrementalAuthAuthorized \ -d confirm=true \ -d capture_method=manual \ -d "expand[]=latest_charge" \ -d "payment_method_options[card][request_incremental_authorization]=if_available" ``` The response now returns the status of the incremental authorisation request in the `payment_method_details.card.incremental_authorization.status` property of the [latest_charge](https://docs.stripe.com/api/charges/object.md). The status values is `available` or `unavailable` depending on the customer’s payment method. ### Before ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent", "amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded { "latest_charge": { "amount": 1000, "payment_method_details": { "card": {"incremental_authorization_supported": true // or false } } ... } } } ``` ### After ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent", "amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded { "latest_charge": { "amount": 1000, "payment_method_details": { "card": { "incremental_authorization": {"status": "available" // or "unavailable" } } } ... } } } ``` ## Incrementally modify the authorised amount **No changes have been made to this step in comparison to the beta version.** ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/increment_authorization \ -u "<>:" \ -d amount=1500 ``` # Overcapture > This is a Overcapture for when flex-payment-features is overcapture. View the full page at https://docs.stripe.com/payments/flexible-features-migration?flex-payment-features=overcapture. > #### Changes from beta > > The first step of this integration didn’t previously exist, but is now mandatory. ## Request overcapture Your *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) must include a request for overcapture before confirmation. The private beta integration for overcapture didn’t include this step because the request parameter didn’t exist. ```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_overcapture]=if_available" ``` The response returns the status of the overcapture request in the `payment_method_details.card.overcapture.status` property of the [latest_charge](https://docs.stripe.com/api/charges/object.md). The status values is `available` or `unavailable` depending on the customer’s payment method. ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent", "amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded { "latest_charge": { "amount": 1000, "payment_method_details": { "card": { "overcapture": {"status": "available", // or "unavailable" "maximum_amount_capturable": 1200 } } } ... } } } ``` ## Capture more than the authorised amount To capture more than the currently authorised amount on a *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process), use the [capture](https://docs.stripe.com/api/payment_intents/capture.md) endpoint and provide an [amount_to_capture](https://docs.stripe.com/api/payment_intents/capture.md#capture_payment_intent-amount_to_capture) up to the [maximum_amount_capturable](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card-overcapture). ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/capture \ -u "<>:" \ -d amount_to_capture=1200 ``` # Extended authorisation > This is a Extended authorisation for when flex-payment-features is extended-auth. View the full page at https://docs.stripe.com/payments/flexible-features-migration?flex-payment-features=extended-auth. > #### Changes from beta > > The first step of this integration didn’t previously exist, but is now mandatory. ## Request extended authorisation Your *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) must include a request for extended authorisation before confirmation. The private beta integration for extended authorisation didn’t include this step because the request parameter didn’t exist. ```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_extended_authorization]=if_available" ``` The response returns the status of the extended authorisation request in the `payment_method_details.card.extended_authorization.status` property of the [latest_charge](https://docs.stripe.com/api/charges/object.md). The status values is `available` or `unavailable` depending on the customer’s payment method. ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent", "amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded { "latest_charge": { "amount": 1000, "payment_method_details": { "card": {// The field is now always available, even when not using extended authorization "capture_before": 1679090539, // The response contains information on whether the capture window was extended. "extended_authorization": {"status": "enabled", // or "disabled" } } } ... } } } ``` ## Capture the authorisation **No changes have been made to this step compared to the beta version.** Perform a capture before the date given in the [`capture_before` field](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card-capture_before). ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/capture \ -u "<>:" \ -d amount_to_capture=1000 ``` # Multicapture > This is a Multicapture for when flex-payment-features is multicapture. View the full page at https://docs.stripe.com/payments/flexible-features-migration?flex-payment-features=multicapture. > #### Changes from beta > > Migrating from the beta to the generally available version requires several changes that affect all four of the following steps. ## Request multicapture Your *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) must include a request for multicapture before confirmation. The private beta integration for multicapture didn’t include this step because the request parameter didn’t exist. Request access to the feature in the generally available version by passing the `multicapture_migrate_to_ga_from_beta` value in the [Stripe-Version](https://docs.stripe.com/sdks/set-version.md) header before confirming the *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process). ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -H "Stripe-Version: 2026-04-22.preview; multicapture_migrate_to_ga_from_beta" \ -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" ``` The response returns the status of the multicapture request in the `payment_method_details.card.multicapture.status` property of the [latest_charge](https://docs.stripe.com/api/charges/object.md). The status value is `available` or `unavailable` depending on the customer’s payment method. ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent","amount": 1000, "amount_capturable": 1000, "amount_received": 0, ... // if latest_charge is expanded "latest_charge": {"amount": 1000, "amount_captured": 0, "amount_refunded": 0, "payment_method_details": { "card": { "multicapture": {"status": "available" // or "unavailable" } } } ... } ... } ``` ## Partially capture the authorised amount multiple times Similar to the beta version, the optional `final_capture` parameter allows you to capture the *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) multiple times as long as it remains in a [requires_capture state](https://docs.stripe.com/payments/paymentintents/lifecycle.md). ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/capture \ -u "<>:" \ -H "Stripe-Version: 2026-04-22.preview; multicapture_migrate_to_ga_from_beta" \ -d amount_to_capture=700 \ -d final_capture=false \ -d "expand[]=latest_charge" ``` ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent","amount": 1000, "amount_capturable": 300, // 1000 - 700 = 300 "amount_received": 700, "status": "requires_capture", // if latest_charge is expanded "latest_charge": {"amount": 1000, "amount_captured": 700, "amount_refunded": 0, ... } ... } ``` > In the generally available version, attempting to capture the full remaining amount with the `final_capture` parameter set to `false` returns a 400 error. ### Before ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/capture \ -u "<>:" \ -d amount_to_capture=300 \ -d final_capture=false \ -d "expand[]=latest_charge" ``` ```json // PaymentIntent Response { "id": "pi_ANipwO3zNfjeWODtRPIg", "object": "payment_intent","amount": 1000, "amount_capturable": 0, // 1000 - 700 - 300 = 0 "amount_received": 1000, "status": "succeeded", // if latest_charge is expanded "latest_charge": {"amount": 1000, "amount_captured": 1000, "amount_refunded": 0, ... } ... } ``` ### After ```curl curl https://api.stripe.com/v1/payment_intents/pi_ANipwO3zNfjeWODtRPIg/capture \ -u "<>:" \ -d amount_to_capture=300 \ -d final_capture=false \ -d "expand[]=latest_charge" ``` ```json // HTTP 400 { "message": "can't set final_capture as false when fully capturing a payment intent.", "type": "invalid_request_error" } ``` ## Webhooks Multicapture event generation differs from the beta version, but the content of the events is unchanged. | Behaviour | Before | After | | ------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | On each non-final capture | Stripe sends [charge.captured](https://docs.stripe.com/api/events/types.md#event_types-charge.captured) | Stripe sends [charge.updated](https://docs.stripe.com/api/events/types.md#event_types-charge.updated) | | On the final capture | Stripe sends [charge.captured](https://docs.stripe.com/api/events/types.md#event_types-charge.captured) | Stripe sends [charge.captured](https://docs.stripe.com/api/events/types.md#event_types-charge.captured) | ## Refund In the generally available version, no [refund](https://docs.stripe.com/api/refunds/object.md) is created to represent uncaptured funds for any *PaymentIntent* (API object that represents your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process) where the user passes in `final_capture=true`. ## Choose how to capture more than initially authorised amount Two of the flexible payment features allow you to capture an amount larger than initially authorised: - Over capture up to a certain limit ([Capture more than the authorised amount on a payment](https://docs.stripe.com/payments/overcapture.md)) - Increment the existing authorisation and then capture the newly authorised amount ([Increment an authorisation](https://docs.stripe.com/payments/incremental-authorization.md)) The example below showcases how these features can complement each other in the generally available version. ```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_incremental_authorization]=if_available" \ -d "payment_method_options[card][request_overcapture]=if_available" ``` ```json // PaymentIntent Response { "object": "payment_intent", "amount": 1000, ... // if latest_charge is expanded { "latest_charge": { "payment_method_details": { "card": { "incremental_authorization": {"status": "available" // or "unavailable" }, "overcapture": {"status": "available", // or "unavailable" "maximum_amount_capturable": 1200 } } } ... } } } ``` Upon *confirmation* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) of the PaymentIntent, if both features are available, you have options on the next steps to capture a larger amount than initially authorised: 1. Overcapture if the desired amount is equal or below the `maximum_amount_capturable`. 1. Perform an incremental authorisation to the desired amount, then capture.