Apply a discount
Coupons let you apply a percentage or fixed-amount discount, with duration and scope rules. See Discounts & coupons for the full model.
1. Create the coupon
POST /v1/couponsIdempotency-Key: <uuid>{ "code": "SUMMER25", "type": "percent", "amount_off": "25", "duration": "repeating", "duration_in_months": 3, "max_redemptions": 1000, "applies_to": { "plan_codes": ["pro-monthly-usd"] }, "valid_until": "2026-08-31T23:59:59Z"}Most coupons are reusable templates. Once created, apply them to as
many subscriptions / customers as the max_redemptions cap allows.
2. Apply to a subscription
At create time:
{ "customer_id": "cus_…", "plan_code": "pro-monthly-usd", "coupons": ["SUMMER25"]}After the fact:
POST /v1/subscriptions/{id}/discounts{ "coupon_code": "SUMMER25" }The discount applies starting with the next invoice (or the upcoming
one if it’s still in draft). repeating discounts count down on each
invoice; on the last cycle, the discount auto-expires and emits
discount.expired.
Apply to a customer
A customer-level discount applies to every subscription that customer has, including future ones:
POST /v1/customers/{id}/discounts{ "coupon_code": "PARTNER10" }Use sparingly — it’s easy to forget that the partner discount is silently applying to every subsequent purchase.
Apply to a one-off invoice
POST /v1/invoices/{id}/discounts{ "coupon_code": "GOODWILL_50" }Only allowed while the invoice is draft. Once finalised, you’d
issue a credit note instead.
Promo codes
For customer-facing redemption, set up a promo code that maps to a coupon:
POST /v1/promotion-codes{ "code": "SUMMER25", "coupon_code": "summer25-internal", "active": true, "max_redemptions": 1000, "first_time_transaction": true, "minimum_amount": "20.00", "currency": "USD"}The same coupon can have multiple promo codes (SUMMER, SUMMER25,
AUGUST) for different campaigns. Use the dashboard’s redemption
analytics to see which campaign drove what.
To enable code entry on hosted checkout:
{ "allow_promotion_codes": true }Removing a discount
DELETE /v1/subscriptions/{id}/discounts/{discount_id}A removed discount stops applying on the next invoice. Already-issued invoices are untouched.
Listing applied discounts
GET /v1/subscriptions/{id}/discountsReturns every discount currently in effect, with cycles remaining and projected savings on the next invoice.
Common pitfalls
- Coupon code collisions. Two coupons with similar codes (
SAVE10vsSAVE_10) are easy for support to mis-apply. Pick a naming convention and stick to it. amountcoupons in the wrong currency. A USD coupon does not apply to an EUR invoice. Either create a per-currency variant or use apercentcoupon.- Discounts on annual plans applied as
duration: repeating, duration_in_months: 3— applies for one invoice (annual = 1 invoice = 1 cycle). Useoncefor annual.
Webhook events
| Event | When |
|---|---|
coupon.created / coupon.updated | Coupon CRUD. |
discount.applied | Coupon attached to a customer / subscription / invoice. |
discount.removed | Detached. |
discount.expired | A repeating discount used its last cycle. |
promotion_code.redeemed | A customer used a public promo code. |