Reconcile an account
Match an account to a bank or card statement: start with the statement date and ending balance, tick the splits that appear on it, and finish when the difference is zero, or postpone.
Reconciling checks your books against the statement the bank sends. You tick every split that appears on the statement;
when the ticked splits bring the account to the statement's ending balance, the difference is zero and you finish.
The ticked splits become reconciled (y), and the next reconciliation starts from there. Each split is in one of
three states: not cleared (n), cleared (c, ticked but not final) or reconciled (y).
red-ale keeps no reconcile window. Each call is complete in itself: you carry the statement date, the ending balance and the list of ticked splits from call to call.
Steps
- Start with reconcile.start: the
account, thestatementDateand theendingBalancefrom the statement. It changes nothing. It returns the splits to consider, with the cleared ones already ticked, thestartingBalance(what was reconciled last time), thetickedBalanceand thedifferencestill to explain. Amounts use the account's raw sign, so for a credit card the balance is negative. Leave out the date and balance to get GnuCash's defaults, or a postponed reconciliation's. - Tick splits. Try a selection with reconcile.status, passing
mark: the splits you would tick, and it returns the new balances without keeping anything. To keep a split cleared between calls, set it with reconcile.setState, statec. - Let red-ale find a selection with reconcile.autoClear: give the
clearedBalancethe ticked splits must reach, and it finds the uncleared splits that make up the difference, as GnuCash's Auto-clear does. It refuses when no subset reaches that balance (reasonunreachable). - Finish with reconcile.finish, passing the same statement and the list of
tickedsplits. It is refused unless the difference is zero. The ticked splits become reconciled; the date and balance are remembered for next time (reconcile.info). - Cannot finish today? reconcile.postpone saves your ticks as cleared and remembers the
statement; the next reconcile.start picks it up (
resumedPostponed: true). - Find the cause of a difference by checking amounts and dates against the statement, and look for a transaction entered twice or not at all. If a transaction is missing, post it (Record deposits and withdrawals) and start again.
Example
Example: with a copy of the reports/reconcile example book open as book.gnucash.
JSON-RPC
Request:
{"jsonrpc":"2.0","id":1,"method":"reconcile.start","params":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00"}}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"statementDate": "1970-03-01",
"endingBalance": {
"num": "2100",
"denom": "100"
},
"resumedPostponed": false,
"difference": {
"num": "0",
"denom": "100"
},
"ticked": [
"d0000000000000000000000000000005"
],
"…": "…"
}
}
Request:
{"jsonrpc":"2.0","id":2,"method":"reconcile.status","params":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","mark":["d0000000000000000000000000000006"]}}
Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tickedBalance": {
"num": "1400",
"denom": "100"
},
"difference": {
"num": "1500",
"denom": "100"
},
"…": "…"
}
}
Request:
{"jsonrpc":"2.0","id":3,"method":"reconcile.finish","params":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","ticked":["d0000000000000000000000000000005"]}}
Response:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"reconciled": [
{
"split": "d0000000000000000000000000000005",
"from": "c",
"to": "y",
"…": "…"
}
],
"difference": {
"num": "0",
"denom": "100"
},
"…": "…"
}
}
Request:
{"jsonrpc":"2.0","id":4,"method":"reconcile.info","params":{"account":"Root:Asset:Bank"}}
Response:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"lastDate": "…",
"postponeDate": null,
"…": "…"
}
}
Command line
red-ale exec --book book.gnucash --script - <<'EOF'
reconcile.start {"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00"}
reconcile.status {"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","mark":["d0000000000000000000000000000006"]}
reconcile.finish {"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","ticked":["d0000000000000000000000000000005"]}
reconcile.info {"account":"Root:Asset:Bank"}
EOF
It prints:
[
{
"statementDate": "1970-03-01",
"endingBalance": {
"num": "2100",
"denom": "100"
},
"resumedPostponed": false,
"difference": {
"num": "0",
"denom": "100"
},
"ticked": [
"d0000000000000000000000000000005"
],
"…": "…"
},
{
"tickedBalance": {
"num": "1400",
"denom": "100"
},
"difference": {
"num": "1500",
"denom": "100"
},
"…": "…"
},
{
"reconciled": [
{
"split": "d0000000000000000000000000000005",
"from": "c",
"to": "y",
"…": "…"
}
],
"difference": {
"num": "0",
"denom": "100"
},
"…": "…"
},
{
"lastDate": "…",
"postponeDate": null,
"…": "…"
}
]
MCP tool call
Tool call:
{"name":"reconcile.start","arguments":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00"}}
Result:
{
"structuredContent": {
"statementDate": "1970-03-01",
"endingBalance": {
"num": "2100",
"denom": "100"
},
"resumedPostponed": false,
"difference": {
"num": "0",
"denom": "100"
},
"ticked": [
"d0000000000000000000000000000005"
],
"…": "…"
}
}
Tool call:
{"name":"reconcile.status","arguments":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","mark":["d0000000000000000000000000000006"]}}
Result:
{
"structuredContent": {
"tickedBalance": {
"num": "1400",
"denom": "100"
},
"difference": {
"num": "1500",
"denom": "100"
},
"…": "…"
}
}
Tool call:
{"name":"reconcile.finish","arguments":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"21.00","ticked":["d0000000000000000000000000000005"]}}
Result:
{
"structuredContent": {
"reconciled": [
{
"split": "d0000000000000000000000000000005",
"from": "c",
"to": "y",
"…": "…"
}
],
"difference": {
"num": "0",
"denom": "100"
},
"…": "…"
}
}
Tool call:
{"name":"reconcile.info","arguments":{"account":"Root:Asset:Bank"}}
Result:
{
"structuredContent": {
"lastDate": "…",
"postponeDate": null,
"…": "…"
}
}
A statement that does not match is refused, and nothing is reconciled:
Example: with a copy of the reports/reconcile example book open as book.gnucash.
JSON-RPC
Request:
{"jsonrpc":"2.0","id":1,"method":"reconcile.finish","params":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"9.00","ticked":[]}}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": 2001,
"message": "…",
"data": {
"help": "error/invalid"
}
}
}
Command line
red-ale exec --book book.gnucash reconcile.finish '{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"9.00","ticked":[]}'
It fails with exit status 2, printing on standard error:
{
"error": {
"code": 2001,
"message": "…",
"data": {
"help": "error/invalid"
}
}
}
MCP tool call
Tool call:
{"name":"reconcile.finish","arguments":{"account":"Root:Asset:Bank","statementDate":"1970-03-01","endingBalance":"9.00","ticked":[]}}
Result:
{
"isError": true,
"structuredContent": {
"error": {
"code": 2001,
"name": "invalid",
"message": "…",
"data": {
"help": "error/invalid"
}
}
}
}