--- title: No-cost orders subtitle: Accept orders for no-cost line items or apply 100% off discounts for one-time payments. route: /payments/checkout/no-cost-orders --- # No-cost orders Accept orders for no-cost line items or apply 100% off discounts for one-time payments. # Stripe-hosted page > This is a Stripe-hosted page for when payment-ui is stripe-hosted. View the original doc at https://docs.stripe.com/payments/checkout/no-cost-orders?payment-ui=stripe-hosted. You can process no-cost orders for one-time payments with [no-cost line items](#no-cost-line-items) or discounts for 100% off with [coupons and customer-facing promotion codes](#full-cost-discounts). You must be on API version [2023-08-16](https://docs.stripe.com/upgrades.md#2023-08-16) or later to process no-cost orders using the Checkout Sessions API. ## Create a Checkout Session with no-cost line items Create a [Price](https://docs.stripe.com/api/prices.md) with a [unit_amount](https://docs.stripe.com/api/prices/object.md#price_object-unit_amount) of 0, and pass it into the [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) array of the Checkout Session. See [Products and prices](https://docs.stripe.com/invoicing/products-prices.md) for more information on creating prices. You can also use the [price_data](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price_data) parameter of the `line_items` array to pass in a free price. If the total amount is 0, Checkout doesn’t collect a payment method from the customer. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 0, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "Free t-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Mode = "payment", SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(0), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("Free t-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(0L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("Free t-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setSuccessUrl("https://example.com/success") .setCancelUrl("https://example.com/cancel") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 0, product_data: { name: 'Free t-shirt', }, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 0, "product_data": {"name": "Free t-shirt"}, "currency": "usd"}, "quantity": 1, }, ], mode="payment", success_url="https://example.com/success", cancel_url="https://example.com/cancel", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 0, 'product_data' => ['name' => 'Free t-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'mode' => 'payment', 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 0, product_data: {name: 'Free t-shirt'}, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }) ``` If the `customer` property isn’t set, the Checkout Session automatically creates a new Customer object. This means [guest customers](https://docs.stripe.com/payments/checkout/guest-customers.md) aren’t supported. ## Create a discount Alternatively, create a coupon and a promotion code to allow customers to complete orders for free. ### Create a coupon Create a [Coupon](https://docs.stripe.com/api/coupons.md) that makes your Checkout Session free. For example, you can create a 100% off coupon. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new CouponCreateOptions { PercentOff = 100M, Duration = "once" }; var service = new CouponService(); Coupon coupon = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CouponParams{ PercentOff: stripe.Float64(100), Duration: stripe.String(string(stripe.CouponDurationOnce)), }; result, err := coupon.New(params); ``` ```java Stripe.apiKey = "<>"; CouponCreateParams params = CouponCreateParams.builder() .setPercentOff(new BigDecimal(100)) .setDuration(CouponCreateParams.Duration.ONCE) .build(); Coupon coupon = Coupon.create(params); ``` ```node const stripe = require('stripe')('<>'); const coupon = await stripe.coupons.create({ percent_off: 100, duration: 'once', }); ``` ```python import stripe stripe.api_key = "<>" coupon = stripe.Coupon.create( percent_off=100, duration="once", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $coupon = $stripe->coupons->create([ 'percent_off' => 100, 'duration' => 'once', ]); ``` ```ruby Stripe.api_key = '<>' coupon = Stripe::Coupon.create({ percent_off: 100, duration: 'once', }) ``` To create a session with an applied discount, pass the [coupon ID](https://docs.stripe.com/api/coupons/object.md#coupon_object-id) in the `coupon` parameter of the [discounts](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-discounts) array. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 2000, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Discounts = new List { new Stripe.Checkout.SessionDiscountOptions { Coupon = "<>" }, }, Mode = "payment", SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(2000), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Discounts: []*stripe.CheckoutSessionDiscountParams{ &stripe.CheckoutSessionDiscountParams{Coupon: stripe.String("<>")}, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .addDiscount(SessionCreateParams.Discount.builder().setCoupon("<>").build()) .setMode(SessionCreateParams.Mode.PAYMENT) .setSuccessUrl("https://example.com/success") .setCancelUrl("https://example.com/cancel") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: { name: 'T-shirt', }, currency: 'usd', }, quantity: 1, }, ], discounts: [ { coupon: '<>', }, ], mode: 'payment', success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 2000, "product_data": {"name": "T-shirt"}, "currency": "usd"}, "quantity": 1, }, ], discounts=[{"coupon": "<>"}], mode="payment", success_url="https://example.com/success", cancel_url="https://example.com/cancel", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 2000, 'product_data' => ['name' => 'T-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'discounts' => [['coupon' => '<>']], 'mode' => 'payment', 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: {name: 'T-shirt'}, currency: 'usd', }, quantity: 1, }, ], discounts: [{coupon: '<>'}], mode: 'payment', success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }) ``` You can also create a free Checkout Session by applying a coupon for an amount equal to or exceeding the Checkout Session total. ### Create a promotion code Promotion codes are customer-facing codes created on top of coupons. You can share these codes with customers who can enter them into Checkout to apply a discount. Create a promotion code from a 100% off coupon to allow customers to create orders for free. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new PromotionCodeCreateOptions { Coupon = "<>", Code = "FREECODE" }; var service = new PromotionCodeService(); PromotionCode promotionCode = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.PromotionCodeParams{ Coupon: stripe.String("<>"), Code: stripe.String("FREECODE"), }; result, err := promotioncode.New(params); ``` ```java Stripe.apiKey = "<>"; PromotionCodeCreateParams params = PromotionCodeCreateParams.builder().setCoupon("<>").setCode("FREECODE").build(); PromotionCode promotionCode = PromotionCode.create(params); ``` ```node const stripe = require('stripe')('<>'); const promotionCode = await stripe.promotionCodes.create({ coupon: '<>', code: 'FREECODE', }); ``` ```python import stripe stripe.api_key = "<>" promotion_code = stripe.PromotionCode.create( coupon="<>", code="FREECODE", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $promotionCode = $stripe->promotionCodes->create([ 'coupon' => '<>', 'code' => 'FREECODE', ]); ``` ```ruby Stripe.api_key = '<>' promotion_code = Stripe::PromotionCode.create({ coupon: '<>', code: 'FREECODE', }) ``` Enable user-redeemable promotion codes using the [allow_promotion_codes](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-allow_promotion_codes) parameter in a Checkout Session. This enables a field in Checkout to allow users to enter promotion codes. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 2000, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Mode = "payment", AllowPromotionCodes = true, SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(2000), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), AllowPromotionCodes: stripe.Bool(true), SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setAllowPromotionCodes(true) .setSuccessUrl("https://example.com/success") .setCancelUrl("https://example.com/cancel") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: { name: 'T-shirt', }, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', allow_promotion_codes: true, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 2000, "product_data": {"name": "T-shirt"}, "currency": "usd"}, "quantity": 1, }, ], mode="payment", allow_promotion_codes=True, success_url="https://example.com/success", cancel_url="https://example.com/cancel", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 2000, 'product_data' => ['name' => 'T-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'mode' => 'payment', 'allow_promotion_codes' => true, 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: {name: 'T-shirt'}, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', allow_promotion_codes: true, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }) ``` Customers can also check out for free if they apply a promotion code for an amount equal to or exceeding the Checkout Session total. For more ways to apply discounts, see [Add discounts](https://docs.stripe.com/payments/checkout/discounts.md). ## Handle completed orders After the Checkout Session completes, you can make a request for the finalized [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) and their quantities. If your customer removes a line item, it also removes it from the line items response. See the [Fulfillment guide](https://docs.stripe.com/checkout/fulfillment.md) to learn how to create an event handler to handle completed Checkout Sessions. To fulfill no-cost orders, make sure to handle the `checkout.session.completed` event rather than [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md) events. Completed Checkout Sessions that are free won’t have an associated [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md). You can see your completed no-cost orders in the [Dashboard](https://dashboard.stripe.com/no-cost-orders). The no-cost orders tab only appears if you have at least one completed no-cost order. ## Payment links and pricing tables Payment links and pricing tables support no-cost orders by default when your account is created after August 17, 2023. For accounts created before August 17, 2023, you can enable no-cost orders for your Payment links and pricing tables by visiting your [Checkout settings](https://dashboard.stripe.com/settings/checkout) in the Dashboard. When you enable this feature, it has a 3-day grace period in which you can turn it off. After 3 days, you can’t disable it. Before you enable it for your live payment links and pricing tables, test it with your fulfillment flow in a sandbox. To use no-cost orders with a payment link in a sandbox, specify a `prefilled_email` [URL parameter](https://docs.stripe.com/payment-links/customize.md#customize-checkout-with-url-parameters) with an email whose local part includes the suffix `+no_cost_orders`. For example, `j.appleseed+no_cost_orders@example.com`. The resulting checkout session lets you apply a discount that reduces the order total to zero. To use no-cost orders with a pricing table in a sandbox, set the pricing table’s `customer-email` [property](https://docs.stripe.com/payments/checkout/pricing-table.md#customer-email) to an email whose local part includes the suffix `+no_cost_orders`. For example, `j.appleseed+no_cost_orders@example.com`. The resulting checkout session lets you apply a discount that reduces the order total to zero. # Embedded form > This is a Embedded form for when payment-ui is embedded-form. View the original doc at https://docs.stripe.com/payments/checkout/no-cost-orders?payment-ui=embedded-form. You can process no-cost orders for one-time payments with [no-cost line items](#no-cost-line-items) or discounts for 100% off with [coupons and customer-facing promotion codes](#full-cost-discounts). You must be on API version [2023-08-16](https://docs.stripe.com/upgrades.md#2023-08-16) or later to process no-cost orders using the Checkout Sessions API. ## Create a Checkout Session with no-cost line items Create a [Price](https://docs.stripe.com/api/prices.md) with a [unit_amount](https://docs.stripe.com/api/prices/object.md#price_object-unit_amount) of 0, and pass it into the [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) array of the Checkout Session. See [Products and prices](https://docs.stripe.com/invoicing/products-prices.md) for more information on creating prices. You can also use the [price_data](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price_data) parameter of the `line_items` array to pass in a free price. If the total amount is 0, Checkout doesn’t collect a payment method from the customer. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 0, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "Free t-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Mode = "payment", UiMode = "embedded", ReturnUrl = "https://example.com/return", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(0), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("Free t-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), UIMode: stripe.String(string(stripe.CheckoutSessionUIModeEmbedded)), ReturnURL: stripe.String("https://example.com/return"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(0L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("Free t-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setUiMode(SessionCreateParams.UiMode.EMBEDDED) .setReturnUrl("https://example.com/return") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 0, product_data: { name: 'Free t-shirt', }, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', ui_mode: 'embedded', return_url: 'https://example.com/return', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 0, "product_data": {"name": "Free t-shirt"}, "currency": "usd"}, "quantity": 1, }, ], mode="payment", ui_mode="embedded", return_url="https://example.com/return", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 0, 'product_data' => ['name' => 'Free t-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'mode' => 'payment', 'ui_mode' => 'embedded', 'return_url' => 'https://example.com/return', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 0, product_data: {name: 'Free t-shirt'}, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', ui_mode: 'embedded', return_url: 'https://example.com/return', }) ``` If the `customer` property isn’t set, the Checkout Session automatically creates a new Customer object. This means [guest customers](https://docs.stripe.com/payments/checkout/guest-customers.md) aren’t supported. ## Create a discount Alternatively, create a coupon and a promotion code to allow customers to complete orders for free. ### Create a coupon Create a [Coupon](https://docs.stripe.com/api/coupons.md) that makes your Checkout Session free. For example, you can create a 100% off coupon. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new CouponCreateOptions { PercentOff = 100M, Duration = "once" }; var service = new CouponService(); Coupon coupon = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CouponParams{ PercentOff: stripe.Float64(100), Duration: stripe.String(string(stripe.CouponDurationOnce)), }; result, err := coupon.New(params); ``` ```java Stripe.apiKey = "<>"; CouponCreateParams params = CouponCreateParams.builder() .setPercentOff(new BigDecimal(100)) .setDuration(CouponCreateParams.Duration.ONCE) .build(); Coupon coupon = Coupon.create(params); ``` ```node const stripe = require('stripe')('<>'); const coupon = await stripe.coupons.create({ percent_off: 100, duration: 'once', }); ``` ```python import stripe stripe.api_key = "<>" coupon = stripe.Coupon.create( percent_off=100, duration="once", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $coupon = $stripe->coupons->create([ 'percent_off' => 100, 'duration' => 'once', ]); ``` ```ruby Stripe.api_key = '<>' coupon = Stripe::Coupon.create({ percent_off: 100, duration: 'once', }) ``` To create a session with an applied discount, pass the [coupon ID](https://docs.stripe.com/api/coupons/object.md#coupon_object-id) in the `coupon` parameter of the [discounts](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-discounts) array. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 2000, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Discounts = new List { new Stripe.Checkout.SessionDiscountOptions { Coupon = "<>" }, }, Mode = "payment", UiMode = "embedded", ReturnUrl = "https://example.com/return", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(2000), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Discounts: []*stripe.CheckoutSessionDiscountParams{ &stripe.CheckoutSessionDiscountParams{Coupon: stripe.String("<>")}, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), UIMode: stripe.String(string(stripe.CheckoutSessionUIModeEmbedded)), ReturnURL: stripe.String("https://example.com/return"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .addDiscount(SessionCreateParams.Discount.builder().setCoupon("<>").build()) .setMode(SessionCreateParams.Mode.PAYMENT) .setUiMode(SessionCreateParams.UiMode.EMBEDDED) .setReturnUrl("https://example.com/return") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: { name: 'T-shirt', }, currency: 'usd', }, quantity: 1, }, ], discounts: [ { coupon: '<>', }, ], mode: 'payment', ui_mode: 'embedded', return_url: 'https://example.com/return', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 2000, "product_data": {"name": "T-shirt"}, "currency": "usd"}, "quantity": 1, }, ], discounts=[{"coupon": "<>"}], mode="payment", ui_mode="embedded", return_url="https://example.com/return", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 2000, 'product_data' => ['name' => 'T-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'discounts' => [['coupon' => '<>']], 'mode' => 'payment', 'ui_mode' => 'embedded', 'return_url' => 'https://example.com/return', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: {name: 'T-shirt'}, currency: 'usd', }, quantity: 1, }, ], discounts: [{coupon: '<>'}], mode: 'payment', ui_mode: 'embedded', return_url: 'https://example.com/return', }) ``` You can also create a free Checkout Session by applying a coupon for an amount equal to or exceeding the Checkout Session total. ### Create a promotion code Promotion codes are customer-facing codes created on top of coupons. You can share these codes with customers who can enter them into Checkout to apply a discount. Create a promotion code from a 100% off coupon to allow customers to create orders for free. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new PromotionCodeCreateOptions { Coupon = "<>", Code = "FREECODE" }; var service = new PromotionCodeService(); PromotionCode promotionCode = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.PromotionCodeParams{ Coupon: stripe.String("<>"), Code: stripe.String("FREECODE"), }; result, err := promotioncode.New(params); ``` ```java Stripe.apiKey = "<>"; PromotionCodeCreateParams params = PromotionCodeCreateParams.builder().setCoupon("<>").setCode("FREECODE").build(); PromotionCode promotionCode = PromotionCode.create(params); ``` ```node const stripe = require('stripe')('<>'); const promotionCode = await stripe.promotionCodes.create({ coupon: '<>', code: 'FREECODE', }); ``` ```python import stripe stripe.api_key = "<>" promotion_code = stripe.PromotionCode.create( coupon="<>", code="FREECODE", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $promotionCode = $stripe->promotionCodes->create([ 'coupon' => '<>', 'code' => 'FREECODE', ]); ``` ```ruby Stripe.api_key = '<>' promotion_code = Stripe::PromotionCode.create({ coupon: '<>', code: 'FREECODE', }) ``` Enable user-redeemable promotion codes using the [allow_promotion_codes](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-allow_promotion_codes) parameter in a Checkout Session. This enables a field in Checkout to allow users to enter promotion codes. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 2000, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Mode = "payment", AllowPromotionCodes = true, UiMode = "embedded", ReturnUrl = "https://example.com/return", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(2000), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), AllowPromotionCodes: stripe.Bool(true), UIMode: stripe.String(string(stripe.CheckoutSessionUIModeEmbedded)), ReturnURL: stripe.String("https://example.com/return"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setAllowPromotionCodes(true) .setUiMode(SessionCreateParams.UiMode.EMBEDDED) .setReturnUrl("https://example.com/return") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: { name: 'T-shirt', }, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', allow_promotion_codes: true, ui_mode: 'embedded', return_url: 'https://example.com/return', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 2000, "product_data": {"name": "T-shirt"}, "currency": "usd"}, "quantity": 1, }, ], mode="payment", allow_promotion_codes=True, ui_mode="embedded", return_url="https://example.com/return", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 2000, 'product_data' => ['name' => 'T-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'mode' => 'payment', 'allow_promotion_codes' => true, 'ui_mode' => 'embedded', 'return_url' => 'https://example.com/return', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: {name: 'T-shirt'}, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', allow_promotion_codes: true, ui_mode: 'embedded', return_url: 'https://example.com/return', }) ``` Customers can also check out for free if they apply a promotion code for an amount equal to or exceeding the Checkout Session total. For more ways to apply discounts, see [Add discounts](https://docs.stripe.com/payments/checkout/discounts.md). ## Handle completed orders After the Checkout Session completes, you can make a request for the finalized [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) and their quantities. If your customer removes a line item, it also removes it from the line items response. See the [Fulfillment guide](https://docs.stripe.com/checkout/fulfillment.md) to learn how to create an event handler to handle completed Checkout Sessions. To fulfill no-cost orders, make sure to handle the `checkout.session.completed` event rather than [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md) events. Completed Checkout Sessions that are free won’t have an associated [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md). You can see your completed no-cost orders in the [Dashboard](https://dashboard.stripe.com/no-cost-orders). The no-cost orders tab only appears if you have at least one completed no-cost order. # Embedded components > This is a Embedded components for when payment-ui is embedded-components. View the original doc at https://docs.stripe.com/payments/checkout/no-cost-orders?payment-ui=embedded-components. You can process no-cost orders for one-time payments with [no-cost line items](#no-cost-line-items) or discounts for 100% off with [coupons and customer-facing promotion codes](#full-cost-discounts). When [rendering](https://docs.stripe.com/checkout/custom/quickstart.md#initialize-checkout-html) no-cost sessions, make sure that Payment Element and Express Checkout Element aren’t mounted on the page. ## Create a Checkout Session with no-cost line items Create a [Price](https://docs.stripe.com/api/prices.md) with a [unit_amount](https://docs.stripe.com/api/prices/object.md#price_object-unit_amount) of 0, and pass it into the [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) array of the Checkout Session. See [Products and prices](https://docs.stripe.com/invoicing/products-prices.md) for more information on creating prices. You can also use the [price_data](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price_data) parameter of the `line_items` array to pass in a free price. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 0, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "Free t-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Mode = "payment", UiMode = "custom", ReturnUrl = "https://example.com/return", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(0), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("Free t-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), UIMode: stripe.String(string(stripe.CheckoutSessionUIModeCustom)), ReturnURL: stripe.String("https://example.com/return"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(0L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("Free t-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setUiMode(SessionCreateParams.UiMode.CUSTOM) .setReturnUrl("https://example.com/return") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 0, product_data: { name: 'Free t-shirt', }, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', ui_mode: 'custom', return_url: 'https://example.com/return', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 0, "product_data": {"name": "Free t-shirt"}, "currency": "usd"}, "quantity": 1, }, ], mode="payment", ui_mode="custom", return_url="https://example.com/return", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 0, 'product_data' => ['name' => 'Free t-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'mode' => 'payment', 'ui_mode' => 'custom', 'return_url' => 'https://example.com/return', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 0, product_data: {name: 'Free t-shirt'}, currency: 'usd', }, quantity: 1, }, ], mode: 'payment', ui_mode: 'custom', return_url: 'https://example.com/return', }) ``` If the `customer` property isn’t set, the Checkout Session automatically creates a new Customer object. This means [guest customers](https://docs.stripe.com/payments/checkout/guest-customers.md) aren’t supported. ## Create a discount Alternatively, create a coupon and a promotion code to allow customers to complete orders for free. ### Create a coupon Create a [Coupon](https://docs.stripe.com/api/coupons.md) that makes your Checkout Session free. For example, you can create a 100% off coupon. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new CouponCreateOptions { PercentOff = 100M, Duration = "once" }; var service = new CouponService(); Coupon coupon = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CouponParams{ PercentOff: stripe.Float64(100), Duration: stripe.String(string(stripe.CouponDurationOnce)), }; result, err := coupon.New(params); ``` ```java Stripe.apiKey = "<>"; CouponCreateParams params = CouponCreateParams.builder() .setPercentOff(new BigDecimal(100)) .setDuration(CouponCreateParams.Duration.ONCE) .build(); Coupon coupon = Coupon.create(params); ``` ```node const stripe = require('stripe')('<>'); const coupon = await stripe.coupons.create({ percent_off: 100, duration: 'once', }); ``` ```python import stripe stripe.api_key = "<>" coupon = stripe.Coupon.create( percent_off=100, duration="once", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $coupon = $stripe->coupons->create([ 'percent_off' => 100, 'duration' => 'once', ]); ``` ```ruby Stripe.api_key = '<>' coupon = Stripe::Coupon.create({ percent_off: 100, duration: 'once', }) ``` To create a session with an applied discount, pass the [coupon ID](https://docs.stripe.com/api/coupons/object.md#coupon_object-id) in the `coupon` parameter of the [discounts](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-discounts) array. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions { UnitAmount = 2000, ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, Currency = "usd", }, Quantity = 1, }, }, Discounts = new List { new Stripe.Checkout.SessionDiscountOptions { Coupon = "<>" }, }, Mode = "payment", UiMode = "custom", ReturnUrl = "https://example.com/return", }; var service = new Stripe.Checkout.SessionService(); Stripe.Checkout.Session session = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.CheckoutSessionParams{ LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ UnitAmount: stripe.Int64(2000), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, Currency: stripe.String(string(stripe.CurrencyUSD)), }, Quantity: stripe.Int64(1), }, }, Discounts: []*stripe.CheckoutSessionDiscountParams{ &stripe.CheckoutSessionDiscountParams{Coupon: stripe.String("<>")}, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), UIMode: stripe.String(string(stripe.CheckoutSessionUIModeCustom)), ReturnURL: stripe.String("https://example.com/return"), }; result, err := session.New(params); ``` ```java Stripe.apiKey = "<>"; SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build() ) .setCurrency("usd") .build() ) .setQuantity(1L) .build() ) .addDiscount(SessionCreateParams.Discount.builder().setCoupon("<>").build()) .setMode(SessionCreateParams.Mode.PAYMENT) .setUiMode(SessionCreateParams.UiMode.CUSTOM) .setReturnUrl("https://example.com/return") .build(); Session session = Session.create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: { name: 'T-shirt', }, currency: 'usd', }, quantity: 1, }, ], discounts: [ { coupon: '<>', }, ], mode: 'payment', ui_mode: 'custom', return_url: 'https://example.com/return', }); ``` ```python import stripe stripe.api_key = "<>" session = stripe.checkout.Session.create( line_items=[ { "price_data": {"unit_amount": 2000, "product_data": {"name": "T-shirt"}, "currency": "usd"}, "quantity": 1, }, ], discounts=[{"coupon": "<>"}], mode="payment", ui_mode="custom", return_url="https://example.com/return", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'unit_amount' => 2000, 'product_data' => ['name' => 'T-shirt'], 'currency' => 'usd', ], 'quantity' => 1, ], ], 'discounts' => [['coupon' => '<>']], 'mode' => 'payment', 'ui_mode' => 'custom', 'return_url' => 'https://example.com/return', ]); ``` ```ruby Stripe.api_key = '<>' session = Stripe::Checkout::Session.create({ line_items: [ { price_data: { unit_amount: 2000, product_data: {name: 'T-shirt'}, currency: 'usd', }, quantity: 1, }, ], discounts: [{coupon: '<>'}], mode: 'payment', ui_mode: 'custom', return_url: 'https://example.com/return', }) ``` You can also create a free Checkout Session by applying a coupon for an amount equal to or exceeding the Checkout Session total. ### Create a promotion code Promotion codes are customer-facing codes created on top of coupons. You can share these codes with customers who can enter them into Checkout to apply a discount. Create a promotion code from a 100% off coupon to allow customers to create orders for free. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new PromotionCodeCreateOptions { Coupon = "<>", Code = "FREECODE" }; var service = new PromotionCodeService(); PromotionCode promotionCode = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.PromotionCodeParams{ Coupon: stripe.String("<>"), Code: stripe.String("FREECODE"), }; result, err := promotioncode.New(params); ``` ```java Stripe.apiKey = "<>"; PromotionCodeCreateParams params = PromotionCodeCreateParams.builder().setCoupon("<>").setCode("FREECODE").build(); PromotionCode promotionCode = PromotionCode.create(params); ``` ```node const stripe = require('stripe')('<>'); const promotionCode = await stripe.promotionCodes.create({ coupon: '<>', code: 'FREECODE', }); ``` ```python import stripe stripe.api_key = "<>" promotion_code = stripe.PromotionCode.create( coupon="<>", code="FREECODE", ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $promotionCode = $stripe->promotionCodes->create([ 'coupon' => '<>', 'code' => 'FREECODE', ]); ``` ```ruby Stripe.api_key = '<>' promotion_code = Stripe::PromotionCode.create({ coupon: '<>', code: 'FREECODE', }) ``` Customers can then check out for free if they apply a promotion code for an amount equal to or exceeding the Checkout Session total. See [using promotion codes](https://docs.stripe.com/payments/checkout/discounts.md?payment-ui=embedded-components#use-promotion-code) for more information. ## Handle completed orders After the Checkout Session completes, you can make a request for the finalized [line items](https://docs.stripe.com/api/checkout/sessions/line_items.md) and their quantities. If your customer removes a line item, it also removes it from the line items response. See the [Fulfillment guide](https://docs.stripe.com/checkout/fulfillment.md) to learn how to create an event handler to handle completed Checkout Sessions. To fulfill no-cost orders, make sure to handle the `checkout.session.completed` event rather than [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md) events. Completed Checkout Sessions that are free won’t have an associated [PaymentIntent](https://docs.stripe.com/payments/payment-intents.md). You can see your completed no-cost orders in the [Dashboard](https://dashboard.stripe.com/no-cost-orders). The no-cost orders tab only appears if you have at least one completed no-cost order.