Billing
Additional features
Applying discounts
Using customer-facing promotion codes

Using customer-facing promotion codes

Learn how to create customer-facing codes.

Coupons are merchant-facing objects you can use to control discounts on subscriptions or invoices. Promotion codes are customer-facing codes that are created on top of coupons and can be shared directly with your customers.

  • Create customer-facing codes that map to a single underlying coupon For example, FALLPROMO and SPRINGPROMO both pointing to a single 25% off coupon.
  • Customize controls and limits on promotion codes by specifying eligible customers, first time orders, minimum order values, expiration dates, and redemption limits
  • Limit the products that coupons can be applied to

Creating promotion codes

To create a promotion code, specify an existing coupon and any restrictions (for example, limiting to a specific customer). If you have a specific code you’d like to give to your customer (e.g., FALL25OFF), set the code. If you leave this field blank, we’ll generate a random code for you.

The code is case-insensitive and unique across active promotion codes for any customer. For example:

  • You can create multiple customer-restricted promotion codes with the same code, but you cannot reuse that code for a promotion code redeemable by any customer.
  • If you create a promotion code that is redeemable by any customer, you cannot create another active promotion code with the same code.
  • You can create a promotion code with code: NEWUSER, inactivate it by passing active: false, and then create a new promotion code with code: NEWUSER.

Promotion codes can be created in the coupons section of the Dashboard or via the API, as shown here:

curl https://api.stripe.com/v1/promotion_codes \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d coupon=ZQO00CcH \ -d code=ALICE20 \ -d customer=cus_4fdAW5ftNQow1a
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' coupon = Stripe::PromotionCode.create({ coupon: 'ZQO00CcH', code: 'ALICE20', customer: 'cus_4fdAW5ftNQow1a', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' coupon = stripe.PromotionCode.create( coupon='ZQO00CcH', code='ALICE20', customer='cus_4fdAW5ftNQow1a', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $coupon = \Stripe\PromotionCode::create([ 'coupon' => 'ZQO00CcH', 'code' => 'ALICE20', 'customer' => 'cus_4fdAW5ftNQow1a', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PromotionCodeCreateParams params = PromotionCodeCreateParams.builder() .setCoupon("ZQO00CcH") .setCode("ALICE20") .setCustomer("cus_4fdAW5ftNQow1a") .build(); PromotionCode promotionCode = PromotionCode.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const promotion_code = await stripe.promotion_codes.create({ coupon: 'ZQO00CcH', code: 'ALICE20', customer: 'cus_4fdAW5ftNQow1a', });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PromotionCodeParams{ Code: stripe.String("ALICE20"), Coupon: stripe.String("ZQO00CcH"), Customer: stripe.String("cus_4fdAW5ftNQow1a"), } pc, _ := promotioncode.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PromotionCodeCreateOptions { Code = "ALICE20", Coupon = "ZQO00CcH", Customer = "cus_4fdAW5ftNQow1a", }; var service = new PromotionCodeService(); var promotionCode = service.Create(options);

Applying promotion codes

When a customer attempts to redeem a code, you’ll first retrieve the promotion code’s id by retrieving the active promotion code with the entered code.

Create a discount by applying the promotion_code[id] to a subscription. You can do this when creating the subscription, as in the following code, or by updating a subscription later. You can also apply the promotion code to a customer when creating or updating the customer.

curl https://api.stripe.com/v1/subscriptions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d customer=cus_4fdAW5ftNQow1a \ -d "items[0][price]"=price_CBb6IXqvTLXp3f \ -d promotion_code=promo_1GgjnlClCIKljWvs0a29jxz1
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' subscription = Stripe::Subscription.create({ customer: 'cus_4fdAW5ftNQow1a', items: [ { price: 'price_CBb6IXqvTLXp3f', }, ], promotion_code: 'promo_1GgjnlClCIKljWvs0a29jxz1', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' subscription = stripe.Subscription.create( customer='cus_4fdAW5ftNQow1a', items=[ { 'price': 'price_CBb6IXqvTLXp3f', }, ], promotion_code='promo_1GgjnlClCIKljWvs0a29jxz1', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $subscription = \Stripe\Subscription::create([ 'customer' => 'cus_4fdAW5ftNQow1a', 'items' => [ [ 'price' => 'price_CBb6IXqvTLXp3f', ], ], 'promotion_code' => 'promo_1GgjnlClCIKljWvs0a29jxz1', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; SubscriptionCreateParams params = SubscriptionCreateParams.builder() .setCustomer("cus_4fdAW5ftNQow1a") .addItem( SubscriptionCreateParams.Item.builder() .setPrice("price_CBb6IXqvTLXp3f") .build()) .setPromotionCode("promo_1GgjnlClCIKljWvs0a29jxz1") .build(); Subscription subscription = Subscription.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const subscription = await stripe.subscriptions.create({ customer: 'cus_4fdAW5ftNQow1a', items: [ { price: 'price_CBb6IXqvTLXp3f', }, ], promotion_code: 'promo_1GgjnlClCIKljWvs0a29jxz1', });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.SubscriptionParams{ Customer: stripe.String("cus_4fdAW5ftNQow1a"), Items: []*stripe.SubscriptionItemsParams{ { Price: stripe.String("price_CBb6IXqvTLXp3f"), }, }, PromotionCode: stripe.String("promo_1GgjnlClCIKljWvs0a29jxz1"), } s, _ := sub.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new SubscriptionCreateOptions { Customer = "cus_4fdAW5ftNQow1a", Items = new List<SubscriptionItemOptions> { new SubscriptionItemOptions { Price = "price_CBb6IXqvTLXp3f", } }, PromotionCode = "promo_1GgjnlClCIKljWvs0a29jxz1", }; var service = new SubscriptionService(); var subscription = service.Create(options);

Adding promotion codes to Checkout

You can also enable promotion codes with the allow_promotion_codes parameter in Checkout Sessions. When allow_promotion_codes is enabled on a Checkout Session, Checkout includes a promotion code redemption box for your customers to use.

Create your coupons and promotion codes through the Dashboard or API in order for your customers to redeem them in Checkout.

curl https://api.stripe.com/v1/checkout/sessions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "payment_method_types[]"=card \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][price_data][currency]"=usd \ -d line_items[0][price_data][product]={{PRODUCT_ID}} \ -d line_items[0][price_data][recurring][interval]=month \ -d "line_items[0][quantity]"=1 \ -d mode=subscription \ -d allow_promotion_codes=true \ -d success_url="https://example.com/success" \ -d cancel_url="https://example.com/cancel"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' session = Stripe::Checkout::Session.create({ payment_method_types: ['card'], line_items: [{ price_data: { currency: 'usd', unit_amount: 2000, product: '{{PRODUCT_ID}}', recurring: { interval: 'month', }, }, quantity: 1, }], mode: 'subscription', allow_promotion_codes: true, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=[{ 'price_data': { 'currency': 'usd', 'unit_amount': 2000, 'product': '{{PRODUCT_ID}}', 'recurring': { 'interval': 'month', }, }, 'quantity': 1, }], mode='subscription', allow_promotion_codes=True, success_url='https://example.com/success', cancel_url='https://example.com/cancel', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'line_items' => [[ 'price_data' => [ 'currency' => 'usd', 'unit_amount' => 2000, 'product' => '{{PRODUCT_ID}}', 'recurring' => [ 'interval' => 'month', ], ], 'quantity' => 1, ]], 'mode' => 'subscription', 'allow_promotion_codes' => true, 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; SessionCreateParams params = SessionCreateParams.builder() .addPaymentMethodType(SessionCreateParams.PaymentMethodType.CARD) .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setCurrency("usd") .setUnitAmount(2000L) .setProduct("{{PRODUCT_ID}}") .setRecurring( SessionCreateParams.LineItem.PriceData.Recurring.builder() .setInterval(SessionCreateParams.LineItem.PriceData.Recurring.Interval.MONTH) .build()) .build()) .setQuantity(1L) .build()) .setMode(SessionCreateParams.Mode.SUBSCRIPTION) .putExtraParam("allow_promotion_codes", "true") .setSuccessUrl("https://example.com/success") .setCancelUrl("https://example.com/cancel") .build(); Session session = Session.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [{ price_data: { currency: "usd", unit_amount: 2000, product: '{{PRODUCT_ID}}', recurring: { interval: 'month', }, }, quantity: 1, }], mode: 'subscription', allow_promotion_codes: true, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.CheckoutSessionParams{ PaymentMethodTypes: stripe.StringSlice([]string{ "card", }), LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ Currency: stripe.String("usd"), UnitAmount: stripe.Int64(2000), Product: stripe.String("{{PRODUCT_ID}}"), Recurring: &stripe.RecurringParams{ Interval: stripe.String("month"), }, }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String("subscription"), SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), } params.AddExtra("allow_promotion_codes", "true") s, _ := session.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card", }, LineItems = new List<SessionLineItemOptions> { new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { UnitAmount = 2000, Currency = "usd", Product = "{{PRODUCT_ID}}", Recurring = new SessionLineItemPriceDataRecurringOptions { Interval = "month", }, }, Quantity = 1, }, }, Mode = "subscription", SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; options.AddExtraParam("allow_promotion_codes", "true"); var service = new SessionService(); var session = service.Create(options);

Promotion code configurations

By configuring the promotion code object parameters, you can customize which customers are eligible, how many times a promotion can be redeemed, when a promotion code expires, or set a minimum amount the discount can be applied to.

Limit by customer

To limit a promotion to a particular customer, specify a customer when creating the promotion code. If no customer is specified, the code can be redeemed by any customer.

Limit by first time order

You can also limit the promotion code to first time customers with the first_time_transaction parameter of the restrictions attribute. If the customer is not defined or if a defined customer has no prior payments or non-void invoices, it is considered a first time transaction.

Set a minimum amount

With promotion codes, you can set a minimum transaction amount for eligible discount by configuring the minimum_amount and the minimum_amount_currency properties. Since promotion code restrictions are checked at redemption time, the minimum transaction amount only applies to the initial payment for a subscription.

Customize expirations

You can set an expiration date on the promotion code using expires_at. If the underlying coupon already has redeem_by set, then the promotion code’s expiration date cannot be later than the coupon’s. If promotion_code[expires_at] is not specified, the coupon’s redeem_by automatically populates expires_at.

  • For example, you might have plans to support a coupon for a year, but you only want it to be redeemable for one week after a customer receives it. You would set coupon[redeem_by] to one year from now, and set each promotion_code[expires_at] to one week after it is created.

Limit redemptions

You can limit the number of redemptions by using max_redemptions, which works similarly to coupons. If the underlying coupon already has max_redemptions set, then the promotion code’s max_redemptions cannot be greater than the coupon’s.

  • For example, you might want a coupon to be redeemable by the first 50 customers, but every customer can only use it once. In this scenario, you would set coupon[max_redemptions]: 50 and promotion_code[max_redemptions]: 1.

Inactive promotions

You can set whether a promotion code is currently redeemable by using the active parameter. However, if the underlying coupon for a promotion code becomes invalid, all of its promotion codes become permanently inactive. Similarly, if a promotion code reaches its max_redemptions or expires_at, it becomes permanently inactive. These promotion codes cannot be reactivated.

Coupon code configurations

There are some configurations that can be set in a coupon, and will apply to any promotion codes that map to it. See how to set coupon configurations, like amount off, redemptions, and restrictions by products, in Creating coupons.

Restrictions

Currently, there are some restrictions to promotion codes:

  • You cannot apply a promotion code with amount restrictions on the Customer object or on a subscription update API call
  • You cannot apply both a promotion code and a coupon at the same time to a subscription or a customer
  • It’s not possible to stack two or more promotion codes