Skip to content
befday
Esc
navigateopen⌘Jpreview
On this page

befday Points Currency

Setel/Mesra-style spendable points — earned proportionally to spend across the merchant network (plus referrals), redeemed via a reward catalog or converted to merchant-funded credit/discount.

Status: Accepted (direction); implementation deferred
Date: June 2026
Decision: Evolve the platform-level befday card from a single completion card into a spendable points currency, modelled on Setel/Mesra. Points are earned proportionally to spend across the befday merchant network (plus referrals/sign-ups), accumulate as a balance, and are redeemed two ways: a reward catalog or converted to credit/discount applied at checkout. Credit-converted discounts are merchant-funded. Referral loop, verified-phone anti-fraud, and idempotency from Platform Stamps & Referral carry forward.
Supersedes: Platform Stamps & Referral — replaces the fill-to-goal → one birthday perk mechanic with a points-balance currency.


TL;DR

The befday card becomes a points wallet. Points are earned proportionally to spend across the network (plus referrals/sign-ups), held as a balance, and redeemed via a reward catalog or converted to merchant-funded credit at checkout. Per-merchant stamp cards stay unchanged.


Context

Platform Stamps & Referral introduced a befday card: a weighted points ledger that fills to a goal and unlocks one birthday perk. Reviewing Setel.my (Petronas) reframed it:

  • In Setel, every purchase earns points proportional to spend.
  • Points are a currency — redeemable for catalog rewards or converted to credit/discount at checkout.

For a multi-merchant platform this is the key unlock: points earned at café A become spendable at restaurant B, turning siloed loyalty into a network-wide currency. The befday card becomes the points wallet, not a punch card.


Decision

The befday card is a points wallet. Points are earned proportionally to qualifying spend (plus referrals/sign-ups), held as a balance, and redeemed via a reward catalog or converted to merchant-funded credit/discount at checkout.

Earning

Source Basis Notes
Purchase (primary) Proportional to spend (e.g. X pts / RM1) Earned on paid orders at befday merchants
referral Fixed bonus (verified referee) Carried from Platform Stamps; idempotent per (A, B)
signup Fixed bonus (verified new user) Carried from Platform Stamps; idempotent per user
  • Earn rate is config (store_settings-style): a base network rate, optionally overridable per merchant for promos.
  • Purchase points issue inside the existing orders.pay transaction (alongside the per-merchant stamp), only when the order’s store_customer is linked to a befday user_id.
  • Per-merchant stamp cards remain unchanged and run alongside the currency (stamps = visit-based reward at one shop; points = spend-based currency across the network).

Redemption (two paths — full Setel model)

  1. Reward catalog — spend points on vouchers, birthday gifts, or partner items at a points price.
  2. Credit / discount — convert points to credit at a fixed redemption rate (e.g. 100 pts = RM1) and apply as a discount line at checkout.

Both paths debit the same balance via the ledger. Redemption is server-verified and idempotent.

Funding

Credit-converted discounts are merchant-funded — the merchant absorbs the discount like a voucher (it lands as a discount line on the order, settled in their books). This bounds befday’s liability and aligns cost with the merchant getting the sale.

Implication: the POS/order flow records point-redemption discounts as a merchant-funded discount line (distinct from voucher_discount_cents and manual_discount_cents), so settlement and analytics attribute it correctly.

Anti-fraud & integrity (carried + extended from Platform Stamps)

  • Referral/sign-up points: verified phone only, idempotent per (referrer, referee) / per user; self-referral blocked.
  • Purchase points: bound to a real paid order, idempotent per order_id (mirrors orders.stamp_issued).
  • Redemption: balance check inside a transaction; cannot spend more than held; idempotent per redemption.
  • Negative-balance impossible — debits are atomic against the current balance.

Points-as-currency: liabilities to design for

Points convert to money-equivalent credit, so this is a financial instrument, not just a game mechanic. Decide explicitly:

  • Earn rate (points per RM) and redemption rate (points per RM credit) — the spread defines program cost.
  • Expiry — points should expire (e.g. 12–18 months of inactivity) to bound liability and model breakage (unredeemed points).
  • Outstanding-liability tracking — the sum of unredeemed balances is money owed (by merchants, under merchant-funded model); surface it in analytics.
  • Rounding — define rounding for partial redemptions to avoid penny-shaving exploits.
  • Min/max redemption per order, to bound abuse and protect merchant margins.

Data Model Impact (sketch)

Evolves the Platform Stamps tables into a wallet + ledger. Keyed by user.id.

befday_wallets (replaces befday_cards)

