Guide

Record deposits and withdrawals

Enter income, expenses and cash withdrawals as balanced transactions, then check the balance and list what you have entered.

Day-to-day bookkeeping is a sequence of transactions: your pay arrives in the bank, you buy groceries, you take cash out of a machine. In double-entry bookkeeping each one is a date, a description and two or more splits whose values sum to exactly zero. A value is in the transaction's currency; positive values are debits, negative values credits.

The sign rule

The account you name decides what a sign means. A positive value on a bank account is a deposit, a negative one a withdrawal. On an income account the signs run the other way, because income is a credit: pay of 2,500.00 is +2500.00 on the bank account and -2500.00 on the income account. An expense is + on the expense account and - on the account you paid from.

Steps

  1. Make the accounts the transaction needs (see Set up accounts): a bank account, a cash account, an income account and an expense account.
  2. Record a deposit: transaction.post with datePosted, description and two splits, the bank account + and the income account -.
  3. Record an expense: the expense account + and the account that paid -.
  4. Record a cash withdrawal: a transfer from the bank account to the cash account, - and +. It is neither income nor expense, so no category is involved.
  5. Check the balance with account.balance, and review the entries with transaction.list, optionally for one account and a date range.

If the splits do not sum to zero the call fails with unbalanced and nothing is recorded, so a typing slip never leaves a half-entered transaction.

Example

Example: with a new, empty book open as book.gnucash, at 2024-07-15T12: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":"Wallet","type":"CASH","commodity":"USD"}}

Response:

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

Request:

{"jsonrpc":"2.0","id":3,"method":"account.create","params":{"name":"Salary","type":"INCOME","commodity":"USD"}}

Response:

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

Request:

{"jsonrpc":"2.0","id":4,"method":"account.create","params":{"name":"Groceries","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":"July pay","splits":[{"account":"Checking","value":"2500.00"},{"account":"Salary","value":"-2500.00"}]}}

Response:

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

Request:

{"jsonrpc":"2.0","id":6,"method":"transaction.post","params":{"datePosted":"2024-07-03","description":"ATM","splits":[{"account":"Wallet","value":"100.00"},{"account":"Checking","value":"-100.00"}]}}

Response:

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

Request:

{"jsonrpc":"2.0","id":7,"method":"transaction.post","params":{"datePosted":"2024-07-05","description":"Market","splits":[{"account":"Groceries","value":"63.40"},{"account":"Wallet","value":"-63.40"}]}}

Response:

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

Request:

{"jsonrpc":"2.0","id":8,"method":"account.balance","params":{"account":"Checking"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "balances": {
      "commodity": "CURRENCY::USD",
      "balance": {
        "num": "240000",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":9,"method":"account.balance","params":{"account":"Wallet"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 9,
  "result": {
    "balances": {
      "balance": {
        "num": "3660",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":10,"method":"transaction.list","params":{"account":"Wallet"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 10,
  "result": {
    "transactions": [
      {
        "description": "ATM",
        "…": "…"
      },
      {
        "description": "Market",
        "…": "…"
      }
    ]
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
account.create {"name":"Wallet","type":"CASH","commodity":"USD"}
account.create {"name":"Salary","type":"INCOME","commodity":"USD"}
account.create {"name":"Groceries","type":"EXPENSE","commodity":"USD"}
transaction.post {"datePosted":"2024-07-01","description":"July pay","splits":[{"account":"Checking","value":"2500.00"},{"account":"Salary","value":"-2500.00"}]}
transaction.post {"datePosted":"2024-07-03","description":"ATM","splits":[{"account":"Wallet","value":"100.00"},{"account":"Checking","value":"-100.00"}]}
transaction.post {"datePosted":"2024-07-05","description":"Market","splits":[{"account":"Groceries","value":"63.40"},{"account":"Wallet","value":"-63.40"}]}
account.balance {"account":"Checking"}
account.balance {"account":"Wallet"}
transaction.list {"account":"Wallet"}
EOF

It prints:

[
  "…",
  "…",
  "…",
  "…",
  {
    "description": "July pay",
    "balanced": true,
    "…": "…"
  },
  {
    "balanced": true,
    "…": "…"
  },
  {
    "balanced": true,
    "…": "…"
  },
  {
    "balances": {
      "commodity": "CURRENCY::USD",
      "balance": {
        "num": "240000",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  },
  {
    "balances": {
      "balance": {
        "num": "3660",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  },
  {
    "transactions": [
      {
        "description": "ATM",
        "…": "…"
      },
      {
        "description": "Market",
        "…": "…"
      }
    ]
  }
]

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":"Wallet","type":"CASH","commodity":"USD"}}

Result:

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

Tool call:

{"name":"account.create","arguments":{"name":"Salary","type":"INCOME","commodity":"USD"}}

Result:

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

Tool call:

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

Result:

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

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-01","description":"July pay","splits":[{"account":"Checking","value":"2500.00"},{"account":"Salary","value":"-2500.00"}]}}

Result:

{
  "structuredContent": {
    "description": "July pay",
    "balanced": true,
    "…": "…"
  }
}

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-03","description":"ATM","splits":[{"account":"Wallet","value":"100.00"},{"account":"Checking","value":"-100.00"}]}}

Result:

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

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-05","description":"Market","splits":[{"account":"Groceries","value":"63.40"},{"account":"Wallet","value":"-63.40"}]}}

Result:

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

Tool call:

{"name":"account.balance","arguments":{"account":"Checking"}}

Result:

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

Tool call:

{"name":"account.balance","arguments":{"account":"Wallet"}}

Result:

{
  "structuredContent": {
    "balances": {
      "balance": {
        "num": "3660",
        "denom": "100"
      },
      "…": "…"
    },
    "…": "…"
  }
}

Tool call:

{"name":"transaction.list","arguments":{"account":"Wallet"}}

Result:

{
  "structuredContent": {
    "transactions": [
      {
        "description": "ATM",
        "…": "…"
      },
      {
        "description": "Market",
        "…": "…"
      }
    ]
  }
}