payinOPERATIONS MANUAL

Latest articles

Stripe Checkout shipping rates: price the whole order, replace rates, and respect the subscription boundary

Decide whether fixed order-level shipping fits Checkout, replace outdated rates without assuming repricing, and distinguish payment-mode shipping from subscription and dynamic-form requirements.

Published; sources checked:

Shipping cost model and shipping-rate lifecycle: fixed order amount, no automatic per-item multiplication, rate replacement and archive, payment versus subscription, narrow dynamic-UI boundary. Excludes address collection and final-quantity fulfillment.

1. Choose an order charge, not a per-item shipping formula

Stripe Checkout shipping rates are fixed amounts for the entire order, not rates multiplied by the number of items.[3] That is the first decision to settle before configuring a shipping selector: does your business sell delivery per order, or calculate it from units, weight, destination or a carrier quote?

A public developer question shows shipping divided by quantity and added into the product unit amount while the author asks how to use shipping rates.[9] This is qualitative evidence of a real modeling problem, not a measure of demand or proof that the workaround is appropriate.

Illustrative example, excluding tax and discounts: three items at US$20 each plus a US$5 order shipping rate total US$65. The shipping component is US$5, not US$15. If your policy is US$5 per item, that same order needs a separately calculated US$15 delivery charge; simply attaching a US$5 shipping rate does not encode that policy.[3] Our recommendation is to keep the product price and delivery policy separately understandable rather than hide freight in product arithmetic.

2. Offer fixed alternatives with a clear default

For a payment-mode Session, pass a saved shipping rate ID through shipping_options, or create a rate inline with shipping_rate_data.[3] The official example offers free shipping and US$15 next-day air, with the first array entry preselected and either option available to the customer.[3]

An illustrative configuration fragment is shipping_options: [{shipping_rate: "shr_standard_v2"}]; the ID is a placeholder, not an existing rate. A reusable rate fits a standard order-level delivery offer. An inline rate fits an amount your application has already determined for that Session. Neither choice turns the rate into an automatic quantity formula.[3]

Before exposing an option, decide its name, amount, currency and delivery estimate. Treat the default as a commercial decision: placing an expensive option first should not be an accidental consequence of how your application sorts records. These are implementation recommendations, not additional Stripe requirements.

3. Replace the amount; archive the superseded rate

Stripe says an amount already set for a currency cannot be updated on that shipping rate; new currencies can be added. In the Dashboard, changing the charge means archiving the existing rate and creating a new one.[3] This is a shipping-rate replacement, not an instruction to mutate the product’s Price object.

Suppose standard delivery rises from US$5 to US$7. Recommended rollout: create the replacement US$7 rate, record its new ID in the configuration that creates future Sessions, retire the old offer, and retain both IDs in your operational history. Coordinate the cutover so the old configuration is not still issuing the retired offer. The API’s active parameter describes whether the rate can be used for new purchases.[7]

Do not interpret an update endpoint as permission to overwrite an existing currency amount.[3][7] Do not assume archiving reprices paid orders or repairs already-open Sessions: those effects are not established by the sources used here. Inventory outstanding Sessions and make an explicit policy for them before the change. The Dashboard also documents an unarchive action, but that does not remove the need to manage which ID your application sends.[3]

4. Stop at the payment-versus-subscription boundary

Only Checkout Sessions in payment mode support the documented shipping options; shipping rates are not available in subscription mode.[3][8] A monthly physical-goods business must not assume that copying a one-time Checkout shipping configuration will create a recurring delivery charge.

Before choosing a subscription billing design, write down whether shipping is charged once, on each billing period, or only on actual dispatch. This guide does not establish a supported recurring-shipping implementation. Review the relevant subscription and invoicing design separately; do not change a subscription purchase to payment mode merely to make a shipping selector appear. The decision here is whether this shipping-options mechanism fits, not whether Stripe can support every possible physical-goods billing model.

5. Dynamic shipping is a different integration decision

The general shipping guide points to dynamic updates as a preview, but the current variant-specific guide explicitly says that the full hosted page and full embedded page do not support dynamically customizing shipping options.[3][4][5] Do not read the broad preview reference as a promise that address changes can recalculate shipping in every Checkout interface.

The embedded-form variant documents a separate flow in which your server calculates options and updates the Session. It is payment-mode only, does not support the Express Checkout Element, and does not support the permissions parameter; its client/server update flow also has a documented 20-second timeout.[8] These limits distinguish the embedded form from the full embedded page. This article is not a dynamic-shipping implementation tutorial.

Decision aid: a known, fixed order charge fits the rate model. If you require a live address-dependent quote, confirm the exact supported interface and its limitations before committing to that experience. If shipping changes with basket quantity, specify when your application recalculates it and which supported integration carries the revised offer; do not promise that the shipping-rate object supplies this behavior on its own.[3][8]

6. Review the cost model before launch or a price change

  • Write the charging unit explicitly: per order, per item, per parcel, or another merchant-defined rule.
  • Check Session mode before relying on shipping options.[3] Verify the exact interface before planning dynamic updates.[4][5][8]
  • Confirm every offered amount and currency, the first/default option, and the intended delivery description.[3]
  • For a price change, record old and new rate IDs, the application cutover, and the handling policy for outstanding Sessions.
  • Proposed sandbox checks: compare one item with three items, choose each offered delivery method, create a new Session after the rate cutover, and inspect what happens to an already-open Session. These checks were not executed for this article.

After payment succeeds, Stripe documents the charged shipping amount under shipping_cost.amount_total and the selected rate under shipping_cost.shipping_rate.[3] We recommend using those fields to compare the purchased delivery offer with your recorded policy, rather than recalculating an old order from today’s rate catalog. This is cost-model reconciliation, not a replacement for payment-readiness or fulfillment controls.

The scope is shipping-price structure and rate lifecycle, not billing-address collection, permitted destination countries, or fulfillment from final adjustable quantities. This is public-document research and editorial guidance, not an executed Stripe integration, a PayIn capability claim, or legal or tax advice.

Sources and dates

Checked on 2026-09-23. Retrieval is not publication. Official documentation establishes technical boundaries; the community question demonstrates qualitative demand only. Source publication and update dates are unknown unless stated below. These pages do not establish account eligibility, carrier coverage or worldwide availability; USD examples and an English documentation locale are not regional eligibility rules.

More guides