Skip to content

Stripe Coupons & Promotions: Discount Codes and Price Reductions

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Stripe Coupons & Promotions: Discount Codes and Price Reductions. We cover key concepts, practical examples, and best practices to help you master this topic.

Stripe Coupons and Promotion Codes let you apply discounts to one-time payments and subscriptions, supporting percentage off, fixed amount off, free trials, and usage limits.

What You'll Learn

How to create coupons and promotion codes, apply discounts to Checkout Sessions and subscriptions, manage discount durations, validate promotion codes, and handle coupon stacking.

Why It Matters

Discounts increase conversion by 20-40% and are essential for promotional campaigns, customer acquisition, and retention. DodaTech uses Stripe coupons for seasonal discounts on Pro plans.

Real-World Use

A user enters promo code SUMMER20 at checkout. Stripe validates the code, applies a 20% discount to the first invoice, and the customer sees the reduced amount before completing payment.

flowchart LR
    A["Customer\nEnters Code"] --> B["Validate\nPromotion Code"]
    B --> C{"Code\nValid?"}
    C -->|Yes| D["Apply\nDiscount"]
    C -->|No| E["Error:\nInvalid Code"]
    D --> F["Update\nInvoice Total"]
    F --> G["Customer\nPays Discounted"]
    style B fill:#dbeafe,stroke:#2563eb
    style D fill:#bbf7d0,stroke:#16a34a
    style E fill:#fecaca,stroke:#dc2626

Creating a Coupon

import stripe
stripe.api_key = "sk_test_..."

# Percentage discount
coupon = stripe.Coupon.create(
    percent_off=20,
    duration="once",
    name="20% Off",
    max_redemptions=100,
    redeem_by=1767225599  # Unix timestamp
)
print(f"Coupon: {coupon.id}")
print(f"Percent Off: {coupon.percent_off}%")
print(f"Duration: {coupon.duration}")
# Expected output:
# Coupon: HJ4cQ3p4
# Percent Off: 20%
# Duration: once

# Fixed amount discount
coupon_fixed = stripe.Coupon.create(
    amount_off=1000,
    currency="usd",
    duration="repeating",
    duration_in_months=3,
    name="$10 Off for 3 Months"
)
print(f"Fixed Coupon: {coupon_fixed.id}")
print(f"Amount Off: ${coupon_fixed.amount_off/100:.2f}")
# Expected output:
# Fixed Coupon: 7kLmN2oP
# Amount Off: $10.00

Creating Promotion Codes

def create_promotion_code(coupon_id, code_name, restrictions=None):
    params = {
        "coupon": coupon_id,
        "code": code_name,
        "active": True,
    }
    if restrictions:
        params["restrictions"] = restrictions
    promo = stripe.PromotionCode.create(**params)
    print(f"Promo Code: {promo.code}")
    print(f"Active: {promo.active}")
    print(f"Restrictions: {promo.restrictions}")
    return promo

# Simple code without restrictions
promo = create_promotion_code(
    coupon_id="HJ4cQ3p4",
    code_name="SUMMER20"
)
# Expected output:
# Promo Code: SUMMER20
# Active: True
# Restrictions: {}

# Code with first-time customer restriction
promo_restricted = create_promotion_code(
    coupon_id="7kLmN2oP",
    code_name="WELCOME10",
    restrictions={"first_time_transaction": True}
)
print(f"First-time only: {promo_restricted.restrictions.first_time_transaction}")
# Expected output:
# First-time only: True

Applying Promotion Codes at Checkout

import stripe

def create_checkout_with_promo(price_id, promo_code, customer_id):
    session = stripe.checkout.Session.create(
        success_url="https://example.com/success",
        cancel_url="https://example.com/cancel",
        mode="subscription",
        line_items=[{"price": price_id, "quantity": 1}],
        customer=customer_id,
        discounts=[{"promotion_code": promo_code}],
        allow_promotion_codes=False  # Disable manual entry for predefined code
    )
    print(f"Session URL: {session.url}")
    print(f"Discounts: {len(session.discounts)}")
    return session

# Alternatively, allow customers to enter their own code:
def create_checkout_with_manual_promo(price_id, customer_id):
    session = stripe.checkout.Session.create(
        success_url="https://example.com/success",
        cancel_url="https://example.com/cancel",
        mode="subscription",
        line_items=[{"price": price_id, "quantity": 1}],
        customer=customer_id,
        allow_promotion_codes=True  # Customer types code themselves
    )
    print(f"Promo codes enabled: {session.allow_promotion_codes}")
    return session

Common Mistakes

1. Setting duration: once for Subscriptions

A one-time coupon applies only to the first invoice. For ongoing discounts, use duration: forever or duration: repeating with duration_in_months.

2. Not Setting max_redemptions

Without a limit, a single coupon can be used unlimited times. Always set max_redemptions for promotional campaigns with a budget.

3. Confusing Coupons and Promotion Codes

A Coupon is the discount definition (20% off). A Promotion Code is the redeemable code (SUMMER20) linked to a coupon. One coupon can have many promotion codes.

4. Ignoring Promotion Code Restrictions

First-time Transaction restrictions prevent existing customers from reusing welcome offers. Set first_time_transaction: true for acquisition campaigns.

5. Applying Discounts After Payment

You cannot retroactively apply a coupon to a completed PaymentIntent or invoice. Create the discount before the customer pays or issue a partial refund.

Practice Questions

  1. What is the difference between a Coupon and a Promotion Code?
  2. How do you create a recurring discount that applies for 6 months?
  3. What restriction ensures a promo code only works for new customers?
  4. How do you let customers enter their own promo code at checkout?

Answers:

  1. A Coupon defines the discount rule (percentage or fixed amount). A Promotion Code is the redeemable string customers enter, linked to a coupon. One coupon can have multiple codes.
  2. Create a coupon with duration: repeating and duration_in_months: 6. The discount applies to the first 6 invoices.
  3. Set restrictions: { first_time_transaction: true } when creating the Promotion Code.
  4. Set allow_promotion_codes: true on the Checkout Session or Subscription. The customer enters their code in Stripe's hosted UI.

Challenge: Build a complete promotion system: create a 25% off coupon with 500 max redemptions, generate a unique promotion code SUMMER25, create a Checkout Session that accepts manual promo code entry, and verify the discount applies to the subscription Invoice.

FAQ

Can I have multiple active promotion codes?

Yes, you can create unlimited promotion codes linked to the same or different coupons, each with unique codes and restrictions.

How does Stacking work?

Stripe does not support stacking multiple coupons on the same invoice. The customer can only use one promotion code per Checkout Session or subscription renewal.

Can I update a coupon after creation?

No, coupons are immutable after creation including amount, duration, and currency. Create a new coupon and deactivate the old one.

Do discounts apply to recurring invoices?

It depends on the coupon duration. 'once' applies to the first invoice only. 'forever' applies to all future invoices. 'repeating' applies for a specified number of months.

How do I report on coupon usage?

Stripe provides coupon and promotion code usage metrics in the Dashboard. You can also query the Coupon API for times_redeemed and max_redemptions fields programmatically.

Mini Project

Build a promotion system: create two coupons (20% once, $5 forever), generate promotion codes for each, create a Checkout Session with allow_promotion_codes, test the codes with different test customers, verify discount application on Invoices, and monitor redemption limits.

What's Next

Products & Prices — define your product catalog and pricing model.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro