Skip to content

Stripe Products & Prices: Managing Your Payment Catalog

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Stripe Products & Prices: Managing Your Payment Catalog. We cover key concepts, practical examples, and best practices to help you master this topic.

Stripe Products represent your goods or services, and Prices define how much customers pay with support for one-time, recurring, tiered, metered, and multi-currency pricing.

What You'll Learn

How to create Products and Prices, define recurring subscription pricing with tiers, set up metered billing for usage-based models, manage multiple currencies, and archive deprecated prices.

Why It Matters

A well-structured product catalog simplifies subscription management, enables multi-currency pricing, and supports complex billing models. DodaTech uses Products and Prices to offer Basic, Pro, and Enterprise tiers in 40+ countries.

Real-World Use

DodaTech defines a "Pro Plan" product with monthly ($15.99) and yearly ($159.99) prices. When a customer checks out, Stripe uses the correct price based on their selected billing interval and currency.

flowchart LR
    A["Define\nProduct"] --> B["Create\nPrices"]
    B --> C["One-Time\nPrice"]
    B --> D["Recurring\nPrice"]
    B --> E["Tiered\nPrice"]
    B --> F["Metered\nPrice"]
    C --> G["Checkout\nSession"]
    D --> H["Subscription"]
    E --> H
    F --> H
    style A fill:#6772e5,color:#fff
    style B fill:#dbeafe,stroke:#2563eb
    style H fill:#bbf7d0,stroke:#16a34a

Creating a Product

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

# Simple product
product = stripe.Product.create(
    name="Pro Plan",
    description="Advanced features for professionals",
    metadata={"plan_tier": "pro", "features": "unlimited_projects,priority_support"}
)
print(f"Product: {product.id} ({product.name})")
# Expected output:
# Product: prod_ProPlanABC123 (Pro Plan)

# Product with statement descriptor
product_branded = stripe.Product.create(
    name="Enterprise Plan",
    description="Custom enterprise solution with dedicated support",
    statement_descriptor="DODATECH ENTERPRISE",
    unit_label="license",
    metadata={"plan_tier": "enterprise"}
)
print(f"Product: {product_branded.id}")
print(f"Statement Descriptor: {product_branded.statement_descriptor}")
# Expected output:
# Product: prod_EnterpriseXYZ456
# Statement Descriptor: DODATECH ENTERPRISE

Creating Prices

# One-time price
price_one_time = stripe.Price.create(
    product=product.id,
    unit_amount=29999,
    currency="usd",
    nickname="Pro Lifetime Access"
)
print(f"One-time Price: {price_one_time.id}")
print(f"Amount: ${price_one_time.unit_amount/100:.2f}")
# Expected output:
# One-time Price: price_1OnetimeABC123
# Amount: $299.99

# Recurring price (monthly)
price_monthly = stripe.Price.create(
    product=product.id,
    unit_amount=1599,
    currency="usd",
    recurring={"interval": "month", "interval_count": 1},
    nickname="Pro Monthly"
)
print(f"Monthly Price: {price_monthly.id}")
# Expected output:
# Monthly Price: price_1MonthlyDEF456

# Recurring price (yearly, 2-month free)
price_yearly = stripe.Price.create(
    product=product.id,
    unit_amount=15999,
    currency="usd",
    recurring={"interval": "year"},
    nickname="Pro Yearly"
)
print(f"Yearly Price: {price_yearly.id}")
print(f"Savings vs monthly: ${(1599*12 - 15999)/100:.2f}")
# Expected output:
# Yearly Price: price_1YearlyGHI789
# Savings vs monthly: $31.89

Tiered and Metered Pricing

# Tiered pricing (volume-based)
price_tiered = stripe.Price.create(
    product=product.id,
    currency="usd",
    billing_scheme="tiered",
    tiers=[
        {"up_to": 100, "unit_amount": 100},     # $1 per unit for first 100
        {"up_to": 1000, "unit_amount": 80},      # 80 cents per unit for 101-1000
        {"up_to": "inf", "unit_amount": 60}       # 60 cents per unit beyond 1000
    ],
    tiers_mode="volume",  # or "graduated"
    recurring={"interval": "month", "usage_type": "metered"},
    nickname="API Calls (Volume)"
)
print(f"Tiered Price: {price_tiered.id}")
print(f"Tier 1: {price_tiered.tiers[0].up_to} @ ${price_tiered.tiers[0].unit_amount/100:.2f}")
# Expected output:
# Tiered Price: price_1TieredJKL012
# Tier 1: 100 @ $1.00

