Guide

Track a loan

Record a loan you owe (a car loan or mortgage) with a liability account, the asset it bought and an interest expense; split each payment into principal and interest.

A loan is money you owe, so the books carry it as a liability. When you borrow to buy something, the loan and the thing you bought both appear: the liability grows and an asset grows by the same amount. Each repayment then has two parts. The principal reduces what you owe. The interest is the lender's charge and is an expense; it does not reduce the debt.

The same layout serves a mortgage, a car loan, and a loan you make to a friend, with the roles reversed for the last: what the friend owes you is an asset, and the interest you receive is income.

Steps

  1. Create the accounts (Set up accounts): the asset you bought (ASSET), the loan (LIABILITY), the interest expense (EXPENSE), and the bank account you repay from.
  2. Record the purchase. The asset +, the loan -, both for the amount borrowed. If you also put down a deposit, a third split takes it from the bank account.
  3. Record each repayment with transaction.post as one transaction with three splits: the loan + (principal), the interest expense +, and the bank account - (the full payment). The lender's statement gives the split between principal and interest.
  4. Check the amount you still owe with account.balance on the loan account. It is negative, because it is a credit balance.
  5. Reconcile the loan account against each statement (Reconcile an account).
  6. Do not type every payment by hand? scheduledTransaction.loan builds a scheduled transaction whose formulas compute the principal and interest of each payment; see Schedule a transaction.
  7. When you sell the asset, record the sale as a deposit from the buyer and a withdrawal from the asset account, with any gain or loss in an income or expense account. Repay the loan with a payment of the remaining balance.

Example

A 20,000.00 car loan, and the first repayment of 450.00 (380.00 principal, 70.00 interest).

Example: with a new, empty book open as book.gnucash, at 2024-07-31T12:00:00Z.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"account.create","params":{"name":"Checking","type":"BANK","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":2,"method":"account.create","params":{"name":"Car","type":"ASSET","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":3,"method":"account.create","params":{"name":"Car loan","type":"LIABILITY","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":4,"method":"account.create","params":{"name":"Loan interest","type":"EXPENSE","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":5,"method":"transaction.post","params":{"datePosted":"2024-07-01","description":"Buy car","splits":[{"account":"Car","value":"20000.00"},{"account":"Car loan","value":"-20000.00"}]}}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "balanced": true,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":6,"method":"transaction.post","params":{"datePosted":"2024-07-31","description":"Loan payment 1","splits":[{"account":"Car loan","value":"380.00"},{"account":"Loan interest","value":"70.00"},{"account":"Checking","value":"-450.00"}]}}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "balanced": true,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":7,"method":"account.balance","params":{"account":"Car loan"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "balances": {
      "commodity": "CURRENCY::USD",
      "balance": {
        "num": "-1962000",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
account.create {"name":"Car","type":"ASSET","commodity":"USD"}
account.create {"name":"Car loan","type":"LIABILITY","commodity":"USD"}
account.create {"name":"Loan interest","type":"EXPENSE","commodity":"USD"}
transaction.post {"datePosted":"2024-07-01","description":"Buy car","splits":[{"account":"Car","value":"20000.00"},{"account":"Car loan","value":"-20000.00"}]}
transaction.post {"datePosted":"2024-07-31","description":"Loan payment 1","splits":[{"account":"Car loan","value":"380.00"},{"account":"Loan interest","value":"70.00"},{"account":"Checking","value":"-450.00"}]}
account.balance {"account":"Car loan"}
EOF

It prints:

[
  "…",
  "…",
  "…",
  "…",
  {
    "balanced": true,
    "…": "…"
  },
  {
    "balanced": true,
    "…": "…"
  },
  {
    "balances": {
      "commodity": "CURRENCY::USD",
      "balance": {
        "num": "-1962000",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
]

MCP tool call

Tool call:

{"name":"account.create","arguments":{"name":"Checking","type":"BANK","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"account.create","arguments":{"name":"Car","type":"ASSET","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"account.create","arguments":{"name":"Car loan","type":"LIABILITY","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"account.create","arguments":{"name":"Loan interest","type":"EXPENSE","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-01","description":"Buy car","splits":[{"account":"Car","value":"20000.00"},{"account":"Car loan","value":"-20000.00"}]}}

Result:

{
  "structuredContent": {
    "balanced": true,
    "…": "…"
  }
}

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-31","description":"Loan payment 1","splits":[{"account":"Car loan","value":"380.00"},{"account":"Loan interest","value":"70.00"},{"account":"Checking","value":"-450.00"}]}}

Result:

{
  "structuredContent": {
    "balanced": true,
    "…": "…"
  }
}

Tool call:

{"name":"account.balance","arguments":{"account":"Car loan"}}

Result:

{
  "structuredContent": {
    "balances": {
      "commodity": "CURRENCY::USD",
      "balance": {
        "num": "-1962000",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
}