Column Type Notes
id uuid PK
user_id text FK → user.id, unique
points_balance integer current spendable balance (never negative)
lifetime_earned integer denormalized, for tiers/analytics
updated_at timestamp

befday_point_events (ledger — earn and spend)

Generalizes the Platform Stamps ledger to signed entries (credits earn, debits redeem).

Column Type Notes
id uuid PK
wallet_id uuid FK → befday_wallets.id
direction enum earn | redeem
event_type enum purchase | referral | signup | catalog_redeem | credit_redeem | expiry
points integer positive magnitude; sign implied by direction
order_id uuid nullable FK → orders.id (for purchase earn and credit_redeem)
referrer_user_id text nullable FK → user.id
referee_user_id text nullable FK → user.id
catalog_item_id uuid nullable FK → befday_reward_items.id (for catalog_redeem)
expires_at timestamp nullable — for earn lots subject to expiry
issued_at timestamp

Idempotency: purchase unique per (order_id); referral unique per (referrer_user_id, referee_user_id); signup unique per (referee_user_id); redemptions unique per redemption request id.

befday_reward_items (catalog)

Column Type Notes
id uuid PK
name text
points_price integer points required
kind enum voucher | gift | partner
is_active boolean

orders extension (merchant-funded credit)

Add a discount line so point→credit redemption is attributable and settled merchant-side:

Column Type Notes
points_discount_cents integer default 0 — merchant-funded discount from redeemed pts

Total formula becomes: total = subtotal − manual_discount − voucher_discount − points_discount + tax.

Earn rate / redemption rate live in config (extend store_settings or a new befday_program_settings).


API Impact (sketch)

Procedure Status Notes
consumer.wallet.get New Balance, lifetime earned, expiring-soon summary
consumer.wallet.history New Ledger entries (earn/redeem)
consumer.rewards.catalog New List catalog items + points prices
consumer.rewards.redeem New Redeem catalog item (debits balance, idempotent)
pos.points.preview New At checkout: look up balance, show max credit redeemable
pos.points.applyCredit New Convert points → points_discount_cents on the order (merchant-funded)
(internal) grantPurchasePoints New Idempotent earn inside orders.pay (per order_id)
consumer.referral.* Carry From Platform Stamps — unchanged
consumer.befdayCard.* Replaced By consumer.wallet.* above

Earning/redeeming are server-side, transactional, idempotent, mirroring stamp + voucher patterns.


Consequences

Type Consequence
Pro Network-wide spendable currency — earn at one merchant, redeem at another. This is the core platform unlock.
Pro Two redemption paths (catalog + credit) match Setel and maximize perceived value/flexibility.
Pro Merchant-funded credit bounds befday’s liability and aligns cost with the merchant getting the sale.
Pro Reuses verified-phone anti-fraud, transactional issuance, and the ledger pattern already in the stack.
Con Points-as-currency is a financial instrument — needs earn/redeem rates, expiry, breakage, rounding, liability tracking.
Con Requires POS + order changes (new points_discount_cents line, balance lookup, apply-credit flow) — heavier than Platform Stamps.
Con Merchant settlement/analytics must correctly attribute merchant-funded point discounts.
Con “Redeem at any merchant” raises cross-merchant funding fairness (who funds points earned at A but spent at B?) — see Open Questions.

Resolved Decisions

Question Decision
Relationship Evolve the befday card (Platform Stamps) into a points currency
Earning basis Proportional to spend (+ carried referral/sign-up bonuses)
Redemption Both — reward catalog and convert to credit/discount
Funding Merchant-funded credit/discount (like a voucher)
Per-merchant stamps Kept — run alongside the currency, unchanged
Anti-fraud Verified phone, transactional idempotent earn/redeem, no negative balance

Open Questions

  • Earn & redemption rates: points per RM earned, and points per RM credit — define the spread (program cost).
  • Cross-merchant funding fairness: ✅ Resolved in Cross-Merchant Points Funding — launch constrained Model 1 (earning-merchant-only redemption + caps), architect for Model 2 (earner pre-funds a pool), reserve Model 3 (befday float).
  • Expiry & breakage: expiry window (e.g. 12–18 months) and how breakage is modelled/reported.
  • Catalog ownership: who funds catalog rewards (platform, merchant, partner)?
  • Min/max redemption per order: caps to protect merchant margin and bound abuse.
  • Birthday hook: does the birthday still grant something special (bonus points, multiplier, exclusive catalog item) to keep befday’s brand identity?
  • POS without payments gateway: point-credit is a discount line (works with cash today); confirm no gateway dependency for v1.

Was this page helpful?