# Graduated tier example
price_graduated = stripe.Price.create(
    product=product.id,
    currency="usd",
    billing_scheme="tiered",
    tiers=[
        {"up_to": 1000, "flat_amount": 5000},         # $50 flat for first 1000
        {"up_to": 10000, "unit_amount": 5},           # 5 cents per unit 1001-10000
        {"up_to": "inf", "unit_amount": 2}            # 2 cents per unit beyond
    ],
    tiers_mode="graduated",
    recurring={"interval": "month"},
    nickname="Storage (Graduated)"
)
print(f"Graduated Price: {price_graduated.id}")
# Expected output:
# Graduated Price: price_1GradMNO345

Common Mistakes

1. Using the Same Price for Multiple Products

Prices are linked to a product at creation. To offer the same monetary amount for different products, create separate Price objects for each product.

2. Not Setting a Nickname

Without a nickname, you'll struggle to identify prices in the Dashboard. Always set a descriptive nickname like "Pro Monthly - USD" or "Pro Yearly - EUR".

3. Confusing Volume and Graduated Tiers

Volume tiering applies the same unit amount to all units based on the tier reached. Graduated tiering applies different amounts per tier bracket. For 1500 units, volume uses the $0.80 rate for everything; graduated uses $1.00 for first 100 and $0.80 for the next 1400.

4. Incorrect Multi-Currency Setup

Each currency needs its own Price object. Do not set currency: "multi" — create individual USD, EUR, GBP prices. Use Stripe's automatic currency conversion feature if needed.

5. Archiving In-Use Prices

You cannot delete a Price attached to active subscriptions. Set active: false to archive it. New customers won't see it, but existing subscriptions continue until the next renewal.

Practice Questions

  1. What is the relationship between a Product and a Price?
  2. How do you create a price that bills $49.99 monthly?
  3. What is the difference between volume and graduated tiering?
  4. How do you retire a price without breaking active subscriptions?

Answers:

  1. A Product describes what you sell (Pro Plan). A Price defines the cost and billing model ($15.99/month). One product can have multiple prices (monthly, yearly, different currencies).
  2. Create a Price with unit_amount: 4999, currency: "usd", and recurring: { interval: "month" }.
  3. Volume tiering uses one unit amount for all units based on the highest tier reached. Graduated tiering applies different amounts per bracket. Volume is simpler; graduated is more precise.
  4. Set active: false on the Price. Existing subscriptions continue unaffected. New subscriptions cannot use an inactive price.

Challenge: Build a complete catalog: create three products (Basic $9.99/month, Pro $29.99/month, Enterprise custom), add yearly equivalents with 2 months free, add EUR and GBP prices for each, create a tiered price for API usage, then archive the old pricing after Migration.

FAQ

Can I change a Price after creation?

No, Prices are immutable. You must create a new Price and update Subscriptions to use the new Price ID. Old prices can be archived with active: false.

What currency formatting does Stripe use?

Stripe uses the smallest currency unit (cents for USD, pence for GBP, cents for EUR). Always pass integer values. Zero-decimal currencies (JPY, KRW) use whole units.

How many Prices can a Product have?

There is no hard limit, but best practice is to keep it manageable (5-10 prices per product). Each currency-interval combination typically needs one price.

What is metered billing?

Metered billing charges based on usage (API calls, storage, bandwidth). Create a Price with recurring: { usage_type: metered }. Report usage via the Stripe API, and customers are billed at the end of each period.

How do I offer a free trial?

Free trials are set on the Subscription or Checkout Session, not on the Price. Set subscription_data: { trial_period_days: 14 } on the Checkout Session.

Mini Project

Build a SaaS product catalog: create a "Team Plan" product with monthly ($49.99), yearly ($499.99), and tiered per-seat ($10/seat for first 10, $8/seat beyond) prices, add EUR and GBP variants, archive an old deprecated plan, and verify the catalog renders correctly in a Checkout Session.

What's Next

Invoices — manage billing documents and payment collection.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro