Skip to main content
A discount code is a merchant-defined string that reduces the price of eligible items. A customer enters it at checkout, an operator applies it to an order, or — with Auto-apply on — TWICE applies it on its own, with no code for the shopper to type. Codes are case-insensitive — SUMMER20 and summer20 resolve to the same code.
Discount codes vs Price Tables: Price Tables define the base price for a listing. Discount codes reduce the total after the base price is calculated. Use Price Tables for rate cards and seasonal pricing; use discount codes for targeted promotions, limited-time offers, or customer-specific incentives.

How it works

Discount types

Every code has a value type that determines how the discount is calculated. For fixed types, the discount on any single item never exceeds that item’s subtotal — no item goes below zero. When a fixed-per-order discount is spread across items, the allocation uses largest-remainder rounding so the per-item amounts sum exactly to the total discount.

Restrictions

A code can be restricted to specific items. Leave a restriction empty to apply the code to everything. When both listing and collection restrictions are set, an item must match at least one of the specified listings or belong to at least one of the specified collections. Exclusions are judged first and they win. An item named under Exclude listings, or belonging to a collection under Exclude collections, never gets the discount, however the apply targeting reads. That is what makes “everything except these three listings” expressible without enumerating the catalog, and it lets a collection-targeted code skip a single member of that collection. The location restriction is the one that works differently: it is an order-level gate rather than a per-item one — the whole checkout’s location either matches or the code does not apply at all. Contexts with no location, such as an admin order edit or a cart preview, skip the gate.

Validity windows

Two independent date windows control when a code can be used. Both windows are optional. A code with no validity window is redeemable at any time.

Subscription cycles

When a code can reach subscriptions, it carries an Applies for setting that decides how many billing cycles the discount covers: the first cycle only, a set number of cycles, or every cycle for as long as the subscription runs. The discount period above still bounds it — the cycle count never extends the discount past the period’s end.

Usage limits

Set a usage limit to cap how many times a code can be used across all customers. Each order that carries the code counts as one use. Deleting an order releases its use automatically. Codes with no usage limit can be used an unlimited number of times.
Usage is enforced with row-level locking to prevent race conditions on high-demand codes.

Enabled / disabled

A code has an enabled toggle. Disabled codes are rejected at checkout and cannot be applied to orders. Disable a code to stop it from being used without deleting it.

Access control

Every code has an access setting that controls who can apply it. Use internal codes for staff-applied promotions, partner discounts, or integration-driven pricing adjustments that customers should not self-serve. In the discount codes table, internal codes are marked with a Staff only chip next to the code string.

Auto-apply

A code with Auto-apply on is applied by TWICE rather than typed by a shopper. It has two effects.
  • While browsing. The storefront projects your active auto-apply codes onto catalog prices, so shoppers see the discounted price on listing cards and product pages before they reach checkout. Only codes that target the online storefront are projected, and a code that is disabled, archived, past its offer window, past the end of its discount period, or out of usage is not projected at all. The projection carries the code’s exclusions, so an excluded listing shows its full price while browsing and stays undiscounted at checkout.
  • At checkout. The code is applied to the order without anyone entering it. The At checkout section below covers how several matching codes resolve.
In storefronts narrows which storefronts a code applies itself in; leave it empty and it covers all of them. The setting means nothing while Auto-apply is off. Two things follow from a code applying itself:
  • A usage limit on an auto-apply code behaves as “the first N orders get the discount”, not as a per-customer cap — every matching checkout claims it.
  • The code does not need to be typeable. Set Who can use this code to Only staff and integrations unless the same code should also work as a shareable coupon; an applied code still shows by name in the shopper’s own order summary either way.

Combining codes

Each code carries a Combinable setting, off by default, and it is enforced per item rather than per order.
  • A non-combinable code is the only discount on the items it holds.
  • Two combinable codes can discount the same item together.
  • Codes that discount different items coexist regardless of the setting — combinability only ever decides what happens on a contested item.

At checkout

A checkout reaches its discounts two ways: codes the shopper enters, and auto-apply codes TWICE applies on its own.

Codes the shopper enters

The checkout order summary includes a discount code input. The customer enters a code and the storefront validates it against the current cart items.
  • On success, the discount is applied and the updated totals are shown. The code appears as a badge in the order summary with the discount amount and a remove button.
  • On failure, a generic “Invalid discount code” message is shown. The storefront does not reveal the specific reason (expired, usage limit reached, etc.) to prevent code enumeration.
Three failures are exempt from that generic message, because the shopper holds a working code and needs to know why it is not landing: the code cannot combine with what is already applied, the applied discounts were weighed against it and won, and the code is already on the checkout.
Discount code endpoints on the storefront are rate-limited to prevent brute-force enumeration.

Auto-apply codes

Auto-apply codes are applied when the checkout is created, with no code to type. Editing the cart recreates the checkout and re-evaluates them; changing the location re-evaluates them too. TWICE walks every candidate whose scope covers the checkout’s storefront and location, most specific first, and each one takes the items whose existing codes accept it. Specificity runs:
  1. Codes limited to locations.
  2. Codes targeted at specific storefronts.
  3. Codes targeted at specific listings or collections.
  4. Untargeted, store-wide codes.
Within one tier the order is fixed by discount type — percentage, then fixed per item, then fixed per order — and equally targeted codes of the same type prefer the bigger discount, so a shopper covered by both a 50 % and a 60 % code gets the 60 %. Exclusions sit outside this order rather than forming a fifth tier. A code skips its excluded items at whatever tier it occupies, and the next candidate down picks them up. Exclusions do not make a code more specific either: a store-wide code with three listings excluded still ranks store-wide. A candidate that fails validation leaves the checkout untouched, so a broader code acts as the fallback for a more specific one that has expired, hit its usage limit, or does not match the cart. Overlapping scopes need no conflict management: “5 % store-wide, 10 % in Helsinki” resolves on its own. Auto-apply never displaces a code the shopper or an integration already secured — it fills what is free. A failure in the whole path leaves the checkout undiscounted rather than blocking it.

When codes contest the same items

A checkout can carry several codes at once. They only contest each other on an item both would discount, and only when one of them is not combinable. When a shopper enters a code whose every eligible item is held by conflicting codes, TWICE prices the entered code alone over those items and weighs it against what the held codes take there. The bigger discount wins: the entered code displaces them on the contested items — a displaced code keeps whatever it holds elsewhere on the checkout — or, if it is worth less, it is rejected and the shopper is told the applied discounts are the better deal. Discount codes can also be applied on checkout links — checkouts backed by an existing order. The code input appears when both conditions are met:
  • The linked order has no existing discount codes.
  • All eligible items on the order are fully unpaid.
If the order already carries a discount code, the existing codes appear as locked chips in the order summary and no new code can be entered. Partially paid orders and instalment links do not support discount codes.
Subscription line items are not eligible for checkout link discounts — only booking and sale items are discounted.

On orders

Once an order is created, the applied discount code is stored with its per-item allocations. The code string is snapshotted at application time — renaming or deleting the code later does not affect existing orders. Operators can manage discount codes on an order from the Discounts drawer on the order detail page:
  • Add a code — search for and validate a code against the order’s line items. The drawer previews the discount amount before you confirm.
  • Remove a code — remove a previously applied code to restore original pricing.
  • Multiple codes — an order can carry several codes, subject to the same combinability rules as a checkout.
The discount allocation is visible on each line item’s pricing breakdown.

Price Tables

Base pricing that discount codes reduce.

Listings

Codes can be restricted to specific listings.

Collections

Codes can be restricted to specific collections.

Order lifecycle

Where discount codes are captured and stored.