Coupons and promotion codes
Define a discount, attach customer-facing promotion codes to it, and read what redeemed where.
A CouponAPI is a reusable discount you define once and apply to checkouts. A Promotion codeAPI is the customer-facing string you give to a customer to redeem a coupon ("FRIENDS20"). One coupon can carry many promotion codes, each with its own restrictions, so you can run several promotions off the same underlying discount.
This page covers how to find a coupon, how to create one, how to attach promotion codes to it, and what you can and can't change after the coupon is live.
Coupons vs promotion codes
These are two different things even though most merchants use them together.
| Concept | What it is | What you set |
|---|---|---|
| Coupon | The discount itself: how much off, how long it applies, how many times it can be redeemed in total. | Discount type and amount, duration, redemption limits, minimum order value, max discount cap, products it applies to. |
| Promotion code | A customer-facing string that points at a coupon. Multiple codes can point at the same coupon with different restrictions. | The code text, first-time-transaction restriction, customer restriction, per-code redemption limit, expiration date, minimum amount. |
A merchant who wants "20% off everything for the summer" creates one coupon and one or more promotion codes that map to it. The coupon defines the 20%; the codes ("SUMMER20", "FRIENDS20") are what customers actually type at checkout.
You can create a coupon without any promotion code (apply it programmatically via the API), but for codes customers type into checkout, you need at least one promotion code.
What you can do
Run percentage or fixed-amount discounts
Pick Percentage off or Fixed amount off, with optional caps and minimum-order rules.
Attach customer-facing codes
One coupon can carry many promotion codes, each with its own expiration, customer restriction, and redemption limit.
Restrict by product or customer
Apply a coupon to specific products in your catalog. Restrict a single promotion code to one customer or first-time customers only.
Archive when done
Deactivate a coupon or promotion code to stop it from being redeemed. Historical redemption data stays intact.
Find a coupon
Click Coupons in the dashboard sidebar (under Shortcuts). The list shows every coupon on your account.
| Column | What it shows |
|---|---|
| Coupon | The coupon's name, or its ID if you didn't set one. |
| Terms | The discount summarized in plain language: "20% off forever", "100 EGP off once", "15% off for 3 months". |
| Redemptions | Times the coupon has been redeemed. Shows X/Y when a maximum is set, just X otherwise. |
| Expires | The redeem-by date, or - if there's no expiration. |
| Status | A badge derived from active and redeemBy. |
Click any row to open the coupon's detail page.
Create a coupon
Click Create coupon in the top right. A new screen opens with two sections: Coupon details and Redemption limits, plus a Promotion codes block at the bottom.
(Optional) Name the coupon
Enter a Name. The name appears on customer receipts and invoices, and on the coupon row in your dashboard. Skip this and the coupon shows up as "Untitled coupon".
Pick the discount type
Choose Percentage off or Fixed amount off.
- Percentage off asks for a percentage between 1 and 100. You can optionally check Limit the maximum discount value to cap how much money the percentage can take off (e.g. 20% off, but no more than 100 EGP).
- Fixed amount off asks for an amount and a currency. Customers pay full price minus that amount.
(Optional) Apply to specific products
Check Apply to specific products to restrict the coupon to a subset of your catalog. A search-and-select picker lets you pick from existing products. Leave the box unchecked to apply the coupon to every product.
Set the duration
Pick how long the discount applies once redeemed:
| Duration | What it does |
|---|---|
| Forever | The discount applies as long as the coupon is active. |
| Once | The discount applies to a single payment, then stops. |
| Multiple months | For subscriptions, the discount applies for N months from redemption, then stops. |
The dashboard hint underneath reads: "For subscriptions, this determines how long this coupon will apply once redeemed." Subscriptions aren't yet shipped, so today the duration matters most for one-time purchases.
(Optional) Set redemption limits
Under Redemption limits, four checkbox-gated fields control when and how often the coupon can be used:
| Field | What it does |
|---|---|
| Limit the date range when customers can redeem this coupon | A Redeem by date, after which no new redemptions are allowed. |
| Limit the total number of times this coupon can be redeemed | A total cap across all customers. The coupon stops redeeming once the cap is hit. |
| Limit the total number of times each customer can redeem this coupon | A per-customer cap. Each customer can redeem up to N times, total can still grow. |
| Require minimum order value | A minimum order subtotal. Orders below it can't redeem the coupon. |
(Optional) Add promotion codes inline
The Promotion codes block at the bottom lets you add one or more customer-facing codes while you're creating the coupon. Click Add another code to add more.
For each code:
- Code (optional). The string customers type at checkout. Codes are case-insensitive and must be unique across all promotion codes on your account. Leave this blank to have one auto-generated.
- Eligible for first-time order only. Restricts the code to customers with no prior completed checkouts.
- Limit to a specific customer. Search for a customer and only that customer can redeem this code.
- Limit times this code can be redeemed. A per-code redemption cap, separate from the coupon's overall cap.
- Add an expiration date. A date after which the code can't be redeemed.
- Require minimum order value. A per-code minimum, separate from the coupon's overall minimum.
You can also skip this and add codes later from the coupon's detail page.
Click Create coupon
In the top right, click Create coupon. The coupon is created, every promotion code you added is created against it, and you land on the coupon's detail page. A "Coupon created successfully" toast confirms.
If a promotion code fails to create (for example, the code string was already in use), the dashboard surfaces a warning toast naming the failed codes; the coupon itself still gets created.
Read a coupon
The detail page is split into a header, a three-cell summary bar, a details grid, applied products (when set), the promotion codes table, and a transactions list at the bottom.
Header
The coupon's name (or "Untitled coupon") sits at the top with a status badge. Two action buttons:
- Rename opens a sheet to update the name.
- Change status lets you flip
activebetween Active and Inactive. Inactive coupons can't be redeemed.
Summary bar
Three cells across the top of the body:
- Type. Percentage off or Fixed amount off.
- Terms. The same plain-language summary as the list: "20% off forever".
- Usage. Times redeemed, with the total cap when one is set.
Details
A two-column grid listing every field on the coupon:
| Field | What it shows |
|---|---|
| ID | The coupon_* ID, with one-click copy. |
| Valid | Yes if the coupon can currently be redeemed. No if it's inactive, expired, or out of redemptions. |
| Name | The display name. |
| Percentage discount / Discount amount | The exact discount. |
| Created | When the coupon was created. |
| Duration | Forever, Once, or N months. |
| Redeem by | The expiration date, when set. |
| Total redemption limit | Unlimited or N times. |
| Per-customer limit | N times when set. |
| Minimum purchase | The minimum order value when set. |
| Maximum discount | The cap on percentage discounts when set. |
| Applies to | All products or N products. |
Applied products
When you restricted the coupon to specific products, this section lists each product with image and name. Click any to open it in the catalog.
Promotion codes
The table of every customer-facing code attached to this coupon. Each row shows the code, API ID, redemption count, expiration date, and creation date.
The + button opens a sheet for adding a new code. The action menu on each row lets you Archive or Unarchive that code (you can't delete a code, only deactivate it).
Transactions
Every successful payment that redeemed this coupon. Click any row to open the payment detail.
Add a promotion code later
Open the coupon, scroll to Promotion codes, click the + button. The same fields as the inline create form appear: code, first-time-transaction, customer restriction, max redemptions, expiration date, minimum amount.
Customers redeem promotion codes at checkout when you've enabled Allow promotion codes on the Checkout Session or Payment Link. The customer sees an "Add promotion code" affordance on the checkout page; if the code is valid for them, the discount applies before payment.
What you can change later
Once a coupon is created, the discount terms are locked. You can't edit any of these:
- Discount type (percentage vs fixed amount)
- Percentage off or amount off
- Currency
- Duration (forever, once, or N months)
The only fields you can change on a live coupon are:
- Name (via Rename).
- Active (via Change status, to deactivate or reactivate).
To change a discount's value or duration, deactivate the old coupon and create a new one. Historical redemptions stay attached to the old coupon for reporting.
For promotion codes, the same rule applies: once created, only the Active flag is mutable. Code, customer restriction, redemption limit, expiration date, and minimum amount are all locked. Create a new code if you need different terms.
Where to next
Prices
How XPay models prices: one-time, recurring, customer-set amounts, stock, scheduling, and the seven price status states.
Payment Links
Create a shareable URL in the dashboard and accept payments without writing any code. Send the link by email or WhatsApp, post it on social, drop it on a button, or print a QR code.