Skip to content
Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Finance automation
Banking as a service
Developer tools
No-code
All products
Home
Payments
Finance automation
Home
Payments
Finance automation
Banking as a service
Developer tools
Overview
Online payments
In-person payments
Multiparty payments
After the payment
Add payment methods
Fraud detection
Payment Links
Stripe Checkout UI
    Overview
    How Checkout works
    Quickstart
    Fulfill your orders
    Migrate payment methods to the Dashboard
    Migrate from legacy Checkout
    Migrate Checkout to use Prices
    Customize your integration
    Customize branding
    Collect taxes
    Collect tax IDs
    Collect phone numbers
    Post-payment invoices
    Make line item quantities adjustable
    Add custom fields
    Let customers decide what to pay
    Boost revenue
    Present local currencies
    Configure subscription upsells
    Configure cross-sells
    Recover abandoned carts
    Collect consent for promotional emails
    Analyze conversion funnel
    Additional features
    Add discounts
    Add shipping
    Start a free trial without collecting payment details
    Set billing cycle date
    Manage limited inventory
    Guest customers
Stripe Elements UI
Financial Connections
Crypto
Identity
Climate
About the APIs
Regulation support
Implementation guides
Testing
Checkout
·
HomePayments

Add shipping

Learn to use shipping rates and collect shipping addresses with Checkout.

Not a programmer?

To adjust shipping rates with a no-code integration—for example, with Thrivecart or Shopify—visit the docs for that service.

Shipping rates let you display various shipping options—like standard, express, and overnight—with more accurate delivery estimates. This guide explains how to set shipping rates with Stripe Checkout, an integration that requires some code.

To charge for shipping based on the customer’s address, you can collect shipping address and write custom code to calculate the shipping rate.

Shipping address collection

Caution

The 2022-08-01 API version changed several shipping properties on the Checkout Session resource. Responses are different on earlier versions. See the API changelog for more details.

You can collect a customer’s shipping address in Checkout by setting shipping_address_collection when you create a Checkout session. You must also specify which countries to allow shipping to by configuring the allowed_countries property with an array of two-letter ISO country codes. These countries appear in the Country dropdown in the Shipping Address form on Checkout.

When the customer completes the session, the Checkout Session object saves the collected shipping address on the shipping_details property and includes it in the payload of the checkout.session.completed webhook. Additionally, shipping information appears in the Checkout summary section of your payment details page in the Dashboard.

Create a Checkout session with shipping options

Note

Only Checkout with payment mode supports shipping options.

Create a Checkout session, and define the shipping rates you want to offer in the shipping_options parameter. You can customize each shipping option with the shipping_rate_data parameter:

ParameterDescription
typeThe type of calculation to used on the shipping rate. Can only be fixed_amount for now.
fixed_amount[amount]How much to charge, in cents. Set it to 0 if you want to offer free shipping.
fixed_amount[currency]Which currency to charge in (for example, usd, eur).
display_nameThe name of the shipping rate, to display to the customer.
delivery_estimateAn object describing the estimated delivery time for this shipping rate option. API reference.

This example code snippet adds two shipping options to the Checkout session:

  • Free shipping, with an estimated delivery of 5-7 business days.
  • Next day air, at a cost of 15.00 USD, with an estimated delivery of exactly 1 business day.

Customers can select between these two options at checkout time.

Note

The first option in the shipping_options array is pre-selected for the customer when they land on the checkout page.

