Tracking Reward Point Systems In ledger-cli

This is the entry for the 24th in the Money Forward Kansai Advent Calendar 2024 , a blog relay event. Our other members have written a variety of articles in both English and Japanese.


Maintaining a personal ledger is mostly straightforward. Accounting for credit card charges is easy since each transaction usually comes with a paper (receipt) or digital (email, app history) record that can be logged. Cash is easy enough but fiddly and annoying. The various point systems in Japan took some more thinking; that’s what I’ll cover here.

If you’re unfamiliar with the point silliness, it’s the same idea as frequent flyer miles or other payment reward/cashback systems. Spend money, receive some fraction back as points, then spend those points again on another purchase. Yodobashi Camera, for example, usually return 10 points (usable as 10 yen) on each 100 yen spent which can be applied as a rolling 10% discount if used correctly.

I record my assets and spending in ledger-cli, a text-based accounting system. The accounting app my employer makes is apparently also pretty decent (available in Japan). This post is a matter of notation, the specific technology used isn’t important.

NOTE: For convenience I’m writing this in $ instead of ¥, it’s easier to type.

In ledger-cli a regular purchase looks like this:

2024-12-24 Traps for Santa
    Expenses:Security   $100
    Assets:Credit Card 1    -$100
# As with any double-entry accounting, these must sum to $0

This indicates $100 billed to a credit card, paying to the Security account. in reality the money went to a merchant somewhere, for the purposes of my accounting it’s flowed into the “Security” bucket and no longer my money. In the next month there will be another transfer to pay off the credit card:

2025-01-10 Pay CC
    Assets:Credit Card 1    $100
    Assets:Bank Account -$100

And then when I ask for a report, I see:

$100 Expenses
    $100 Security
-$100 Assets
    $0 Credit Card 1
    $900 Bank Account
# Bank account was at $1,000 before

My recording requirements are:

  • Credit card bills balance correctly at the end of the month (Assets:Credit Card 1 matches what the credit card company will pull out of my bank account)
  • Expense accounts correctly reflect my spending (If I spend $500 pulling gatcha on some mobile game I want that to show up on the statement)

The second requirement is so that I can keep an eye on my spending - both absolute values and the proportions I’m spending on various accounts. If it looks like I’m spending too much on games I can try to reel it in or reduce spending on something else to balance it out.

To integrate points into this I had a few ideas:

  • Option 1, Handle points as a separate account (Assets:Points). This is an entirely accurate, viable option but I don’t like it.

Purchases look like this:

2024-12-20 Buy traps
    Expenses:Traps  $80
    Assets:Points   -$20
    Assets:Credit Card 1    -$60

But logging all the minor increases is a pain and fills the file and the reports with a bunch of noise.

# 10 lines of this
2024-12-26 Receive points from buying traps
    Assets:Points   $1
    Income:Points

More importantly, having points included in my assets summary feels wrong.

$1,059 Assets 
    $900 Bank account
    $10 Points
    $50 Frequent Flyer Miles
    $99 Starbucks vouchers

While being roughly equivalent to cash they’re not 100% compatible. They can’t be converted to, or used with the same flexibility as cash - $10 in Starbucks vouchers does’t feel like cash because they can only be redeemed for face value at Starbucks. If somebody asks if I can lend them $1,000 the Assets top line says yes but the detailed accounts say it’s not possible.

  • Option 2: Handle as a separate account and separate currency (Assets:Points denominated in P)

This looks similar:


2024-12-26 Points from buying traps
    Assets:Points   P10
    Income:Points

2024-12-25 Buy KFC
    Expenses:Going out  $20
    Assets:Points   -P5
    Assets:Credit Card -$15
# ledger-cli allows multiple currencies and handles exchange rates automatically
# Based on this it will set $5 to be equivalent to P5 on this date

And the report:

$1,010 Assets 
P5
    -$15 Credit Card 1
    $1,000 Bank account
    P5 Points  
# The top lines read as a total of $1,010 and P5 in the Assets group of accounts

This solves the problem of distorting real cash in the assets report but not the annoyances of handling too many small incoming transactions.

  • Option 3: Consider the point-reduced price as the purchase price

This is simple and the numbers work out. Buying a $100 item paying for most of it with some points:

# Item list price is $100
2024-12-26 Knipex plier wrench
    Expenses:Tools $10
    Assets:Credit Card 1    -$10
    # Points reduced by $90 worth

But this allows too much space for dishonesty. The price tag was $100, so I want it reported as $100. The :Tools account would go up by $10 instead of $100 which matches the decrease in my credit card balance, but I committed another $90 of spending ability to the purchase.

If my Expenses:Tools account is already up to $500 for the month, I don’t want to look at those pliers and think it’s fine to squeeze them in because the credit card balance only changes by $10.

If I had a coupon that actually took the price down to $10 I would record the purchase at $10 and be done with it; my overall spending ability has only gone down $10. Marking that sale as $100 spent and the coupon as $90 Income or Saved will lead to ruin because buying more junk looks like earning money.

# Original price $100, $90 reduced with a coupon
2024-12-26 Knipex plier wrench
    Expenses:Tools $100
    Assets:Credit Card 1    -$10
    Income:Coupons  -$90
# This is not, in fact, earning $90

  • Option 4: Record transactions at full price and resolve the difference later.

Simply ignore the points in the transaction:

2024-12-26 Knipex bolt cutters
    Expenses:Tools  $100
    Assets:Credit Card 1    -$100
# But the actual credit card charge was only $50 - the mismatch against the real bill is Points

Obviously the credit card charge is wrong. Doing this and resolving the difference as points spent at the end would work (card company takes $1000, my accounting says $1,200, so $200 worth was points) but any other errors or forgotten transactions will be hidden and forgotten. Matching transaction entries against the real credit card statement becomes impossible and the whole thing just feels wrong. This method stretches the accuracy of the system a bit too far.

  • Option 5: Log spent points as income.

Consider points at the point of payment, but don’t try to track the balance:

2024-12-26 Buy stuff half with points
    Expenses:Books $100
    Income:Points   -$50
    Assets:Credit Card 1    -$50
# The Income:Points record would have occurred when the points are received under patterns 1 and 2

At the end of the month I can see how much money I “saved” (kind of) using points but all entries are correct and consistent. The timing when points are received is incorrect but that is not information I ever found a use for.

As a bonus, if some points evaporate (expire) I don’t need to think about it too much or guilt myself into using them to buy junk. The border of the system excludes point balance; they are not an asset of interest.

Option 5 is how I currently record my accounts. By choosing the borders of my accounting system I can see the information I want and make spending decisions based on clear, honest data.


I have some utility scripts for ledger-cli on github.