Skip to main content

Coupons

Use billingData.couponCodes to pass one or more coupon codes for subscription estimation and creation.

Overview​

You can provide coupons in two ways:

  1. In the initial Create Session API request (billingData.couponCodes)
  2. By re-creating the session with the updated coupon list when the shopper adds or removes a coupon at checkout

couponCodes must be an array of strings.

{
"billingData": {
"couponCodes": ["SPRING25", "WELCOME10"]
}
}

Option 1: Pass coupons in Create Session API​

Send couponCodes during POST /api/session/v1/create.

{
"paymentData": {
"currency": "EUR",
"paymentMethod": "card"
},
"redirectUrl": "https://yourdomain.com/success",
"billingData": {
"lineItems": [
{
"type": "plan",
"id": "price_123",
"quantity": "1"
}
],
"billingPlatformId": "3287b8c7-ce43-41fd-9d58-f510e610b8f3",
"couponCodes": ["SPRING25", "WELCOME10"]
}
}

Option 2: Let shoppers apply coupons at checkout​

Coupons are part of the session's billingData, which is set server-side. To let shoppers add or remove coupons on your checkout page, re-create the session with the updated coupon list. Sessions are cheap and single-use, so this is the recommended pattern.

This is exactly how the Altruon Merchant Demo does it (see client/src/pages/CheckoutPage.jsx and server/src/routes.js):

// Frontend: coupon state drives session creation. Whenever the shopper
// applies or removes a coupon, the checkout asks the backend for a FRESH
// session that includes the updated coupon list.
const [couponCodes, setCouponCodes] = useState([]);

useEffect(() => {
// (Re)create the session whenever pricing inputs change.
initializeCheckout(); // → POST /api/session { couponCodes, ... }
}, [couponCodes]);
// Backend: forward the coupon list into billingData on session creation.
const data = await createSession({
paymentData: { currency: cfg.currency },
redirectUrl,
billingData: {
billingPlatformId: cfg.billingConnectionId,
lineItems: buildLineItems(cfg),
...(couponCodes?.length ? { couponCodes } : {}),
},
});

To show the discount before the shopper pays, pair this with the estimate endpoint (POST /api/checkout/v1/{billingConnectionId}/estimate-subscription), which prices the subscription (including coupon discount and tax) without creating anything. The demo's live order summary (client/src/components/OrderSummary.jsx) re-runs the estimate every time the coupon list or billing country changes.

Provider expectations​

Use couponCodes consistently in Altruon. Altruon maps values per provider as follows:

Chargebee​

  • Input in Altruon: couponCodes: string[]
  • Sent to Chargebee as: coupon_ids
  • Important: values should be valid Chargebee coupon IDs

Recurly​

  • Input in Altruon: couponCodes: string[]
  • Sent to Recurly as: coupon_codes
  • Important: values should be valid Recurly coupon codes

Stripe Billing​

  • Input in Altruon: couponCodes: string[]
  • Sent to Stripe as: discounts[].coupon
  • Important: values are treated as Stripe coupon IDs (not promotion code IDs)

Frisbii​

  • Input in Altruon: couponCodes: string[]
  • Sent to Frisbii as: coupon_codes
  • Important: values should be valid Frisbii coupon codes

Behavior notes​

  • Multiple coupons are supported (couponCodes array)
  • Empty array means no coupon is sent
  • Invalid/unknown coupons are rejected by the billing provider
  • Always test coupons in sandbox before production