> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Discounts

> Create promotional codes to drive conversions, run campaigns, and reward customers with percentage discounts across one‑time and subscription purchases.

<Frame>
  <img src="https://mintcdn.com/dodopayments/mOQO5ej_lx0yH9p-/images/discount-codes/discount-code-cover.png?fit=max&auto=format&n=mOQO5ej_lx0yH9p-&q=85&s=57f1a644801ddc5efc506b50541eaaba" alt="Discount codes overview cover" style={{ maxHeight: '500px', width: 'auto' }} width="1200" height="630" data-path="images/discount-codes/discount-code-cover.png" />
</Frame>

Discount codes let you run targeted promotions and incentives. Create percentage-based discounts, set limits and expirations, restrict to products, and apply them seamlessly in checkout.

<CardGroup cols={2}>
  <Card title="Checkout Sessions" icon="cart-shopping" href="/developer-resources/checkout-session">
    Apply one or more stacked codes during hosted checkout with `discount_codes` and UI controls.
  </Card>

  <Card title="Validate Discount" icon="code" href="/api-reference/discounts/validate-discount">
    Check if a discount is valid by its ID.
  </Card>

  <Card title="Get Discount by Code" icon="tag" href="/api-reference/discounts/get-discount-by-code">
    Look up and validate a discount using its code name (e.g., "SAVE20").
  </Card>

  <Card title="Create Discount (API)" icon="code" href="/api-reference/discounts/create-discount">
    Programmatically create new discount codes.
  </Card>

  <Card title="List & Update Discounts" icon="code" href="/api-reference/discounts/list-discounts">
    Browse and manage existing discounts; update or delete as needed.
  </Card>

  <Card title="Plan Change Discounts" icon="arrows-rotate" href="/api-reference/subscriptions/change-plan">
    Apply discount codes when upgrading or downgrading subscription plans.
  </Card>
</CardGroup>

## What Are Discount Codes?

Discount codes are promotional tokens that reduce order totals at checkout. They’re ideal for:

* **Seasonal campaigns**: Black Friday, product launches, or anniversaries
* **Acquisition offers**: First‑purchase incentives or referral rewards
* **Retention**: Win‑back or loyalty rewards for existing customers
* **B2B deals**: Contracted or negotiated pricing via private codes

## Key Benefits

* **Flexible discounts**: Percentage-based discounts
* **Stackable codes**: Apply up to 20 codes per checkout, payment, or subscription — combine campaigns (e.g. `WELCOME10` + `BLACKFRIDAY20`) without creating bespoke codes
* **Targeted control**: Restrict by product and subscription cycles
* **Campaign governance**: Expiration dates and usage limits
* **Seamless checkout**: UI field and API support via checkout sessions

## Creating Discount Codes

Create discount codes in your Dodo Payments dashboard, then apply them in hosted checkout or via API.

### Dashboard setup

* **Discount Name** (required): Internal and dashboard display name
* **Code** (required): The string customers enter at checkout
* **Type & Amount** (required): Set a percentage value (only percentage-based discounts are currently supported), or generate a random code using the button provided
* **Expiration Date** (optional): Date after which the code becomes invalid
* **Usage Limit** (optional): Max total redemptions across all customers
* **Product Restriction** (optional): Limit applicability to selected products
* **Subscription Cycle Limit** (optional): Number of billing cycles the discount applies to
* **Metadata** (optional): Attach custom key–value pairs for internal tracking or integrations

<Tip>
  Use cycle limits for introductory pricing on subscriptions (e.g., "50% off for 3 months").
</Tip>

## Checkout Experience

1. Shoppers enter the code in the checkout field.
2. Eligible discounts are applied and totals update immediately.

<Info>
  In Checkout Sessions, pass `discount_codes` (an array) to pre‑apply one or more codes, and set `feature_flags.allow_discount_code` to show the input field. Codes are applied in array order, up to a maximum of 20.
</Info>

## Stacking Discount Codes

Checkout sessions, payments, and subscriptions accept up to **20 stacked codes** via the `discount_codes` array (max 20 entries). Codes are applied **in array order**, so the first eligible code reduces the base price first, the next code reduces the already-discounted price, and so on. The full set of applied discounts is returned in the response under `discount_ids` (on payments/subscriptions) and `discounts` (richer per-discount detail, including position and remaining subscription cycles).

