Skip to content

Gift Cards

Issue gift card codes with fixed balances. Shoppers redeem them at checkout for partial or full order coverage. Codes can have expiry dates, custom strings, and full lifecycle tracking.

Each gift card has:

  • A balance (in pence) that decrements as it’s used.
  • A code — either auto-generated or a custom string you specify.
  • An optional expiry — date after which the card can no longer be redeemed.
  • A status (active, redeemed, expired, deactivated).

Shoppers enter a code on the Swft Checkout payment step. If valid, the balance is applied as a discount. Partial coverage is allowed — if the gift card balance is less than the cart total, the shopper pays the difference with their normal payment method.

Swft Dashboard → Gift Cards.

Click Create gift card. Fill in:

FieldNotes
Amount£1 – £10,000. Stored in pence internally.
CodeLeave blank to auto-generate a random 16-character code. Or specify your own (alphanumeric + hyphens, max 50 chars; must be unique within your store).
Expiry dateOptional. Leave blank for no expiry.
NoteInternal-only note (e.g. “Customer service compensation for order #1234”).

Click Create. The code is displayed once for you to send to the recipient — make sure to copy it.

The Gift Cards page lists every card with:

  • Code (partially masked unless you click to reveal)
  • Original balance and remaining balance
  • Status (active, redeemed, expired, deactivated)
  • Created date and creator
  • Redeemed by (customer email) and redeemed at (timestamp)

Per-card actions:

  • Reveal — show the full code.
  • Deactivate — invalidate immediately (e.g. if it’s been compromised).
  • Adjust balance — manual increase or decrease (creates a ledger entry).

On the Swft Checkout payment step, the shopper sees a Have a gift card? input. They paste the code and click Apply.

  • If the code is valid and has balance: the discount is applied immediately; the order total updates; if the balance covers the whole order, the payment method selector is hidden.
  • If the code is invalid, expired, or zero-balance: a friendly error appears (“Sorry, this gift card isn’t valid”).

The shopper can apply only one gift card per order.

Gift cards are stored in the gift_cards table:

ColumnType
idUUID
merchant_idUUID
codeTEXT, unique per merchant
balance_penceINTEGER
original_balance_penceINTEGER
expires_atTIMESTAMPTZ, nullable
redeemed_byTEXT (customer email), nullable
redeemed_atTIMESTAMPTZ, nullable
statusTEXT enum

The shopper-facing lookup is GET /sessions/:id/apply-gift-card (POST to apply). The lookup endpoint is rate-limited to 10/min per session to discourage brute-force code guessing.

When applied, the gift card balance is recorded against the session in session_data.cart.applied_gift_card. On payment_intent.succeeded, the balance is decremented atomically and redeemed_by / redeemed_at are stamped if the full balance is consumed.

Partial redemption leaves the card active with the remaining balance.

  • One gift card per order. Stacking isn’t supported. If a customer has £20 across two cards, they need to use them on separate orders.
  • Refunds don’t restore balance. If you refund an order paid for partly by gift card, the refunded amount goes to the customer’s original payment method (or your manual choice), not back to the gift card. To re-credit the card, manually adjust the balance in the dashboard.
  • Brute-force resistance is best-effort. Use long, random codes — auto-generated 16-character codes are fine. Short or guessable custom codes (GIFT2024, WELCOME10) are vulnerable.
  • Expiry is enforced at apply-time. A card that expires while sitting in a cart will fail on the next attempt to apply it. Cards that have already been applied to a session don’t expire mid-session.
  • Gift card sales are accounting liabilities. A £50 card sold today is £50 you owe to the bearer later. Reconcile carefully.