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

# How to create and share a discount code

> Create a code, scope it to the right listings and dates, decide who may redeem it, and find out why a customer's code was rejected.

<Card title="Open in TWICE Admin" icon="external-link" href="https://admin.twicecommerce.com/discount-codes" horizontal>
  Catalog → Discount Codes
</Card>

A discount code is easy to create and easy to scope wrongly. Two settings decide almost every "the code doesn't work" report: which items the code is allowed to touch, and which of the two date windows you set.

This guide walks the code from creation to a customer redeeming it, and then covers how to find out why a code was rejected — because the storefront will not tell you.

## Prerequisites

<Warning>
  **Required permission:** `catalog:discount` create and manage. Owner, Admin and Manager hold every operation on discount codes. **Member does not hold it at all** — a Member cannot see the Discount Codes view, let alone create a code.
</Warning>

<Info>
  **Decide which date window you mean before you start.** There are two, they look alike, and they answer different questions:

  * **Valid from / Valid until** — when the code can be *redeemed*. A window on the order date.
  * **Start date from / Start date until** — which *items* the code applies to, by their booking or subscription start date.

  A summer campaign you want people to book in March, for equipment they pick up in July, needs the second pair. Setting the first pair instead makes the code redeemable only in July, which is the opposite of a campaign.
</Info>

## The Walkthrough

<Steps>
  <Step title="Create the code — it exists immediately">
    Go to **Catalog → Discount Codes** and click **Create discount code** (hotkey `a`).

    There is no dialog. TWICE creates the code straight away and opens it: a placeholder string like `NEW-4K2P9X`, 10 %, and **Enabled** switched **off**. The rest of this walkthrough is editing that code, not filling in a form before it exists.

    Two consequences worth knowing. The code is safe while you work on it, because it is disabled and no customer can redeem a disabled code. And if you abandon the page half-finished, you have left a `NEW-…` stub in the list — it does nothing, but it is yours to clean up.
  </Step>

  <Step title="Name the code">
    Replace the placeholder in **Code** with the string customers will type.

    The field uppercases as you type, and codes are matched case-insensitively — `Summer25` and `SUMMER25` are the same code. Letters (accented ones included, so `KESÄ15` is fine), digits, hyphens and underscores are allowed; spaces, slashes and punctuation are not. If you paste something unsupported, the field names the offending characters and **Save** stays disabled until you fix them.

    **Description** is internal. Customers never see it, and a line about which campaign a code belongs to is worth more in six months than the code string itself.
  </Step>

  <Step title="Set the discount type and value">
    **Discount type** is **Percentage** or **Fixed**.

    A fixed code also asks for a **Scope**, and this is the setting people get wrong:

    * **Per order** — *Apply the amount once to the whole order.* €10 off, spread proportionally across the eligible items.
    * **Per item** — *Apply the amount to each eligible item separately.* €10 off every eligible item. On a five-item order that is €50.

    Percentage codes have no scope — a percentage is per item by nature. Percentages are rounded down to the whole currency unit.

    Either way the discount is clamped to what the item actually costs, so a code can never take an order below zero or produce a refund.
  </Step>

  <Step title="Decide who may redeem it">
    **Who can use this code** is a select, not a toggle, because it matters:

    * **Anyone with the code** — an ordinary campaign code. Whoever has the string can redeem it.
    * **Only staff and integrations** — *a staff-only code can't be entered by customers at checkout.* Use this for codes an integration grants automatically, or that staff apply on the customer's behalf.

    Staff-only codes carry a **Staff only** chip in the Discount Codes table so you can spot them while scanning.

    A staff-only code still appears by name on the customer's own order summary once applied. What is restricted is who may *use* it, not who may *see* it — so do not treat the string as a secret.
  </Step>

  <Step title="Scope it to the right items">
    Three settings narrow which items the discount touches. Each is empty by default, and empty means no restriction.

    * **Applies to** — **Sales**, **Bookings**, **Subscriptions**. Leave empty and the code covers every purchase type, including ones not listed here such as buyback. Restrict it and only the types you picked match.
    * **Limit to listings** — specific listings.
    * **Limit to collections** — items belonging to specific collections.

    Two things to be clear about. These restrictions **narrow the discount per item, not per order**: a code limited to one collection applies to the items from that collection and leaves the rest of the order at full price. And the restrictions **combine with AND** — an item has to satisfy every restriction you set. A code limited to a listing that is not in the collection you also picked matches nothing at all.
  </Step>

  <Step title="Set the subscription duration — if subscriptions are in scope">
    A **Subscriptions** section appears when the code can reach subscriptions, and **Applies for** is required there:

    * **First cycle only** — one cycle, then full price.
    * **A number of cycles** — asks for **Number of cycles**.
    * **Every cycle** — for as long as the subscription runs.

    The section also appears when **Applies to** is *empty*, because an unrestricted code covers subscriptions too. That surprises people who never intended a subscription code. If you do not want one, restrict **Applies to** to Sales and Bookings and the section goes away.
  </Step>

  <Step title="Set the limits and the date windows">
    **Usage limit** is the total number of redemptions across all customers, not a per-customer limit. Leave it empty for **Unlimited**. The **Times used** row shows the count against the limit as the campaign runs.

    Then the two date pairs from the Prerequisites:

    * **Valid from** / **Valid until** — the redemption window.
    * **Start date from** / **Start date until** — the item start dates the code covers.

    All four are day-only dates read in your account's timezone, and any of them can be left empty. An item with no start date at all — an ordinary sale — is never excluded by the second pair.
  </Step>

  <Step title="Turn it on">
    Switch **Enabled** on and save. The code is now live for anyone who has the string.

    Do this last. A code that is enabled while you are still editing its restrictions is redeemable at whatever it happens to say at that moment.
  </Step>
