Skip to main content

Discounts

PaymentKit offers a flexible discount system using Coupons and Promotion Codes. This allows you to provide various types of discounts to your customers, such as percentage-off, fixed amount-off, and limited-time offers.

  • Coupons: Define the core discount rules, such as the discount percentage or amount, duration (e.g., once, forever, repeating), and maximum total redemptions.
  • Promotion Codes: These are the customer-facing codes that are linked to a coupon. They can have their own set of rules, such as individual redemption limits, expiration dates, and restrictions (e.g., for first-time customers only).

You can think of a Coupon as a template for a discount, and Promotion Codes as specific instances of that discount that customers can use.

For a detailed breakdown of all available API operations, see the Coupons API Reference and Promotion Codes API Reference.

How Discounts Work

The following diagram illustrates the relationship between Coupons, Promotion Codes, and their application during a transaction.

Discounts

Creating Coupons

A Coupon object contains information about a discount, such as whether it's a percentage or a fixed amount. You can create coupons and then attach promotion codes to them.

Create a Coupon with Promotion Codes

You can create a coupon and one or more associated promotion codes in a single API call. This is useful for setting up a new campaign quickly.

Create Coupon with Promo Code

javascript
import payment from '@blocklet/payment-js';

async function createDiscountCampaign() {
  try {
    const result = await payment.coupons.create({
      name: 'New User Discount',
      percent_off: 20,
      duration: 'once',
      max_redemptions: 1000, // Max redemptions for the coupon itself
      promotion_codes: [
        {
          code: 'WELCOME20',
          description: 'Welcome discount for new users',
          max_redemptions: 100, // Max redemptions for this specific code
          expires_at: Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60) // 30 days from now
        }
      ]
    });

    console.log('Coupon created:', result.coupon);
    console.log('Promotion codes created:', result.promotion_codes);
  } catch (error) {
    console.error('Error creating coupon:', error.message);
  }
}

createDiscountCampaign();

Parameters

  • name string (required) — The name of the coupon, for internal display.
  • percent_off number — A percentage (0-100) that will be taken off the subtotal. Must not be provided if amount_off is set.
  • amount_off string — A fixed amount to be taken off the subtotal. Must not be provided if percent_off is set.
  • currency_id string — Required if amount_off is set. The ID of the currency for the fixed amount discount.
  • duration string (required) — Describes how long the discount will be applied. Can be once, forever, or repeating.
  • duration_in_months number — If duration is repeating, the number of months the coupon applies.
  • max_redemptions number — The maximum number of times the coupon can be redeemed.
  • redeem_by number — A Unix timestamp specifying the expiration date for the coupon.
  • promotion_codes array — An array of promotion code objects to create and attach to this coupon.
    • code string — The customer-facing code. If omitted, a random code will be generated.
    • max_redemptions number — Maximum number of times this specific promotion code can be used.
    • expires_at number — Unix timestamp for when this promotion code expires.
    • description string — An optional description for the promotion code.
  • metadata object — A set of key-value pairs to store additional information.

Creating Promotion Codes

While you can create promotion codes along with a coupon, you can also create them separately and attach them to an existing coupon. This is useful for generating multiple unique codes for a single campaign.

Create a Standalone Promotion Code

Create Promotion Code

javascript
import payment from '@blocklet/payment-js';

async function createPromoCode(couponId) {
  try {
    const promotionCode = await payment.promotionCodes.create({
      coupon_id: couponId, // ID of an existing coupon
      code: 'SAVE15NOW',
      description: 'Save 15% on your next purchase',
      max_redemptions: 500,
      restrictions: {
        first_time_transaction: true, // Only for new customers
      }
    });
    console.log('Promotion code created:', promotionCode);
  } catch (error) {
    console.error('Error creating promotion code:', error.message);
  }
}

createPromoCode('coupon_xxx'); // Replace with your actual coupon ID