```typescript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_abc', quantity: 1 }],
  discount_codes: ['WELCOME10', 'BLACKFRIDAY20'], // applied in this order
  customer: { email: 'user@example.com' },
  return_url: 'https://yoursite.com/return'
});
```

<Info>
  The singular `discount_code` field is **deprecated** but still fully supported for backward compatibility — existing integrations continue to work without changes. It cannot be combined with `discount_codes` in the same request. We recommend migrating to `discount_codes` (the array form) when convenient, even for single codes, to take advantage of stacking and the richer response shape.
</Info>

## API Management

<AccordionGroup>
  <Accordion title="Create discounts">
    Create discount codes programmatically with type and amount.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/create-discount">
      View the create discount API.
    </Card>
  </Accordion>

  <Accordion title="List and retrieve">
    List all discounts or retrieve details for management and auditing.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/list-discounts">
      Browse listing and retrieval APIs.
    </Card>
  </Accordion>

  <Accordion title="Get discount by code">
    Look up a discount using its human-readable code (e.g., "SAVE20") instead of the internal ID.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/get-discount-by-code">
      Retrieve discount by code name.
    </Card>
  </Accordion>

  <Accordion title="Update discounts">
    Modify discount configuration such as amount, expiration, or restrictions.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/update-discount">
      Learn how to update discount details.
    </Card>
  </Accordion>

  <Accordion title="Validate discounts">
    Check whether a discount is valid and applicable before applying.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/validate-discount">
      Validate discount usage.
    </Card>
  </Accordion>

  <Accordion title="Delete discounts">
    Deactivate or remove discounts that are no longer needed.

    <Card title="API Reference" icon="code" href="/api-reference/discounts/delete-discount">
      Delete a discount.
    </Card>
  </Accordion>
</AccordionGroup>

## Common Use Cases

* **Intro offers**: Limited‑time launch promotions for new products
* **Bulk or B2B**: Contracted discounts for select product sets
* **Retention plays**: Win‑back codes in churn‑prevention workflows
* **Seasonal campaigns**: Holiday or event‑based promotions

## Integration Examples

### Create a discount with metadata

Attach custom key–value pairs for internal tracking.

```typescript theme={null}
const discount = await client.discounts.create({
  type: 'percentage',
  amount: 1500, // 15%
  code: 'SUMMER2025',
  metadata: {
    campaign: 'summer_promo',
    source: 'email_blast'
  }
});
```

<Tip>
  Use metadata to tag discounts by campaign, source, or internal reference ID so you can reconcile usage and measure ROI later.
</Tip>

### Apply discounts in Checkout Sessions

Pre‑apply one or more stacked discounts and show the code input UI.

```typescript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [
    { product_id: 'prod_abc', quantity: 1 }
  ],
  discount_codes: ['BLACKFRIDAY2024', 'NEWUSER5'], // stacked in array order
  customer: { email: 'user@example.com', name: 'Jane Doe' },
  return_url: 'https://yoursite.com/return'
});
```

### Apply discounts during plan changes

Offer promotional pricing when customers upgrade or downgrade their subscription.

```typescript theme={null}
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  discount_codes: ['UPGRADE20']
});
```

| `discount_codes` value              | Behavior on plan change                                                                                |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `undefined` / `null` (not provided) | Existing discounts with `preserve_on_plan_change=true` are preserved if applicable to the new product. |
| `[]` (empty array)                  | **All** existing discounts are removed from the subscription.                                          |
| `['CODE_A', 'CODE_B', ...]`         | Replaces any existing discounts with this stacked set, applied in array order.                         |

<Info>
  Read all applied discounts off the subscription via the new `discounts` array on the subscription response. Each entry includes `discount_id`, `position`, `cycles_remaining` (for subscriptions), and the original code.
</Info>

### Enable discount entry without pre‑applying

Let customers enter a code at checkout without passing one upfront.

```typescript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [
    { product_id: 'prod_abc', quantity: 1 }
  ],
  feature_flags: {
    allow_discount_code: true
  },
  return_url: 'https://yoursite.com/return'
});
```

## Best Practices

* **Name clearly**: Use recognizable codes that match campaign names
* **Time‑box**: Add expirations to drive urgency and prevent misuse
* **Scope wisely**: Limit to specific products to avoid margin leakage
* **Validate early**: Check code applicability before confirming checkout
* **Monitor impact**: Track usage and conversion by campaign

<Info>
  Discount codes are powerful levers for acquisition and retention. Start with simple, well‑named offers, validate thoroughly, and iterate based on performance.
</Info>
