> For the complete documentation index, see [llms.txt](https://developer.paddle.com/llms.txt).

# Create and manage discounts

Attract new customers and entice existing ones to upgrade using discounts. They're sometimes called promotions or coupons.

---

Discounts let you reduce the amount that a customer has to pay. You may run discounts as part of promotions, or as a way to incentivize customers to upgrade or buy more.

## How it works

Discounts are applied to the total value of the checkout or transaction. The type of discount determines how the total is impacted.

{% feature-comparison cols=3 %}

{% feature-column title="Percentage" %}

{% feature-item %}
A percentage taken from the full value of the checkout or transaction.

{% /feature-item %}

{% feature-item title="Example" %}
If the total is $100 and the discount is 10%, the customer pays $90.
{% /feature-item %}

{% /feature-column %}

{% feature-column title="Flat amount" %}

{% feature-item %}
A set amount that's subtracted from the full value of the checkout or transaction.

{% /feature-item %}

{% feature-item title="Example" %}
If the total is $100 and the discount is $20, the customer pays $80.
{% /feature-item %}

{% /feature-column %}

{% feature-column title="Per unit amount" %}

{% feature-item %}
A set amount that's subtracted from each quantity of an item in the checkout or transaction.

{% /feature-item %}

{% feature-item title="Example" %}
If there are 10 items at $10 each and the discount is $5, the customer pays $50.

{% /feature-item %}

{% /feature-column %}

{% /feature-comparison %}

### Redemptions

You can discount a transaction in two ways:

- **Customer applying a discount code**  
   During checkout, the customer can enter a discount code. You can set whether discounts can be applied at checkout or whether they're turned off when you [initialize Paddle.js](https://developer.paddle.com/paddlejs/include-paddlejs.md) or [open the checkout](https://developer.paddle.com/paddlejs/methods/paddle-checkout-open.md).
- **Applying a discount to a transaction directly**  
   You can open a checkout with a discount already applied, or add a discount to any transaction that hasn't yet been billed.

{% callout type="info" %}

You can't apply a discount to a transaction that's already been billed. You should use an adjustment to [refund or credit a transaction](https://developer.paddle.com/build/transactions/create-transaction-adjustments.md) instead.

{% /callout %}

Paddle counts when discounts are redeemed so you can keep track of how many times a discount has been used.

A redemption counts when a transaction is completed, or on the initial application against a subscription.

If a discount is present on a transaction created for subscription renewals, midcycle changes, and one-time charges, this doesn't count as a redemption.

### Rules and limits

Discounts in Paddle are flexible and powerful. You can set specific rules and restrictions on how they're applied to a transaction or across multiple transactions to give you the freedom to run promotions and discounts in a way that works for you.

#### Recurring discounts

By default, discounts are one-time. This means they're only applied on the first transaction or checkout that you add them to.

You can create recurring discounts which apply to the current transaction and future transactions where a customer has a [subscription](https://developer.paddle.com/api-reference/subscriptions/overview.md). Discounts can recur forever, or for a number of billing periods you specify.

When recurring discounts start applying to transactions depends on if a subscription has a [free trial period](https://developer.paddle.com/build/subscriptions/update-trials.md):

- **With a free trial**  
   The discount only applies once the trial period ends. For example, a recurring discount set for 4 billing periods applies to the first paid billing period after the trial and the next 3 renewals.
- **Without a free trial**  
   The discount applies immediately. For example, a recurring discount set for 4 billing periods applies to the initial transaction and the next 3 renewals.

In both cases, the discount applies to any subscription changes within those periods.

#### Usage limits

You can prevent discounts from being valid after certain conditions have been met.

- **Time-based**  
   Once a set date has passed, the discount can no longer be applied to checkouts or transactions.
- **Amount-based**  
   Once a discount has been redeemed a certain amount of times, the discount can no longer be applied to checkouts or transactions.

Amount-based limits are a total limit for the discount, rather than a per-customer limit.

{% callout type="info" %}
Expired and fully redeemed discounts can't be redeemed against transactions or checkouts, but can be applied when updating subscriptions.
{% /callout %}

#### Item restrictions

By default, a discount applies to all items on a transaction. You may want a discount to only be applied to specific items at checkout. For example, only annual plans, or specific regional price points.

To do this, you can provide a list of:

- **Products**  
   Restricts the discount to apply to all prices for that product.
- **Prices**  
   Restricts the discount to only apply to that specific price for a product.

{% callout type="info" %}

The discount applies only to the individual item it's restricted to. You can't limit a discount to apply to the full total only when set items are present.

{% /callout %}

#### Checkout restrictions

Customers can apply discounts to checkouts using a discount code. You can assign a discount code, or can have Paddle automatically generate one for you.

However, you may not want customers to be able to apply a discount at checkout. This is useful when you want to control who has access to a discount, like with non-transferable custom discounts only valid for particular customers. To achieve this, you can set a discount to be turned off at checkout.

If discounts aren't enabled for use at checkout, Paddle won't automatically generate a code. The discount can only be applied by passing the discount to the checkout or transaction directly using its `id`.

{% callout type="note" %}
You can also use the `showAddDiscounts` parameter to determine whether Paddle Checkout presents customers with the option to enter a discount. See [Pass checkout settings](https://developer.paddle.com/build/checkout/set-up-checkout-default-settings#hide-option-to-add-discount.md)
{% /callout %}

#### Currency restrictions

Discounts for a flat amount or per-seat amount are currency-specific. They have a currency and can only be applied to transactions in the same currency.

For example, you can't apply a flat amount type discount (`type: flat`) with a currency of `USD`
(`currency_code: USD`) to a transaction with the currency of `GBP` (`currency_code: GBP`).

{% callout type="info" %}
[Non-catalog discounts](#background-non-catalog-discounts) use the transaction's currency. A new transaction must have a `currency_code` if the discount being applied is for a flat amount or per-seat amount.
{% /callout %}

### Discount groups

You can [create groups](#create-discount-group) to assign discounts under. Discounts could be categorized by usage or team, like:

- Marketing and new customer prospects that would be used by the marketing team.
- Retention or loyalty that would be used by customer service or operational teams.
- Seasonal promotions or campaigns like Black Friday or Cyber Monday.

This makes your discounts more easily identifiable and easier to manage as your catalog grows or as discounts become redundant.

### Non-catalog discounts

When you [create a discount](#create-discount), it gets added to your discount catalog. These discounts can be used against any transaction, and at checkout by default. However, you may want to apply a discount to a single transaction which isn't recorded in your catalog.

{% feature-comparison level=4 %}

{% feature-column title="Catalog discounts" %}
{% feature-item %}
For broadly distributed and repeatable discounts.
{% /feature-item %}
{% feature-item %}
When you want to track, report, and attribute performance to the same discount.
{% /feature-item %}
{% feature-item %}
When customers need to be able to add discounts at checkout.
{% /feature-item %}
{% feature-item %}
For example, you may run a public seasonal promotion like for Black Friday, or allow all users in a specific segment to use a discount like non-profits or new customers.
{% /feature-item %}
{% /feature-column %}
{% feature-column title="Non-catalog discounts" %}
{% feature-item %}
For one-off, highly targeted, or private offers.
{% /feature-item %}
{% feature-item %}
When a single customer should have access to a discount.
{% /feature-item %}
{% feature-item %}
When you have many custom discounts of varying prices and amounts.
{% /feature-item %}
{% feature-item %}
For example, you may agree on a discounted price for a specific customer's next transaction to prevent churn, or incentivize them to complete a renewal.
{% /feature-item %}
{% /feature-column %}

{% /feature-comparison %}

Non-catalog discounts can only be applied directly to a transaction and can't be added by customers using [Paddle Checkout](https://developer.paddle.com/concepts/sell/self-serve-checkout.md). They don't show in the Paddle dashboard or when [listing discounts through the API](https://developer.paddle.com/api-reference/discounts/list-discounts.md).

{% callout type="info" %}
You can also turn on [checkout recovery](https://developer.paddle.com/build/checkout/checkout-recovery.md) to offer discounts to recover abandoned checkouts. These discounts are non-catalog, non-transferable, and only applicable to the transaction that's recovered.
{% /callout %}

## Before you begin

To open a checkout with a discount, you'll need to first:

- [Set your default payment link](https://developer.paddle.com/build/transactions/default-payment-link.md) under **Paddle > Checkout > Checkout settings > Default payment link**.
- Get your default payment link domain approved, if you're working with the live environment.

## Create a discount

Create discounts to add them to your catalog for usage against checkouts and transactions.

{% tabs sync="interaction-preference" %}
{% tab-item title="Dashboard" %}

{% instruction-steps %}

1. Go to **Paddle > Catalog > Discounts**.
2. Click {% mock-button icon="carbon:add" %}New discount
3. Enter the details for your new discount.
4. Toggle **Recurring discount** and select from the dropdown if you want the discount to apply across subsequent transactions.
5. Select **Set an expiration date for the discount** if you want to set a date and time the discount is no longer applicable.
6. Select **Limit the number of times this discount can be redeemed** if you want to set an amount of redemptions before the discount is no longer applicable.
7. Toggle **Checkout discount code** to set a discount code that customers can apply at checkout.
8. Toggle **Limit discount to selected products** if you want to select products or prices which the discount should only be applicable to.
9. Click Save

{% /instruction-steps %}

{% /dashboard-instructions %}

{% /tab-item %}
{% tab-item title="API" %}

Send a `POST` request to the `/discounts` endpoint to create a discount.

In your request, include `type`, `amount`, and `description`.

- For `flat` or `flat_per_seat` types, also include `currency_code`.
- Optionally set `code` for customers to use at checkout. If `enabled_for_checkout` is `true` and no `code` is provided, Paddle generates one.
- Set `recur: true` to apply the discount to future billing periods; optionally limit recurrences with `maximum_recurring_intervals`.
- Set `expires_at` to expire after a datetime, or `usage_limit` to expire after a number of redemptions.
- Use `restrict_to` with an array of product or price IDs to limit which items the discount applies to.

{% accordion %}
{% accordion-item title="Create a discount with a code" %}

This example creates a new flat discount called "New Customers." It has a code of `NEWCUST` which can be applied at checkout to get $5 off every purchase. `currency_code` is required as the `type` is `flat`.

If successful, Paddle responds with a copy of the new discount entity. Paddle creates an `id` starting with `dsc_` for you.

{% api-example method="POST" path="/discounts" href="/api-reference/discounts/create-discount" %}

```json
{
  "description": "New Customers",
  "type": "flat",
  "amount": "500",
  "currency_code": "USD",
  "code": "NEWCUST"
}
```
```json
{
  "data": {
    "id": "dsc_01jz8dxadfqnnv74hymjq6nvkf",
    "status": "active",
    "description": "New Customers",
    "enabled_for_checkout": false,
    "code": "NEWCUST",
    "type": "flat",
    "amount": "500",
    "currency_code": "USD",
    "recur": false,
    "maximum_recurring_intervals": null,
    "usage_limit": null,
    "restrict_to": null,
    "expires_at": null,
    "mode": "standard",
    "times_used": 0,
    "custom_data": null,
    "import_meta": null,
    "discount_group_id": null,
    "created_at": "2025-07-03T15:19:02.831Z",
    "updated_at": "2025-07-03T15:19:02.831Z"
  },
  "meta": {
    "request_id": "6d69fd6b-8385-4c20-a401-e0ec1d05a7f7"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% accordion-item title="Create a recurring discount" %}

This example creates a new discount called "All orders (10% off)." It recurs for a maximum of 4 billing periods after the first transaction.

If successful, Paddle responds with a copy of the new discount entity. Paddle creates an `id` starting with `dsc_` for you.

{% api-example method="POST" path="/discounts" href="/api-reference/discounts/create-discount" %}

```json
{
  "description": "All orders (10% off)",
  "type": "percentage",
  "amount": "10",
  "code": "BF10OFF",
  "enabled_for_checkout": true,
  "recur": true,
  "maximum_recurring_intervals": 3,
  "expires_at": "2024-12-03T00:00:00Z",
  "discount_group_id": "dsg_01js2gqehzccfkywgx1jk2mtsp"
}
```
```json
{
  "data": {
    "id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
    "status": "active",
    "description": "All orders (10% off)",
    "enabled_for_checkout": true,
    "code": "BF10OFF",
    "type": "percentage",
    "mode": "standard",
    "amount": "10",
    "currency_code": null,
    "recur": true,
    "maximum_recurring_intervals": 3,
    "usage_limit": null,
    "restrict_to": null,
    "expires_at": "2024-12-03T00:00:00Z",
    "times_used": 0,
    "discount_group_id": "dsg_01js2gqehzccfkywgx1jk2mtsp",
    "custom_data": null,
    "import_meta": null,
    "created_at": "2024-11-28T14:36:14.695Z",
    "updated_at": "2024-11-28T14:36:14.695Z"
  },
  "meta": {
    "request_id": "1681f87f-9c36-4557-a1da-bbb622afa0cc"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% accordion-item title="Create an expiring discount" %}

This example creates a new discount called "Limited July 2026 Promotion." It's set to expire at the end of July with a maximum of 1000 redemptions before it's invalid. `currency_code` is required as the `type` is `flat_per_seat`.

If successful, Paddle responds with a copy of the new discount entity. Paddle creates an `id` starting with `dsc_` for you.

{% api-example method="POST" path="/discounts" href="/api-reference/discounts/create-discount" %}

```json
{
  "description": "Limited July 2025 Promotion",
  "type": "flat_per_seat",
  "amount": "700",
  "currency_code": "USD",
  "code": "JULY2025PROMO",
  "expires_at": "2026-07-31T23:59:59.999Z",
  "usage_limit": 1000
}
```
```json
{
  "data": {
    "id": "dsc_01jz8f6p33mpkb9pk83xjx2ba6",
    "status": "active",
    "description": "Limited July 2025 Promotion",
    "enabled_for_checkout": false,
    "code": "JULY2025PROMO",
    "type": "flat",
    "amount": "700",
    "currency_code": "USD",
    "recur": false,
    "maximum_recurring_intervals": null,
    "usage_limit": 1000,
    "restrict_to": null,
    "expires_at": "2026-07-31T23:59:59.999Z",
    "mode": "standard",
    "times_used": 0,
    "custom_data": null,
    "import_meta": null,
    "discount_group_id": null,
    "created_at": "2026-07-03T15:41:38.275Z",
    "updated_at": "2026-07-03T15:41:38.275Z"
  },
  "meta": {
    "request_id": "a9f11e36-7b6b-446d-a007-6da676f3ecbf"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% accordion-item title="Create a discount limited to select prices" %}

This example creates a new discount called "Annual renewals (20% off)." It's restricted to only be applicable to transactions for annual prices across multiple products, and not available for customers to insert at checkout.

If successful, Paddle responds with a copy of the new discount entity. Paddle creates an `id` starting with `dsc_` for you.

{% api-example method="POST" path="/discounts" href="/api-reference/discounts/create-discount" %}

```json
{
  "description": "Annual renewals (20% off)",
  "type": "percentage",
  "amount": "20",
  "enabled_for_checkout": false,
  "restrict_to": [
    "pri_01jv7cypftwz5da2zxggr6sxfa",
    "pri_01jv76qc4e46yxgjksp88y7fpy"
  ]
}
```

```json
{
  "data": {
    "id": "dsc_01jz8fnwmdpq9prsadz7gc4hqb",
    "status": "active",
    "description": "Annual renewals (20% off)",
    "enabled_for_checkout": false,
    "code": null,
    "type": "percentage",
    "amount": "20",
    "currency_code": null,
    "recur": false,
    "maximum_recurring_intervals": null,
    "usage_limit": null,
    "restrict_to": [
      "pri_01jv7cypftwz5da2zxggr6sxfa",
      "pri_01jv76qc4e46yxgjksp88y7fpy"
    ],
    "expires_at": null,
    "mode": "standard",
    "times_used": 0,
    "custom_data": null,
    "import_meta": null,
    "discount_group_id": null,
    "created_at": "2025-07-03T15:49:56.493Z",
    "updated_at": "2025-07-03T15:49:56.493Z"
  },
  "meta": {
    "request_id": "1c20ae9c-6ba2-4545-a244-716dfc85fe55"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% /accordion %}

{% /tab-item %}
{% /tabs %}

## Apply a discount

Customers can apply discounts to a checkout by using a discount code during their transaction. You can also automatically apply a discount to a checkout when you open it in your frontend, or directly to a transaction using the API.

You can apply non-catalog discounts directly to transactions through the API. Non-catalog discounts are intended as custom, one-off discounts which aren't part of your catalog. They can't be applied at checkout by customers, or applied automatically to a checkout when opened.

{% callout type="info" %}
`enabled_for_checkout` must be `true` against [the discount entity](https://developer.paddle.com/api-reference/discounts/overview.md) to apply it to a checkout. Non-catalog discounts always have `enabled_for_checkout` set to `false`.
{% /callout %}

{% tabs %}
{% tab-item title="JavaScript (Paddle.js)" %}

You can pass either a `discountCode` or `discountId` when opening a Paddle Checkout using Paddle.js.

Pass parameters to the `Paddle.Checkout.open()` method to prefill those values on a checkout.

```js {% title="Paddle.js example" collapse=true %}
Paddle.Checkout.open({
  settings: {
    theme: "light",
    locale: "en"
  },
  discountId: "dsc_01gp0ynsntfpyw2spd2md1wqx1",
  items: [
    {
      priceId: 'pri_01gm81eqze2vmmvhpjg13bfeqg',
      quantity: 1
    },
    {
      priceId: 'pri_01gm82kny0ad1tk358gxmsq87m',
      quantity: 1
    },
    {
      priceId: 'pri_01gm82v81g69n9hdb0v9sw6j40',
      quantity: 1
    }
  ]
});
```

To learn more, see [`Paddle.Checkout.open()`](https://developer.paddle.com/paddlejs/methods/paddle-checkout-open.md)

{% callout type="note" %}
You can update properties on an open checkout using the [`Paddle.Checkout.updateCheckout()`](https://developer.paddle.com/paddlejs/methods/paddle-checkout-updatecheckout.md) method.
{% /callout %}

{% /tab-item %}
{% tab-item title="HTML data attributes (Paddle.js)" %}

You can pass either a `discountCode` or `discountId` when opening a Paddle Checkout using Paddle.js.

Add data attributes to your checkout launcher to prefill those values on a checkout.

```html {% title="Checkout launcher element" collapse=true %}
<a href='#'
  class='paddle_button'
 data-display-mode='overlay'
 data-theme='light'
  data-locale='en'
  data-discount-id='dsc_01gp0ynsntfpyw2spd2md1wqx1'
  data-discount-code='10OFF'
 data-items='[
    {
      "priceId": "pri_01gm81eqze2vmmvhpjg13bfeqg",
      "quantity": 1
    },
    {
      "priceId": "pri_01gm82kny0ad1tk358gxmsq87m",
      "quantity": 1
    },
    {
      "priceId": "pri_01gm82v81g69n9hdb0v9sw6j40",
      "quantity": 1
    }
  ]'
>
 Buy now
</a>
```

To learn more, see [HTML data attributes](https://developer.paddle.com/paddlejs/html-data-attributes.md)

{% /tab-item %}
{% tab-item title="Backend (API)" %}

Send a request to the `/transactions` endpoint to create a transaction.

In your request, include either a `discount_id` to apply a discount from your catalog or a `discount` object with `type`, `amount`, `description`.

Optionally include `recur`, `maximum_recurring_intervals`, and `restrict_to` for a [non-catalog discount](#background-non-catalog-discounts).

{% callout type="warning" %}
For non-catalog flat discounts, include `currency_code` on the transaction. For `flat` or `flat_per_seat` catalog discounts, the discount's currency must match the transaction's `currency_code`.
{% /callout %}

{% accordion %}
{% accordion-item title="Create a transaction with a catalog discount" %}

This request creates a new transaction with a discount from your catalog applied using the `id` of the discount.

If successful, Paddle responds with a copy of the updated transaction entity with the `id` of the discount as `discount_id`.

{% api-example method="POST" path="/transactions" href="/api-reference/transactions/create-transaction" %}

```json
{
  "items": [
    {
      "quantity": 10,
      "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke"
    }
  ],
  "customer_id": "ctm_01gzgmxdmgkgc7p94b5kgqq82p",
  "address_id": "add_01gzkce0amtjsqv8xxd1rv3dna",
  "currency_code": "GBP",
  "discount_id": "dsc_01gy7qp5pqhnyd22yspwane77h"
}
```

```json
{
  "data": {
    "id": "txn_01gzkcdstcwq4cj8waj812v9my",
    "status": "ready",
    "customer_id": "ctm_01gzgmxdmgkgc7p94b5kgqq82p",
    "address_id": "add_01gzkce0amtjsqv8xxd1rv3dna",
    "business_id": null,
    "custom_data": null,
    "origin": "api",
    "collection_mode": "automatic",
    "subscription_id": null,
    "invoice_id": null,
    "invoice_number": null,
    "billing_details": null,
    "billing_period": null,
    "currency_code": "GBP",
    "discount_id": "dsc_01gy7qp5pqhnyd22yspwane77h",
    "created_at": "2025-05-04T12:40:07.834144Z",
    "updated_at": "2025-05-04T12:40:07.834144Z",
    "billed_at": null,
    "items": [
      {
        "price": {
          "id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
          "description": "Monthly (per seat)",
          "name": "Monthly (per seat)",
          "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
          "billing_cycle": {
            "interval": "month",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "3000",
            "currency_code": "GBP"
          },
          "unit_price_overrides": [],
          "quantity": {
            "minimum": 10,
            "maximum": 999
          },
          "status": "active"
        },
        "quantity": 10
      }
    ],
    "details": {
      "tax_rates_used": [
        {
          "tax_rate": "0.2",
          "totals": {
            "subtotal": "30000",
            "discount": "3000",
            "tax": "5400",
            "total": "32400"
          }
        }
      ],
      "totals": {
        "subtotal": "30000",
        "tax": "5400",
        "discount": "3000",
        "total": "32400",
        "grand_total": "32400",
        "fee": null,
        "credit": "0",
        "balance": "32400",
        "earnings": null,
        "currency_code": "GBP"
      },
      "adjusted_totals": {
        "subtotal": "30000",
        "tax": "5400",
        "total": "32400",
        "grand_total": "32400",
        "fee": "0",
        "earnings": "0",
        "currency_code": "GBP"
      },
      "payout_totals": null,
      "adjusted_payout_totals": null,
      "line_items": [
        {
          "id": "txnitm_01h0qjj0ds7arpp88m5b2c399g",
          "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
          "quantity": 10,
          "totals": {
            "subtotal": "30000",
            "tax": "5400",
            "discount": "3000",
            "total": "32400"
          },
          "product": {
            "id": "pro_01gsz4t5hdjse780zja8vvr7jg",
            "name": "ChatApp Pro",
            "description": "Everything in basic, plus access to a suite of powerful tools and features designed to take your team's productivity to the next level.",
            "tax_category": "standard",
            "image_url": "https://twemoji.maxcdn.com/v/latest/72x72/2708.png",
            "status": "active"
          },
          "tax_rate": "0.2",
          "unit_totals": {
            "subtotal": "3000",
            "tax": "540",
            "discount": "300",
            "total": "3240"
          }
        }
      ]
    },
    "payments": [],
    "checkout": {
      "url": "https://aeroedit.com/pay?_ptxn=txn_01gzkcdstcwq4cj8waj812v9my"
    }
  },
  "meta": {
    "request_id": "415a5995-bece-4775-8fb6-54be15c004d6"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% accordion-item title="Create a transaction with a non-catalog discount" %}

This request creates a new transaction with a non-catalog discount applied called "Custom loyalty discount", giving 10% off the next 6 billing periods. A `currency_code` is included on the transaction as the discount type is `flat`.

If successful, Paddle responds with a copy of the updated transaction entity with the `id` of the discount as `discount_id`. Non-catalog discounts still have a discount entity created for them so you can see their details when fetching them through the API. They have a `mode` of `custom`.

{% api-example method="POST" path="/transactions" href="/api-reference/transactions/create-transaction" %}

```json
{
  "items": [
    {
      "quantity": 10,
      "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke"
    }
  ],
  "customer_id": "ctm_01gzgmxdmgkgc7p94b5kgqq82p",
  "address_id": "add_01gzkce0amtjsqv8xxd1rv3dna",
  "currency_code": "GBP",
  "discount": {
    "type": "flat",
    "description": "Custom loyalty discount",
    "amount": "500",
    "recur": true,
    "maximum_recurring_intervals": 6
  }
}
```

```json
{
  "data": {
    "id": "txn_01gzkcdstcwq4cj8waj812v9my",
    "status": "ready",
    "customer_id": "ctm_01gzgmxdmgkgc7p94b5kgqq82p",
    "address_id": "add_01gzkce0amtjsqv8xxd1rv3dna",
    "business_id": null,
    "custom_data": null,
    "origin": "api",
    "collection_mode": "automatic",
    "subscription_id": null,
    "invoice_id": null,
    "invoice_number": null,
    "billing_details": null,
    "billing_period": null,
    "currency_code": "GBP",
    "discount_id": "dsc_01gy7s3d0n20p1m8b8q8v7e5k4",
    "created_at": "2025-05-04T12:40:07.834144Z",
    "updated_at": "2025-05-04T12:40:07.834144Z",
    "billed_at": null,
    "items": [
      {
        "price": {
          "id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
          "description": "Monthly (per seat)",
          "name": "Monthly (per seat)",
          "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
          "billing_cycle": {
            "interval": "month",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "3000",
            "currency_code": "GBP"
          },
          "unit_price_overrides": [],
          "quantity": {
            "minimum": 10,
            "maximum": 999
          },
          "status": "active"
        },
        "quantity": 10
      }
    ],
    "details": {
      "tax_rates_used": [
        {
          "tax_rate": "0.2",
          "totals": {
            "subtotal": "30000",
            "discount": "500",
            "tax": "5900",
            "total": "35400"
          }
        }
      ],
      "totals": {
        "subtotal": "30000",
        "tax": "5900",
        "discount": "500",
        "total": "35400",
        "grand_total": "35400",
        "fee": null,
        "credit": "0",
        "balance": "35400",
        "earnings": null,
        "currency_code": "GBP"
      },
      "adjusted_totals": {
        "subtotal": "30000",
        "tax": "5900",
        "total": "35400",
        "grand_total": "35400",
        "fee": "0",
        "earnings": "0",
        "currency_code": "GBP"
      },
      "payout_totals": null,
      "adjusted_payout_totals": null,
      "line_items": [
        {
          "id": "txnitm_01h0qjj0ds7arpp88m5b2c399g",
          "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
          "quantity": 10,
          "totals": {
            "subtotal": "30000",
            "tax": "5900",
            "discount": "500",
            "total": "35400"
          },
          "product": {
            "id": "pro_01gsz4t5hdjse780zja8vvr7jg",
            "name": "ChatApp Pro",
            "description": "Everything in basic, plus access to a suite of powerful tools and features designed to take your team's productivity to the next level.",
            "tax_category": "standard",
            "image_url": "https://twemoji.maxcdn.com/v/latest/72x72/2708.png",
            "status": "active"
          },
          "tax_rate": "0.2",
          "unit_totals": {
            "subtotal": "3000",
            "tax": "590",
            "discount": "50",
            "total": "3540"
          }
        }
      ]
    },
    "payments": [],
    "checkout": {
      "url": "https://aeroedit.com/pay?_ptxn=txn_01gzkcdstcwq4cj8waj812v9my"
    }
  },
  "meta": {
    "request_id": "415a5995-bece-4775-8fb6-54be15c004d6"
  }
}
```

{% /api-example %}

{% /accordion-item %}
{% /accordion %}

{% /tab-item %}
{% /tabs %}

## See how many times a discount has been redeemed

You may want to understand how many times a discount has been redeemed to understand its performance, track how many usages it has left, or expose it to customers to promote a sense of urgency against a limit to the discount.

You can see this against a discount entity when you fetch or list discounts as `times_used`. If a discount has a limit, you can compare this to the value of `usage_limit` to calculate and show how many redemptions are left.

This example is a discount entity with a usage limit for how many times this discount can be redeemed as `usage_limit`. It shows how many times the discount has been redeemed as `times_used`.

{% api-example method="GET" path="/discounts/{discount_id}" href="/api-reference/discounts/get-discount" %}

```json
{
  "data": {
    "id": "dsc_01jxw1svzg816ptbzkzf7w12rw",
    "status": "active",
    "description": "25% off (All)",
    "enabled_for_checkout": true,
    "code": "138ETPB5NN",
    "type": "percentage",
    "amount": "25",
    "currency_code": null,
    "recur": false,
    "maximum_recurring_intervals": null,
    "usage_limit": 100,
    "times_used": 79,
    "restrict_to": null,
    "expires_at": null,
    "mode": "standard",
    "custom_data": null,
    "import_meta": null,
    "discount_group_id": "dsg_01jxyv6jh22m3bav2e3srk1a2t",
    "created_at": "2025-06-16T09:40:51.824Z",
    "updated_at": "2025-06-26T13:36:56.314Z"
  },
  "meta": {
    "request_id": "7ba4139f-fc18-412f-b08e-08aabc14fd1c"
  }
}
```

{% /api-example %}

## Create a discount group

Discounts can be grouped together to make them easier to manage. For example, you might create a group for your Black Friday discounts, and then add all your Black Friday discounts to the group.

{% tabs sync="interaction-preference" %}
{% tab-item title="Dashboard" %}

{% callout type="info" %}
Discount groups is only available using the API.
{% /callout %}

{% /tab-item %}
{% tab-item title="API" %}

Create a discount group the API in two steps:

1. **Create a discount group**  
   Build and send a request to create your discount group.
2. **Add discounts to your group**  
   Update discounts to add them to the group you just created.

### Create a discount group {% step=true %}

Send a `POST` request to the `/discount-groups` endpoint to a create a discount group.

In your request, include a `name` for the discount group. Make it descriptive, short, and memorable — this isn't shown to customers.

This example creates a discount group called "Black Friday 2024." If successful, Paddle responds with a copy of the new discount group entity. Take the `id` of the discount group if you want to [add a discount to it](#add-discount-to-group).

{% api-example method="POST" path="/discount-groups" href="/api-reference/discount-groups/create-discount-group" %}

```json
{
  "name": "Black Friday 2026"
}
```

```json
{
  "data": {
    "id": "dsg_01js2gqehzccfkywgx1jk2mtsp",
    "status": "active",
    "name": "Black Friday 2026",
    "import_meta": null,
    "created_at": "2026-11-28T14:36:14.695Z",
    "updated_at": "2026-11-28T14:36:14.695Z"
  },
  "meta": {
    "request_id": "1681f87f-9c36-4557-a1da-bbb622afa0cc"
  }
}
```

{% /api-example %}

### Add a discount to a discount group {% step=true %}

Send a `PATCH` request to the `/discounts/{discount_id}` endpoint to add an existing discount to a discount group, or send a `POST` request to the `/discounts` endpoint to create a new discount.

Provide the `discount_group_id` you just created in the payload, with the value of `id` of the discount group.

This example updates a discount called "All orders (10% off)" to add it to the "Black Friday 2024" discount group. If successful, Paddle responds with a copy of the created or updated discount entity, containing the `discount_group_id` field.

{% api-example method="PATCH" path="/discounts/{discount_id}" href="/api-reference/discounts/update-discount" %}

```json {% title="Request" highlightLines="2" %}
{
  "discount_group_id": "dsg_01js2gqehzccfkywgx1jk2mtsp"
}
```

```json
{
  "data": {
    "id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
    "status": "active",
    "description": "All orders (10% off)",
    "enabled_for_checkout": true,
    "code": "BF10OFF",
    "type": "percentage",
    "mode": "standard",
    "amount": "10",
    "currency_code": null,
    "recur": true,
    "maximum_recurring_intervals": 3,
    "usage_limit": null,
    "restrict_to": [
      "pro_01gsz4t5hdjse780zja8vvr7jg",
      "pro_01gsz4s0w61y0pp88528f1wvvb"
    ],
    "expires_at": "2024-12-03T00:00:00Z",
    "times_used": 0,
    "discount_group_id": "dsg_01js2gqehzccfkywgx1jk2mtsp",
    "custom_data": null,
    "import_meta": null,
    "created_at": "2024-11-28T14:36:14.695Z",
    "updated_at": "2024-11-28T14:38:12.331Z"
  },
  "meta": {
    "request_id": "dd850364-99f7-4e27-bb1e-0a477bdb320b"
  }
}
```

{% /api-example %}

{% /tab-item %}
{% /tabs %}