Coupon redemption codes: reservations, caps, expiry and merchant confirmation
The short answer
A coupon redemption code should follow a strict lifecycle: a shopper reserves a code from an offer with remaining capacity, the code stays reserved until an expiry time, and it becomes redeemed only when the merchant confirms it at the counter. If the reservation lapses first, the code expires. The server, not the app, must enforce the cap, the expiry and the rule that a code can be confirmed only once, because that is where overselling and double use are stopped.
Key takeaways
- Reservation and redemption are two different events; reports and limits must treat them separately.
- Enforce an offer's code cap inside a single database transaction so two shoppers can never take the last code at once.
- Every reservation needs an expiry, or a capped offer can be blocked by people who never visit.
- A code becomes redeemed only when an authorised merchant confirms it, and a second confirmation must fail.
Reservation vs redemption: two different events
A reservation means a shopper has claimed a code; a redemption means a merchant has confirmed that the code was used. Mixing the two is a common mistake in coupon apps, and it shows up later as inflated reports and offers that run out before anyone visits.
Consider a café that publishes an offer capped at a fixed number of codes. Shoppers reserve codes on Monday. Some come in on Tuesday, some forget, and some reserved only to keep their options open. If the app counts reservations as uses, the café believes the offer was a success and may run out of codes for real customers. If it counts only redemptions, the café sees what actually happened at the counter.
T-CODE, the offers app FLUIDS designed and built, keeps these events apart. A signed-in shopper reserves an offer code; reserved coupons are kept separate from codes already used; reservations carry expiry information; and redemption is confirmed by the merchant, code by code. The rest of this guide explains how to build that lifecycle so it holds up under real use.
The coupon code lifecycle, state by state
Model every code as a small state machine. Each state has one meaning, a defined way in, and a limited set of next states. Anything not on the table is an illegal transition the server should reject:
| State | Meaning | Entered when | Can move to |
|---|---|---|---|
| Available | The offer still has capacity; no code issued to this shopper | Offer is published and active | Reserved |
| Reserved | A unique code belongs to one shopper and is waiting to be used | Shopper reserves while capacity remains | Redeemed, Expired, Cancelled |
| Redeemed | The merchant confirmed use at a branch | Authorised staff confirm the code | None (final) |
| Expired | The reservation lapsed before use | Expiry time passes, or the offer ends (if that is the rule) | None (final) |
| Cancelled | The reservation was released | Shopper releases it, or the offer is withdrawn | None (final) |
The offer has its own, simpler lifecycle: draft, active, then ended because its time limit passed or its codes ran out. A code's state depends on its offer: when an offer ends, outstanding reservations need a rule, either honoured until their own expiry or expired with the offer. Write that rule down and show it to the shopper.
Final states are final. A redeemed code is never "un-redeemed" by editing a field; if a confirmation was a mistake, record a separate correction with a reason. This keeps the merchant's numbers trustworthy and gives support staff a clear history to look at when a shopper complains.
How to enforce a code cap without overselling
A cap is enforced only if the server checks and decrements it in one atomic step. Checking "are codes left?" in the app and then reserving a moment later leaves a gap in which two shoppers can both take the last code. T-CODE treats its cap as enforced rather than advisory, and any serious coupon app should do the same.
In practice, there are a few reliable patterns, all of which live in the database rather than the mobile app:
- A conditional update: increase the offer's issued count only where it is still below the cap, and treat zero updated rows as "sold out".
- A row lock: lock the offer row, count active reservations, insert the new one, then commit.
- A unique constraint: allow only one open reservation per shopper per offer, so repeated taps cannot take several codes.
Then decide what the cap actually counts. If it counts reservations, expired and cancelled reservations should release capacity back to the offer, or the offer will appear sold out while codes go unused. If it counts only redemptions, more shoppers can reserve than the cap allows, and some may arrive to find the offer has ended. A common choice is to count active reservations plus redemptions, and return capacity when a reservation expires.
Choosing how long a reservation lasts
A reservation should last long enough for a realistic visit and no longer. Too short, and shoppers arrive to find their code gone; too long, and capped offers are blocked by people who changed their plans.
The right window depends on the type of offer. A lunch deal at a restaurant suits a same-day reservation. A discount at a furniture shop may need several days, because people plan those visits. Some products let the merchant choose the window per offer, within limits the platform sets.
Three implementation details matter more than the exact duration. First, compute expiry on the server and store it as a timestamp with the reservation, so the phone's clock cannot extend it. Second, show expiry clearly in the shopper's saved coupons; in T-CODE, reservations carry expiry information so the shopper can see which offers are still available to use. Third, treat a reservation as expired the moment its time passes, even if a background job has not yet updated the row; checking expiry at confirmation time prevents a late code from slipping through.
How merchant confirmation should work
Confirmation is the moment the coupon turns into a real transaction, so the merchant app has to make it quick for staff and strict on the server. A sound confirmation runs these checks in order:
- Find the code. Staff enter or scan the code the shopper shows.
- Check ownership. The code must belong to an offer from this merchant.
- Check the branch. If the offer is limited to certain branches, the confirming staff member must be at one of them.
- Check the state. The code must be reserved and not expired, cancelled or already redeemed.
- Confirm once. Mark it redeemed in a single update that fails if another device confirmed it first.
- Record who and where. Store the staff member, branch and time with the redemption.
When a check fails, the message should tell staff what to do: "This code was already used at another branch" is more useful than "Error". In T-CODE, code redemption sits in the merchant app's main navigation alongside offers and the dashboard, and the merchant confirms each use with a redemption code.
This is also where shopper-side shortcuts fail. A button that lets the shopper mark a coupon as used proves nothing, and a screenshot of a code can be shown twice. Only a server-side confirmation by an authorised merchant gives both the merchant and the platform a reliable record.
Preventing coupon abuse
Every rule in a coupon system exists to stop a specific kind of abuse. Naming them makes it easier to decide which safeguards your first release needs:
| Abuse | What it looks like | Safeguard |
|---|---|---|
| Hoarding | One person reserves many codes and blocks a capped offer | One open reservation per shopper per offer, plus expiry |
| Screenshot sharing | A code image is passed around and shown more than once | Codes tied to an account and confirmable only once |
| Code guessing | Someone tries sequential or short codes at the counter | Long random codes and rate limits on lookups |
| Multiple accounts | One person signs up repeatedly to get more codes | Verified sign-up, such as a phone number, and per-device checks |
| Staff collusion | Staff confirm codes for friends without a real visit | Each redemption records the staff member and branch, with reports per staff |
| Fake merchants | A non-existent business publishes offers to collect sign-ups | Merchant applications reviewed and approved before a shop exists |
None of these needs heavy machinery. Most are constraints and logging that cost little to add at the start and a lot to retrofit. The last row matters as much as the others: in T-CODE, a merchant application is reviewed and approved before the shop is created, which our merchant offers dashboard guide covers in detail.
If your merchants have several branches and staff at each, redemption permissions become part of abuse prevention too; see staff roles for multi-branch merchants. For the overall product, start with how to build a coupon app, the T-CODE case study and our custom software development service. Scope, price and timeline for a similar product are agreed in a written proposal before development.
Frequently asked questions
What happens when a reserved coupon expires?
The code moves to an expired state and can no longer be confirmed. In many designs, its place in a capped offer is released so another shopper can reserve it.
Can the same coupon code be used twice?
Not in a well-built system. Confirmation is a single server-side update that succeeds only if the code is still reserved, so a second attempt, even from another branch or device, fails.
Should an offer's cap count reservations or redemptions?
A common choice is active reservations plus redemptions, with capacity returned when a reservation expires or is cancelled. Counting only redemptions lets more people reserve than the merchant can honour.
Why not let the shopper mark a coupon as used?
Because it proves nothing to the merchant and makes reports unreliable. Merchant-confirmed redemption, as in T-CODE, records real use at a real branch.
Can FLUIDS build a coupon reservation and redemption system?
Yes. We define the code states, cap rules, expiry and merchant permissions with you, then build the shopper app, merchant tools and server rules. Scope, price and timeline are confirmed in a written proposal before development.
Related development services
From the idea to a working product
Offers, coupons & loyalty
Keep reading
Coupon app development
How to build a coupon and local offers app
Merchant offers dashboard
A merchant dashboard for offers: publishing, limits and clear numbers
Multi-branch merchant roles
Multi-branch merchants: staff roles, branch visibility and point permissions
Loyalty points apps
Building a loyalty points app: wallet, QR identification and merchant point grants
Turn the idea into a written scope
A short call to understand your users and workflow, then a written proposal covering scope, timeline and price before development starts.
Start on WhatsApp