</Steps>

## How do I know it worked?

The code appears in **Catalog → Discount Codes** with **Status** *Enabled*, its value, and **Usage** at `0` (or `0 / 100` against a limit).

The check that actually proves it works is applying it. Open a test order, use **Discounts** → **Discount codes** → **Apply**, and confirm two things: the code is accepted, and the amount that comes off is the amount you meant on the items you meant. A code that applies to the wrong items is accepted just as cheerfully as one that applies to the right ones.

When customers start redeeming it, **Times used** climbs.

## Troubleshooting / Common Pitfalls

<AccordionGroup>
  <Accordion title="A customer says the code doesn't work, and the storefront won't say why">
    **Working as designed.** The storefront collapses every failure into *Invalid discount code* — expired, disabled, usage limit reached, wrong items, staff-only — so that nobody can probe a code's state by typing guesses at checkout.

    **What to do:** apply the code from admin instead. Open any order with representative items, go to **Discounts** → **Discount codes**, and apply it there. The admin returns the specific reason: not found, disabled, not yet valid, expired, usage limit reached, staff-only, purchase type mismatch, listing or collection not applicable, no eligible items, or no effect. That message is the diagnosis; the rest of this section is what to do with it.
  </Accordion>

  <Accordion title="The code is accepted but takes nothing off">
    **Cause:** the code is valid and resolves to a zero discount — most often a percentage rounding down to nothing on a very small subtotal, or a fixed amount clamped away by an item that is already free.

    TWICE treats a no-op code as a failure rather than silently applying nothing, so you get *no effect* rather than a €0 discount line.

    **What to do:** check the code's value against the actual item prices. If a 5 % code is meant to work on €1 items, it cannot — the discount floors to zero. Use a fixed amount instead.
  </Accordion>

  <Accordion title="The discount came off the wrong items, or only some of them">
    **Cause:** this is scoping working as specified. **Limit to listings**, **Limit to collections** and **Applies to** narrow the discount to matching items — the rest of the order stays at full price, and that is deliberate.

    **What to do:** open the code and read the three restrictions together. Remember they combine with AND. If you meant "10 % off the whole order when it contains a tent", that is not what these settings do — they discount the tent.
  </Accordion>

  <Accordion title="A fixed code took off far more than expected">
    **Cause:** **Scope** is set to **Per item**. A €20 per-item code on a six-item order is €120.

    **What to do:** switch Scope to **Per order** if you meant one amount off the order. The wording in the helper text is the reliable test — *once to the whole order* versus *to each eligible item separately*.
  </Accordion>

  <Accordion title="The code works now but should not start until the campaign does">
    **Cause:** **Valid from** is empty, so the code is redeemable as soon as it is enabled.

    **What to do:** set **Valid from**, and leave **Enabled** on. A future-dated code is rejected as *not yet valid* until the window opens, which is what you want — you do not have to remember to switch it on.
  </Accordion>

  <Accordion title="I only wanted a booking code, but it is discounting subscriptions">
    **Cause:** **Applies to** was left empty. Empty is not "bookings by default", it is "every purchase type".

    **What to do:** tick the purchase types you actually mean. This is also why the Subscriptions section appears on codes that were never intended for subscriptions.
  </Accordion>

  <Accordion title="I removed a code and now I cannot find it">
    **Cause:** removing a discount code **archives** it rather than deleting it. It leaves the Discount Codes list but still exists.

    **What to do:** find it under **Settings → Archived assets**, where you can unarchive it or delete it permanently. Unarchiving fails if an active code has since taken the same string — rename one of them first.
  </Accordion>

  <Accordion title="An old order still shows a code we changed">
    **Working as designed.** The code string and its per-item allocations are recorded on the order when it is applied. Editing or archiving the code afterwards does not rewrite orders that already used it.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Discount Codes" icon="tag" href="/docs/catalog/discount-codes">
    The view reference, field by field.
  </Card>

  <Card title="Discount codes" icon="percent" href="/docs/concepts/catalog/discount-codes">
    How a code resolves against an order.
  </Card>

  <Card title="Build a collection" icon="layer-group" href="/docs/guides/catalog/build-a-collection">
    The collections a code can be limited to.
  </Card>

  <Card title="Price a listing" icon="tag" href="/docs/guides/catalog/price-a-listing">
    The price a discount comes off.
  </Card>
</CardGroup>