Parameters

  • coupon_id string (required) — The ID of the coupon this promotion code should be attached to.
  • code string — The customer-facing code. If omitted, a random code will be generated.
  • active boolean (default: true) — Whether the promotion code is currently active.
  • max_redemptions number — Maximum number of times this specific promotion code can be used.
  • expires_at number — Unix timestamp for when this promotion code expires.
  • restrictions object — Applies restrictions to this promotion code.
    • first_time_transaction boolean — If true, the promotion code can only be redeemed by customers with no prior payments.
    • minimum_amount number — The minimum transaction amount required to use the code.
    • minimum_amount_currency string — The currency for the minimum amount.
  • metadata object — A set of key-value pairs to store additional information.

Applying Discounts at Checkout

To allow customers to enter a promotion code on the checkout page, you must explicitly enable this option when creating a Checkout Session or a Payment Link.

Enable on a Checkout Session

Set the allow_promotion_codes parameter to true when creating a Checkout Session. This will add a field to the payment page for customers to enter their code.

Enable Promotion Codes

javascript
import payment from '@blocklet/payment-js';

async function createCheckoutWithDiscounts() {
  try {
    const session = await payment.checkout.sessions.create({
      success_url: 'https://example.com/success',
      cancel_url: 'https://example.com/cancel',
      mode: 'payment',
      line_items: [
        { price_id: 'price_xxx', quantity: 1 }
      ],
      allow_promotion_codes: true // This enables the promo code field
    });
    console.log('Checkout session created with promotion codes enabled:', session.url);
  } catch (error) {
    console.error('Error creating checkout session:', error.message);
  }
}

createCheckoutWithDiscounts();

The same logic applies to reusable Payment Links. Setting allow_promotion_codes to true ensures that anyone using the link can apply a valid promotion code.

Enable on Payment Link

javascript
import payment from '@blocklet/payment-js';

async function createPaymentLinkWithDiscounts() {
  try {
    const paymentLink = await payment.paymentLinks.create({
      line_items: [{
        price_id: 'price_xxx',
        quantity: 1,
      }],
      allow_promotion_codes: true,
    });
    console.log('Payment link created with promotion codes enabled:', paymentLink.url);
  } catch (error) {
    console.error('Error creating payment link:', error.message);
  }
}

createPaymentLinkWithDiscounts();

Managing Discounts

The SDK provides various methods to manage and track your discounts.

Retrieve a Promotion Code by its Code

You can fetch a promotion code's details directly using the customer-facing code string.

Get Promotion Code by Code

javascript
import payment from '@blocklet/payment-js';

async function getPromoDetails(code) {
  try {
    const promoByCode = await payment.promotionCodes.byCode(code);
    console.log('Found promotion code:', promoByCode);
    // You can now access the associated coupon details
    console.log('Discount:', promoByCode.coupon);
  } catch (error) {
    console.error(`Promotion code '${code}' not found or an error occurred:`, error.message);
  }
}

getPromoDetails('WELCOME20');

Check Coupon Usage

Determine if a coupon has been redeemed at least once. This is useful for deciding whether a coupon's rules can still be edited.

Check Coupon Usage

javascript
import payment from '@blocklet/payment-js';

async function checkCouponUsage(couponId) {
  try {
    const { used } = await payment.coupons.used(couponId);
    if (used) {
      console.log(`Coupon ${couponId} has been used and its rules are now locked.`);
    } else {
      console.log(`Coupon ${couponId} has not been used yet.`);
    }
  } catch (error) {
    console.error('Error checking coupon usage:', error.message);
  }
}

checkCouponUsage('coupon_xxx'); // Replace with a valid coupon ID

List Redemptions

You can retrieve a paginated list of customers or subscriptions that have redeemed a specific coupon or promotion code.

List Coupon Redemptions

javascript
import payment from '@blocklet/payment-js';

async function getCouponRedemptions(couponId) {
  try {
    const redemptions = await payment.coupons.redemptions(couponId, {
      type: 'customer', // or 'subscription'
      page: 1,
      pageSize: 10
    });
    console.log(`Found ${redemptions.count} customer redemptions for coupon ${couponId}:`);
    redemptions.customers.forEach(customer => {
      console.log(`- Customer ID: ${customer.id}`);
    });
  } catch (error) {
    console.error('Error getting redemptions:', error.message);
  }
}

getCouponRedemptions('coupon_xxx'); // Replace with a valid coupon ID