Command Line
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_4eC39HqLyjWDarjtT1zdp7dc
:"
\ -d "shipping_address_collection[allowed_countries][0]"=US \ -d "shipping_address_collection[allowed_countries][1]"=CA \ -d "shipping_options[0][shipping_rate_data][type]"=fixed_amount \ -d "shipping_options[0][shipping_rate_data][fixed_amount][amount]"=0 \ -d "shipping_options[0][shipping_rate_data][fixed_amount][currency]"=usd \ -d "shipping_options[0][shipping_rate_data][display_name]"="Free shipping" \ -d "shipping_options[0][shipping_rate_data][delivery_estimate][minimum][unit]"=business_day \ -d "shipping_options[0][shipping_rate_data][delivery_estimate][minimum][value]"=5 \ -d "shipping_options[0][shipping_rate_data][delivery_estimate][maximum][unit]"=business_day \ -d "shipping_options[0][shipping_rate_data][delivery_estimate][maximum][value]"=7 \ -d "shipping_options[1][shipping_rate_data][type]"=fixed_amount \ -d "shipping_options[1][shipping_rate_data][fixed_amount][amount]"=1500 \ -d "shipping_options[1][shipping_rate_data][fixed_amount][currency]"=usd \ -d "shipping_options[1][shipping_rate_data][display_name]"="Next day air" \ -d "shipping_options[1][shipping_rate_data][delivery_estimate][minimum][unit]"=business_day \ -d "shipping_options[1][shipping_rate_data][delivery_estimate][minimum][value]"=1 \ -d "shipping_options[1][shipping_rate_data][delivery_estimate][maximum][unit]"=business_day \ -d "shipping_options[1][shipping_rate_data][delivery_estimate][maximum][value]"=1 \ -d "line_items[0][price_data][currency]"=usd \ -d "line_items[0][price_data][product_data][name]"=T-shirt \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ --data-urlencode success_url="https://example.com/success" \ --data-urlencode cancel_url="https://example.com/cancel"

Your customers see a shipping selector on the checkout page:

The shipping selector on the checkout page

The shipping selector on the checkout page.

Delivery estimates

You can configure shipping rates using a number of delivery estimate combinations. The following table contains some examples of plain English delivery estimates, and their corresponding delivery_estimate.minimum and delivery_estimate.maximum values.

Delivery EstimateMinimumMaximum
1 day
{ unit: 'day', value: 1, }
{ unit: 'day', value: 1, }
1 business day
{ unit: 'business_day', value: 1, }
{ unit: 'business_day', value: 1, }
At least 2 business days
{ unit: 'business_day', value: 2, }
null
3 to 7 days
{ unit: 'day', value: 3, }
{ unit: 'day', value: 7, }
4 to 8 hours
{ unit: 'hour', value: 4, }
{ unit: 'hour', value: 8, }
4 hours to 2 business days
{ unit: 'hour', value: 4, }
{ unit: 'business_day', value: 2, }

Handling completed transactions

After the payment completes, you can retrieve the shipping amount in the amount_total attribute in the shipping_cost of the completed Checkout session. You can also retrieve the selected shipping rate using the shipping_rate attribute in shipping_cost.

See the Fulfillment guide to learn how to create an event handler to handle completed Checkout sessions.

Note

To test your event handler, install the Stripe CLI and use stripe listen --forward-to localhost:4242/webhook to forward events to your local server.

As soon as you have a handler, you can access the shipping_cost property:

# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
"sk_test_4eC39HqLyjWDarjtT1zdp7dc"
require 'sinatra' # You can find your endpoint's secret in your webhook settings endpoint_secret = 'whsec_...' post '/webhook' do event = nil # Verify webhook signature and extract the event # See https://stripe.com/docs/webhooks/signatures for more information. begin sig_header = request.env['HTTP_STRIPE_SIGNATURE'] payload = request.body.read event = Stripe::Webhook.construct_event(payload, sig_header, endpoint_secret) rescue JSON::ParserError => e # Invalid payload return status 400 rescue Stripe::SignatureVerificationError => e # Invalid signature return status 400 end if event['type'] == 'checkout.session.completed' checkout_session = event['data']['object'] fulfill_order(checkout_session) end status 200 end def fulfill_order(checkout_session) selected_shipping_rate = Stripe::ShippingRate.retrieve(checkout_session.shipping_cost.shipping_rate) shipping_total = checkout_session.shipping_cost.amount_total # TODO: Remove error and implement... raise NotImplementedError.new(<<~MSG) Given the Checkout Session "#{checkout_session.id}" load your internal order from the database then implement your own fulfillment logic. MSG end

OptionalCreate a shipping rate with the Dashboard

OptionalCreate a shipping rate with the API

OptionalCharge tax for shipping

Was this page helpful?
Need help? Contact Support.
Watch our developer tutorials.
Check out our product changelog.
Questions? Contact Sales.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
Shipping address collection
Create a Checkout session with shipping options
Delivery estimates
Handling completed transactions
Stripe Shell
Test mode
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to your Stripe account and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported Stripe commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$