# Elements with Checkout Sessions API beta changelog Keep track of changes to the Elements with Checkout Sessions API beta integration. This doc contains changelogs related to beta versions of Elements with Checkout Sessions API. If you’re already on the of Elements with Checkout Sessions API, this doc does not apply to you. ## Migrating to Basil ### Changes * Asynchronous methods, such as [confirm](https://docs.stripe.com/js/custom_checkout/confirm) or [applyPromotionCode](https://docs.stripe.com/js/custom_checkout/apply_promotion_code), resolve with a different schema: * If successful, the updated session state is populated under the `session` key. Previously, this was under the `success` key. * An error is now thrown when passing in [returnUrl](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-returnUrl) on [confirm](https://docs.stripe.com/js/custom_checkout/confirm) when [return_url](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-return_url) has been already set on the Checkout Session. * The return URL redirected to after a successful confirmation previously had inconsistent query parameters. Extra parameters are now removed and the URL only contains what’s provided in [returnUrl](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-returnUrl) on [confirm](https://docs.stripe.com/js/custom_checkout/confirm) or [return_url](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-return_url) on the Checkout Session. * Improves latency on Checkout Session API for subscription-mode Sessions and fixes a bug that prevented your customers from updating a Session after the first payment attempt * The change creates the subscription after the user has completed the payment, so `checkout_session.invoice` and `checkout_session.subscription` are null until the Checkout Session completes. * If you currently rely on the deprecated `payment_intent.invoice` field, we recommend using the `checkout_session.completed` webhook, which ensures an invoice is present, and `checkout_session.invoice` or [Invoice Payment list](https://docs.stripe.com/api/invoice-payment/list.md) to find the associated invoice. * To learn more, read the . * Added [percentOff](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-discountAmounts-percentOff) to [discountAmounts](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-discountAmounts) as an option to display discounts. ### Upgrade Before migrating to Basil, first [update your integration](#beta-changelog) to `custom_checkout_beta_6`. - If you’re using any Stripe NPM packages, you must first upgrade `@stripe/stripe-js` to at least `7.0.0` and `@stripe/react-stripe-js` to at least `3.6.0`. - If you’re loading Stripe.js through the script tag, update the script tag to use [versioned Stripe.js](https://docs.stripe.com/sdks/stripejs-versioning.md) by replacing the tag as follows: ```html Checkout ``` - Remove the Stripe.js beta header when initializing Stripe.js. ```js const stripe = Stripe( '<>', { betas: ['custom_checkout_beta_6'], } ); ``` ```javascript import {loadStripe} from '@stripe/stripe-js'; const stripe = loadStripe("<>", { betas: ['custom_checkout_beta_6'], }); ``` - Remove the API version beta header and specify the API version to be at least `2025-03-31.basil` on your back-end integration. ```javascript // Set your secret key. Remember to switch to your live secret key in production. // See your keys here: https://dashboard.stripe.com/apikeys import Stripe from 'stripe'; const stripe = new Stripe('<>', { apiVersion: '{{merchant.apiVersion}}; custom_checkout_beta=v1' as any, }); ``` ```javascript <> ``` ```ruby <> ``` ```php <> ``` ```python <> ``` ```go <> ``` ```go <> ``` ```java <> ``` ```javascript // Set your secret key. Remember to switch to your live secret key in production. // See your keys here: https://dashboard.stripe.com/apikeys import Stripe from 'stripe'; const stripe = new Stripe('<>', { apiVersion: '2025-03-31.basil' as any, }); ``` ```javascript <> ``` ```ruby <> ``` ```php <> ``` ```python <> ``` ```go <> ``` ```go <> ``` ```java <> ``` ## Beta changelog Elements with Checkout Sessions API beta uses two kinds of beta versions: * A Stripe.js beta header (e.g., `custom_checkout_beta_6`), which is set on your front-end integration. * An API version beta header (e.g., `custom_checkout_beta=v1`), which is set on your back-end integration. ### Front-end beta versions Specify the front-end beta version when [initializing Stripe.js](https://docs.stripe.com/checkout/custom/quickstart.md). #### custom_checkout_beta_6 If you’re using any Stripe NPM packages, you must first upgrade `@stripe/stripe-js` to at least `6.1.0` and `@stripe/react-stripe-js` to at least `3.5.0`. * The sign of [total.appliedBalance](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-total-appliedBalance) has been flipped. A positive number now increases the amount to be paid, and a negative number decreases the amount to be paid. * Replaced `clientSecret` with [fetchClientSecret](https://docs.stripe.com/js/custom_checkout/init#custom_checkout_init-options-clientSecret). Update your integration to pass an async function resolving to the client secret instead of passing a static value. * Elements methods has been renamed. * If you’re using React Stripe.js, you don’t need to do anything except upgrade `@stripe/react-stripe-js`. * If you’re using HTML/JS: * Use `createPaymentElement()` instead of `createElement('payment')`. * Use `createBillingAddressElement()` instead of `createElement('address', {mode: 'billing'})`. * Use `createShippingAddressElement()` instead of `createElement('address', {mode: 'shipping'})`. * Use `createExpressCheckoutElement()` instead of `createElement('expressCheckout')`. * Use `getPaymentElement()` instead of `getElement('payment')`. * Use `getBillingAddressElement()` instead of `getElement('address', {mode: 'billing'})`. * Use `getShippingAddressElement()` instead of `getElement('address', {mode: 'shipping'})`. * Use `getExpressCheckoutElement()` instead of `getElement('expressCheckout')`. * Updated fields related to confirmation to more accurately reflect session state. * [canConfirm](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-canConfirm) now responds to any mounted Billing Address Element or Shipping Address Element. * [canConfirm](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-canConfirm) now becomes `false` if there is an in-flight confirmation. * Removed `confirmationRequirements`. * [updateEmail](https://docs.stripe.com/js/custom_checkout/update_email) now throws an error if [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email) was provided when creating the Checkout Session. If you intend to prefill an email that your customer can update, call `updateEmail` as soon as the page loads instead of passing `customer_email`. * [returnUrl](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-returnUrl) must be an absolute URL (for example, starts with `https://` rather than a relative URL, like `/success`). * Updated pricing fields to a nested object for ease of rendering. * Replaced numeric values with an object containing `amount` (a formatted currency string, such as `$10.00`) and `minorUnitsAmount`, an integer representing the value in the currency’s smallest unit. If you’re already reading the amount, read instead from `minorUnitsAmount`. * For example, replace `total.total` with [`total.total.minorUnitsAmount`](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-total-total-minorUnitsAmount). * You must either read `total.total.amount` or each of `total.total.minorUnitsAmount` and `currency` and `minorUnitsAmountDivisor` from the `checkout` object and display in your UI, otherwise an error will be thrown. This helps keep your checkout page in sync as the CheckoutSession updates, including adding future Stripe features, with minimal UI code changes. * Customer tax IDs can now be collected. Learn how to [collect tax IDs](https://docs.stripe.com/tax/checkout/tax-ids.md?payment-ui=embedded-components). * A test mode-only assistant is now available at the bottom of your checkout page, offering guidance for your integration and shortcuts for common test scenarios. #### custom_checkout_beta_5 * The `initCustomCheckout` function has been renamed to [initCheckout](https://docs.stripe.com/js/custom_checkout/init) * Within React Stripe.js, `CustomCheckoutProvider` has been renamed to `CheckoutProvider` and `useCustomCheckout` has been renamed to `useCheckout`. * To confirm the [Express Checkout Element](https://docs.stripe.com/checkout/one-click-payment-buttons.md), call [confirm](https://docs.stripe.com/js/custom_checkout/confirm), passing the [confirm event](https://docs.stripe.com/js/elements_object/express_checkout_element_confirm_event) as `expressCheckoutConfirmEvent` * Previously, Express Checkout Element was confirmed by calling `event.confirm()`. * When [confirm](https://docs.stripe.com/js/custom_checkout/confirm) is called, Payment Element and Address Element will validate form inputs and render any errors. * Error messages have been standardized and improved. * Errors returned/resolved by a function represent known scenarios like invalid payment details or insufficient funds. These are predictable issues that can be communicated to your customer by displaying the `message` on the checkout page. * Errors thrown/rejected by a function represent errors in the integration itself, such as invalid parameters or configuration. These errors are not meant to be displayed to your customers. * Asynchronous methods, such as [confirm](https://docs.stripe.com/js/custom_checkout/confirm) or [applyPromotionCode](https://docs.stripe.com/js/custom_checkout/apply_promotion_code), resolve with a different schema: * A `type="success"|"error"` discriminator field has been added. * If successful, the updated session state is populated under the `success` key. Previously, this was under the `session` key. * Otherwise, the error continues to be populated under the `error` key. * Added the `email`, `phoneNumber`, `billingAddress`, and `shippingAddress` options to [confirm](https://docs.stripe.com/js/custom_checkout/confirm). * Address Element no longer automatically updates the [billingAddress](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-billingAddress) or [shippingAddress](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-shippingAddress) fields on the Session. * So long as Address Element is mounted, form values will automatically be used when calling [confirm](https://docs.stripe.com/js/custom_checkout/confirm). * Listen to the [change event](https://docs.stripe.com/js/element/events/on_change?type=addressElement) to use the Address Element value before confirmation. #### custom_checkout_beta_4 * Added [images](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-images) to the [Session object](https://docs.stripe.com/js/custom_checkout/session_object). * Added [fields](https://docs.stripe.com/js/custom_checkout/create_payment_element#custom_checkout_create_payment_element-options-fields) as an option when creating the Payment Element. * Added [paymentMethods](https://docs.stripe.com/js/custom_checkout/create_express_checkout_element#custom_checkout_create_express_checkout_element-options-paymentMethods) as an option when creating the Express Checkout Element. * Passing invalid options to [createElement](https://docs.stripe.com/js/custom_checkout/create_payment_element) now throws an error. Previously, unrecognized options would be silently ignored. * [updateEmail](https://docs.stripe.com/js/custom_checkout/update_email) and [updatePhoneNumber](https://docs.stripe.com/js/custom_checkout/update_phone_number) apply changes asynchronously. Calling these methods before the customer finishes entering complete values might cause poor performance. * Instead of calling `updateEmail` or `updatePhoneNumber` on each input’s change event, wait until your customer finishes the input, such as on input blur or when they submit the form for payment. * `updateEmail` now validates that the input is a properly formed email address and returns an error if an invalid input is used. * `updatePhoneNumber` still performs no validation on the input string. #### custom_checkout_beta_3 * The following fields have been added to the [Session object](https://docs.stripe.com/js/custom_checkout/session_object): * [id](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-id) * [livemode](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-livemode) * [businessName](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-businessName) * Saved cards can now be reused. Learn how to [save and reuse](https://docs.stripe.com/payments/checkout/save-during-payment.md) payment methods. * The default [layout](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-layout) of the Payment Element has been changed to `accordion`. * To continue using the previous default layout, you must explicitly specify `layout='tabs'`. * The default behavior of [confirm](https://docs.stripe.com/js/custom_checkout/confirm) has been changed to always redirect to your `return_url` after a successful confirmation. * Previously, `confirm` redirected only if the customer chooses a redirect-based payment method. To continue using the old behavior, you must pass [redirect=‘if_required’](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-redirect) to `confirm`. #### custom_checkout_beta_2 * The `lineItem.recurring.interval_count` field has been removed and replaced with [lineItem.recurring.intervalCount](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-recurring-intervalCount). * The `lineItem.amount` field has been removed and replaced with the following: * [lineItem.amountSubtotal](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-amountSubtotal) * [lineItem.amountDiscount](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-amountDiscount) * [lineItem.amountTaxInclusive](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-amountTaxInclusive) * [lineItem.amountTaxExclusive](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-lineItems-amountTaxExclusive) #### custom_checkout_beta_1 _This is the initial front-end beta version._ ### Back-end changelog Specify the back-end beta version when [setting up your server library](https://docs.stripe.com/checkout/custom/quickstart.md#init-stripe). _There are no changes to the back-end beta version._