Coupons
Create discount codes customers can apply at checkout. Percentage or fixed-amount, time-limited or capped, one-time or recurring.
Coupons are managed in the builder’s Commerce panel > Products > Coupons sub-tab, or through the SDK at proyecta.commerce.coupons.
Anatomy of a coupon
Section titled “Anatomy of a coupon”| Field | Notes |
|---|---|
code | The promo code customers type at checkout (e.g. LAUNCH20) |
percent_off or amount_off | Mutually exclusive. Percent is 1–100. Amount is in the smallest currency unit (cents). |
currency | Required for amount_off discounts (three-letter ISO code). Accepted on creation and forwarded to Stripe, but not stored or returned by the API afterward. |
duration | once (first payment only), repeating (for duration_in_months), or forever |
duration_in_months | Required when duration is repeating |
max_redemptions | Total cap across all customers |
redeem_by | Expiration date after which the coupon stops working |
name | Display name shown to customers |
active | Toggle to enable/disable without deleting |
Create a coupon
Section titled “Create a coupon”From the Coupons sub-tab, click Add coupon and fill in the fields. Or via the SDK:
// 20% off foreverawait proyecta.commerce.coupons.create({ code: 'LAUNCH20', name: 'Launch discount', percent_off: 20, duration: 'forever',});
// $10 off, single use, expires in 30 daysawait proyecta.commerce.coupons.create({ code: 'WELCOME10', amount_off: 1000, currency: 'USD', duration: 'once', max_redemptions: 1, redeem_by: new Date(Date.now() + 30 * 86400 * 1000).toISOString(),});
// 50% off for the first 3 months of a subscriptionawait proyecta.commerce.coupons.create({ code: 'EARLY3', percent_off: 50, duration: 'repeating', duration_in_months: 3,});Apply a coupon at checkout
Section titled “Apply a coupon at checkout”Customers can enter the coupon code themselves on the Stripe-hosted checkout page — the promo code field is shown automatically.
await proyecta.commerce.checkout({ customer_id, line_items: [{ variant_id: 'var_pro_monthly' }], success_url: 'https://myapp.com/welcome',});Passing a coupon code programmatically in the checkout call is not yet supported.
List, update, deactivate
Section titled “List, update, deactivate”// Browse every coupon (only lists coupons created via the SDK)const { data } = await proyecta.commerce.coupons.list();for (const coupon of data.data) { console.log(coupon.code, coupon.times_redeemed, '/', coupon.max_redemptions);}// Paginate using data.has_more and the starting_after query parameter if needed.
// Disable a coupon (without deleting)await proyecta.commerce.coupons.update({ couponId: 'coupon_123', active: false });Note:
coupons.list()only returns coupons created via the SDK. Coupons created in the builder Dashboard are not visible throughcoupons.list().
Notes and limits
Section titled “Notes and limits”- Codes and discount amounts are immutable. You can update the display
nameand toggleactive, but notpercent_off,amount_off, orcodeitself. Create a new coupon if you need different terms. times_redeemedauto-increments and is read-only — useful for tracking campaign performance.- Coupons apply per customer, not per order — if a coupon is
foreverand a customer subscribes, every renewal gets the discount.