How the Credit Card Rewards Engine Works in MyFam360
MyFam360 ships an 8-card preset library covering common Indian credit cards — and runs a rule engine that computes rewards from your actual logged spend.
A ₹300 cashback you don’t claim because you used the wrong card is, functionally, the same as throwing away ₹300. Across a year of unconscious card choice, the cost is real — most Indian cardholders leave thousands of rupees in unclaimed rewards on the table because remembering which card earns the most on Swiggy versus Amazon versus the petrol pump is too much cognitive overhead.
MyFam360’s Credit Card Rewards engine is built to make that decision automatic. This post explains how the engine works, what the 8-card preset library contains, and how to read the Rewards tab.
If you haven’t added a card yet, the foundation post is the prerequisite.
What the Rewards Engine Is
The rewards engine is a deterministic, server-side calculator that takes your actual logged expenses and computes the points or cashback you should have earned. It sits in app/services/credit_rewards_service.py.
It is not:
- A scraper that reads your bank’s rewards statement.
- An estimator that guesses based on category averages.
- A connector to the issuer’s rewards API.
It is a rule engine. You configure the card’s rules (or apply a preset that ships with them), the engine reads your expenses, and the numbers fall out.
The deliberate choice not to scrape or estimate is part of why the numbers in MyFam360 match your issuer’s statement (when configured correctly). The downside: if your card’s rule library doesn’t match the issuer’s exact rules, the numbers drift. The preset library is the mitigation for that.
The 8-Card Preset Library
As of v2.8.0, MyFam360 ships presets for these cards:
| Preset key | Card | Headline earn |
|---|---|---|
hdfc_millennia | HDFC Millennia | 5% on online MCC merchants, 1% elsewhere |
hdfc_moneyback_plus | HDFC MoneyBack+ | 10x on Amazon/Flipkart/Swiggy/BookMyShow, 5x online, 1x offline |
sbi_simplyclick | SBI SimplyClick | 10x on online partner merchants, 5x other online, 1x offline |
icici_amazon_pay | ICICI Amazon Pay | 5% on Amazon, 2% on Amazon Pay merchants, 1% elsewhere |
flipkart_axis | Flipkart Axis | 5% on Flipkart, 4% on travel partners, 1.5% elsewhere |
axis_magnus | Axis Magnus | 25 EDGE rewards per ₹200, accelerated travel categories |
tata_neu_plus | Tata Neu Plus | 2% on Tata Neu app, 1.5% on Tata brands, 1% elsewhere |
tata_neu_infinity | Tata Neu Infinity | 5% on Tata Neu app, 1.5% non-Tata UPI, 1% elsewhere |
Each preset includes:
- Multiple rules with priority ordering
- Online sub-caps where applicable (e.g., HDFC Millennia’s 5% cap)
- Merchant-tier multipliers
- Card-wide monthly caps
- Surcharge waiver bounds (e.g., fuel surcharge waiver at petrol pumps)
To apply a preset: open the Rewards tab on the card detail page, tap Apply Preset, pick the matching key. The endpoint POST /families/{id}/credit-cards/{card_id}/rewards/apply-preset?preset_key=... is idempotent — applying the same preset twice soft-deletes the old profile/rules and inserts fresh ones, with audit logging.
If your card variant differs from the preset (a different earning rate, a merchant the preset missed), edit the rules after applying. The PUT /rewards/rules endpoint accepts a bulk replacement.
How a Rule Resolves
Every expense flowing through the engine resolves to exactly one rule. The resolution is priority-ordered:
- Channel filter —
online/offline/international. Expenses without a channel default tooffline. - Category filter — matches the expense’s category against the rule’s MCC list.
- Merchant filter — matches the expense’s merchant string against the rule’s allowlist (case-insensitive, substring).
- Date filter — for quarterly or seasonal rules.
The first rule that matches all four filters wins. Its earn_rate × amount is added to the cycle’s accumulated rewards.
If no rule matches, the base rate (configured on the rewards profile, typically 1%) applies.
The whole resolution is in _resolve_rule_for_expense() and is deterministic — same expense, same rule, same earned amount, every time.
Caps and Fallback
Two layers of caps:
Rule-Level Cap
A rule like “5% on online up to ₹1,000 per month” has a monthly_cap of ₹1,000. Once the accumulated rewards under that rule hit ₹1,000 for the cycle, the rule stops matching. Any further online spend falls back to the next-priority rule, eventually landing on the base rate.
Card-Wide Cap
The rewards profile has a monthly_cap (a hard ceiling). Once total rewards across all rules hit this number for the cycle, all earning stops regardless of which rule would have matched. This protects you from rule misconfigurations that would otherwise inflate rewards.
Both caps are visible in the Rewards tab as small “cap exhausted” badges next to each rule.
The Read Pattern (And Why It’s Decimal)
The engine reads expenses for the current cycle window (computed from the card’s billing_cycle_day):
expenses = (
db.query(Expense)
.join(Account, Account.id == Expense.account_id)
.filter(Account.id == card.linked_account_id)
.filter(Expense.expense_date >= cycle_start)
.filter(Expense.expense_date <= cycle_end)
.filter(Expense.is_deleted == False)
.all()
)
total_rewards = Decimal('0')
for exp in expenses:
rule = _resolve_rule_for_expense(exp, profile, rules)
earn = exp.amount * (rule.earn_rate / Decimal('100'))
total_rewards += earn
Note the Decimal accumulator. The project convention (CLAUDE.md → Credit-card rewards source) forbids SQL func.sum() over EncryptedDecimal columns — they’re encrypted at rest, so SQL can’t sum them. Iterating in Python with Decimal (not float, which loses paise precision) is the only correct path.
This is slower than a single SQL aggregate, but for the scale of a single cycle’s expenses (typically <500 rows) it’s invisible.
The Best-Card Recommendation
The function recommend_best_card_for_category(family_id, category, amount, channel) walks every active card, simulates earning the amount under the card’s rules accounting for current monthly cap headroom, and returns the card that would earn the most.
It powers the QuickAdd best-card hint that appears when you log an expense without picking a card. Tap “Use HDFC MoneyBack+” and the form switches to the right card with one click.
The recommendation respects:
- Cap headroom — a 10% card with no remaining cap loses to a 5% card with full headroom.
- Channel — online / offline / international filters apply.
- Category — a card with a category bonus wins for that category.
The Rewards Tab UI
Open any card’s Rewards tab to see:
- This cycle’s earned rewards — the live
Decimaltotal. - Breakdown by rule — how much each rule contributed.
- Cap status — “5/5 cap exhausted” or “₹400 of ₹1,000 cap remaining”.
- Rule editor — inline edits with bulk save.
- Apply Preset — re-apply any preset (warns about replacing current rules).
- Worth-keeping verdict (Family+ only) — rewards earned vs annual fee.
- Economics editor (Pro+ only) — APR, annual fee, base rate.
What This Means For You
If you own any of the 8 cards in the preset library: apply the preset and let the engine compute rewards in the background. Open the Rewards tab once a cycle to see what you actually earned.
If your card isn’t in the library: spend 10 minutes configuring the rules manually. Look at your card’s terms-and-conditions page, translate each “X% on Y” line into a rule, and save. You only do this once per card.
The single highest-leverage habit: before any large purchase (over ~₹2,000), glance at the QuickAdd best-card hint and use the recommended card. Over a year, that one habit recovers most of the rewards otherwise lost to unconscious card choice.
See Also
Take control of your family finances — free
MyFam360 lets your whole family track expenses, set budgets, and hit savings goals together. Free to start, no credit card needed.
Free plan available · No credit card required · Cancel anytime
Frequently Asked Questions
Which credit cards does MyFam360 have presets for?
Eight commonly-used Indian cards as of v2.8.0: HDFC Millennia, HDFC MoneyBack+, SBI SimplyClick, ICICI Amazon Pay, Flipkart Axis, Axis Magnus, Tata Neu Plus, and Tata Neu Infinity. Each preset includes the card's tiered earn rates (online, online-merchant categories, offline, international), monthly card-wide caps, and rule-level sub-caps. If your card isn't in the preset library, you can configure rules manually.
Where does the rewards engine get spend data from?
Exclusively from your logged expenses, via the credit card's mirror account. The DL.13 mirror relationship (credit_accounts.linked_account_id → accounts.id ← Expense.account_id) means every expense you log against the card's account is what the engine sees. It does not query a separate credit_transactions table (one doesn't exist; the Account Aggregator import path is deferred indefinitely per project strategy).
What happens when a rule's monthly cap is exhausted?
When a rule (e.g., '5% on online purchases up to ₹1,000 per month') reaches its cap, additional spend that would have qualified for the rule falls back to the base rate (typically 1%). The card-wide monthly_cap on the rewards profile is a hard ceiling — once you hit it, all further earning stops for the cycle regardless of which rule the spend matched. Both behaviours are visible in the Rewards tab as 'cap exhausted' badges.
Why doesn't MyFam360 use SUM() in SQL to compute rewards?
Because expense amounts are encrypted at rest using EncryptedDecimal columns, SQL can't aggregate them. The engine iterates expenses in Python with a Decimal accumulator (not float — float would lose paise precision). This is documented as Critical Learning v1.43 in the project conventions and is enforced across every rewards path.
Can I edit a preset after applying it?
Yes. Apply the preset to seed the rules, then open the Rewards tab and edit any rule inline. Common edits: bumping a category rate if your card variant earns more than the preset assumes, adding a new rule for a merchant category the preset missed, or removing a rule that doesn't apply to your variant. The PUT /rewards/rules endpoint accepts a bulk replacement so editing one rule doesn't corrupt the others.
What is the 'recommend best card for category' feature?
Given a category (e.g., 'Groceries') and an amount (e.g., '₹3,000'), recommend_best_card_for_category() in the rewards service evaluates every active card's rule set, accounts for monthly cap headroom, and returns the card that would earn the most rewards for that spend right now. This powers the QuickAdd best-card hint that appears when you log an online/offline/international expense without picking a card.
Share this article
Related Articles
How to Track Your Credit Cards in MyFam360 — The Foundation
Add credit cards to MyFam360 with joint cardholders, billing-cycle days, and an automatic account mirror that powers every downstream feature.
21 May 2026
App GuideAskAI History in MyFam360 — Pin, Re-Run, and Why the Cap Doesn't Reset
AskAI in MyFam360 now persists every question, lets you pin favourites, and supports one-click re-runs against current data. Here's how the history flow works.
21 May 2026
App GuideCredit Card Annual Fees and the 'Worth Keeping' Verdict in MyFam360
How MyFam360 charges and tracks annual fees automatically, and the Family+ 'Worth Keeping' verdict that tells you whether the card is paying for itself.
21 May 2026