# Dynamically update payment amounts Learn how to modify total amounts when customers change their selections during checkout. Update the amount of a [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md) or [Payment Intent](https://docs.stripe.com/api/payment_intents.md) when customers change what they’re buying or how much they pay. Recalculate the totals on your server, and then update the amount of the PaymentIntent. #### Common use cases - Add or remove add-ons (such as gift wrap or a warranty). - Select a different shipping method or delivery speed. - Add additional services or charges. - Apply or remove a discount code or pre-tax store credit. #### Security best practices - Recalculate amounts on your server. Don’t trust client-provided prices or totals. - Authorize the update based on your business rules (for example, enforce max quantities). - Only update Sessions that are active and not completed or expired. #### Constraints and behavior - You can update the amount while the Payment Intent or Checkout Session is awaiting payment (for example, `requires_payment_method` or `requires_confirmation`). - After confirmation, you generally can’t increase the amount. # Payment Intents API ## Recalculate and update the total on the server [Server-side] To update the total amount: 1. Retrieve the changes to the cart or selection from the client. 2. Recalculate the new total amount on your server. 3. Update the PaymentIntent with the new amount. 4. Return the PaymentIntent (or its `client_secret`) to the client. #### Node ```node import express from 'express'; import Stripe from 'stripe'; const app = express(); app.use(express.json()); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = new Stripe('<>'); function computeOrderAmount(items, options = {}) { // ToDo: Your logic to compute an order total } app.post('/update-payment-intent', async (req, res) => { try { const {payment_intent_id, items, shipping_cents, service_cents, discount_cents} = req.body; // Compute amount on server const amount = computeOrderAmount(items, {shipping_cents, service_cents, discount_cents}); // Update the amount if the PaymentIntent can be updated const pi = await stripe.paymentIntents.update(payment_intent_id, { amount, }); return res.json({id: pi.id, amount: pi.amount, client_secret: pi.client_secret}); } catch (err) { return res.status(400).json({error: err.message}); } }); app.listen(4242, () => console.log('Server running on port 4242')); ``` ## Update the client and confirm [Client-side] > You’re responsible for keeping the client and server in sync. After updating the PaymentIntent amount on the server, call [elements.fetchUpdates](https://docs.stripe.com/js/elements_object/fetch_updates) to sync the Payment Element with the new amount, then confirm when the customer is ready. ```javascript async function updateAmount(items, options) { // Update the PaymentIntent on the server and get back the updated amount const response = await fetch('/update-payment-intent', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({payment_intent_id: paymentIntentId, items, ...options}), }); const {error: responseError} = await response.json(); if (responseError) { // Handle server error return; } // Sync the Payment Element with the updated PaymentIntent const {error} = await elements.fetchUpdates(); if (error) { // Handle sync error } } ```