Method

import.preview

Read a file and propose what importing it would do: the Import proposal, held by ID. Changes nothing.

Reads a file and says what importing it would do, without changing the book. The answer, the Import proposal, is held under an id until you apply or discard it. Nothing reaches the book without a preview first, whatever the format.

format is one of csvTransactions (GnuCash's Import Transactions from CSV), qif (Import QIF), csvAccounts, csvPrices, csvDocuments (Import Bills & Invoices) and csvOwners (Import Customers & Vendors). The file's content goes in files as text, or as base64 with an encoding; there is no path to read. Only QIF takes several files. The other params depend on the format: for CSV transactions and prices, a layout, by name or written out whole, which says the separator, the date and number formats and what each column is.

Only CSV transactions go through GnuCash's duplicate matcher (action is add, clear, update or skip for each transaction, with matches to choose from). A transaction that does not balance is not refused, as in GnuCash: applying it adds an Imbalance-<CUR> split, and the proposal flags it with imbalance beforehand. Rows that cannot be imported are listed in errors with GnuCash's own messages and are left out.

Proposal IDs (imp-1, …) count up from 1 in each server and are never reused while it runs, so a proposal made before the book was opened, or pushed out by 16 newer ones, is gone. Applying a proposal made at an older revision of the book is refused.

Examples

A bank's statement in a CSV file, as a layout with a base account describes it. The transfer account is unknown, so each transaction would be balanced against Imbalance-USD; give the account at import.apply.

Example: with a new, empty book open as book.gnucash.

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":"import.preview","params":{"format":"csvTransactions","files":[{"name":"bank.csv","text":"Date,Description,Amount\n2024-06-03,Coffee,-3.50\n2024-06-04,Lunch,-12.00\n"}],"layout":{"format":"csv","separators":",","skipStartLines":1,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","baseAccount":"Checking","columns":["Date","Description","Amount"]}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "id": "…",
    "format": "csvTransactions",
    "summary": {
      "add": 2,
      "imbalanced": 2,
      "errors": 0,
      "…": "…"
    },
    "newAccounts": [
      {
        "name": "Imbalance-USD",
        "type": "BANK",
        "commodity": "CURRENCY::USD"
      }
    ],
    "transactions": [
      {
        "index": 0,
        "description": "Coffee",
        "datePosted": "2024-06-03",
        "action": "add",
        "splits": [
          {
            "accountName": "Checking",
            "value": {
              "num": "-350",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "imbalance": {
          "value": {
            "num": "350",
            "denom": "100"
          },
          "…": "…"
        },
        "…": "…"
      },
      {
        "index": 1,
        "description": "Lunch",
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
import.preview {"format":"csvTransactions","files":[{"name":"bank.csv","text":"Date,Description,Amount\n2024-06-03,Coffee,-3.50\n2024-06-04,Lunch,-12.00\n"}],"layout":{"format":"csv","separators":",","skipStartLines":1,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","baseAccount":"Checking","columns":["Date","Description","Amount"]}}
EOF

It prints:

[
  "…",
  {
    "id": "…",
    "format": "csvTransactions",
    "summary": {
      "add": 2,
      "imbalanced": 2,
      "errors": 0,
      "…": "…"
    },
    "newAccounts": [
      {
        "name": "Imbalance-USD",
        "type": "BANK",
        "commodity": "CURRENCY::USD"
      }
    ],
    "transactions": [
      {
        "index": 0,
        "description": "Coffee",
        "datePosted": "2024-06-03",
        "action": "add",
        "splits": [
          {
            "accountName": "Checking",
            "value": {
              "num": "-350",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "imbalance": {
          "value": {
            "num": "350",
            "denom": "100"
          },
          "…": "…"
        },
        "…": "…"
      },
      {
        "index": 1,
        "description": "Lunch",
        "…": "…"
      }
    ],
    "…": "…"
  }
]

MCP tool call

Tool call:

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

Result:

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

Tool call:

{"name":"import.preview","arguments":{"format":"csvTransactions","files":[{"name":"bank.csv","text":"Date,Description,Amount\n2024-06-03,Coffee,-3.50\n2024-06-04,Lunch,-12.00\n"}],"layout":{"format":"csv","separators":",","skipStartLines":1,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","baseAccount":"Checking","columns":["Date","Description","Amount"]}}}

Result:

{
  "structuredContent": {
    "id": "…",
    "format": "csvTransactions",
    "summary": {
      "add": 2,
      "imbalanced": 2,
      "errors": 0,
      "…": "…"
    },
    "newAccounts": [
      {
        "name": "Imbalance-USD",
        "type": "BANK",
        "commodity": "CURRENCY::USD"
      }
    ],
    "transactions": [
      {
        "index": 0,
        "description": "Coffee",
        "datePosted": "2024-06-03",
        "action": "add",
        "splits": [
          {
            "accountName": "Checking",
            "value": {
              "num": "-350",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "imbalance": {
          "value": {
            "num": "350",
            "denom": "100"
          },
          "…": "…"
        },
        "…": "…"
      },
      {
        "index": 1,
        "description": "Lunch",
        "…": "…"
      }
    ],
    "…": "…"
  }
}

The base account can also be given beside the layout, which overrides the layout's own or gives one to a layout that has none, as choosing the account in GnuCash's assistant does. A saved layout can then serve several accounts:

Example: with a new, empty book open as book.gnucash.

JSON-RPC

Request:

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

Response:

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

Request:

{"jsonrpc":"2.0","id":2,"method":"import.preview","params":{"format":"csvTransactions","files":[{"text":"2024-06-03,Interest,1.25\n"}],"layout":{"format":"csv","separators":",","dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Description","Amount"]},"baseAccount":"Savings"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "transactions": [
      {
        "index": 0,
        "description": "Interest",
        "splits": [
          {
            "accountName": "Savings",
            "value": {
              "num": "125",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
account.create {"name":"Savings","type":"BANK","commodity":"USD"}
import.preview {"format":"csvTransactions","files":[{"text":"2024-06-03,Interest,1.25\n"}],"layout":{"format":"csv","separators":",","dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Description","Amount"]},"baseAccount":"Savings"}
EOF

It prints:

[
  "…",
  {
    "transactions": [
      {
        "index": 0,
        "description": "Interest",
        "splits": [
          {
            "accountName": "Savings",
            "value": {
              "num": "125",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "…": "…"
      }
    ],
    "…": "…"
  }
]

MCP tool call

Tool call:

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

Result:

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

Tool call:

{"name":"import.preview","arguments":{"format":"csvTransactions","files":[{"text":"2024-06-03,Interest,1.25\n"}],"layout":{"format":"csv","separators":",","dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Description","Amount"]},"baseAccount":"Savings"}}

Result:

{
  "structuredContent": {
    "transactions": [
      {
        "index": 0,
        "description": "Interest",
        "splits": [
          {
            "accountName": "Savings",
            "value": {
              "num": "125",
              "denom": "100"
            },
            "…": "…"
          }
        ],
        "…": "…"
      }
    ],
    "…": "…"
  }
}

In a book that has imported before, the Bayesian matcher proposes the account the same words and weekday went to last time (from: "bayes"), so import.apply needs no account for them:

Example: with a copy of the synthetic/import-map example book open as book.gnucash.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"import.preview","params":{"format":"csvTransactions","files":[{"text":"2024-06-03,Corner Grocer,-23.40\n2024-06-28,Salary ACME,2000.00\n"}],"layout":{"columns":["Date","Description","Amount"],"dateFormat":"y-m-d"},"baseAccount":"Assets:Checking"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "transactions": [
      {
        "description": "Corner Grocer",
        "action": "add",
        "other": {
          "accountName": "Expenses:Groceries",
          "from": "bayes",
          "…": "…"
        },
        "…": "…"
      },
      {
        "description": "Salary ACME",
        "other": {
          "accountName": "Income:Salary",
          "from": "bayes",
          "…": "…"
        },
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash import.preview '{"format":"csvTransactions","files":[{"text":"2024-06-03,Corner Grocer,-23.40\n2024-06-28,Salary ACME,2000.00\n"}],"layout":{"columns":["Date","Description","Amount"],"dateFormat":"y-m-d"},"baseAccount":"Assets:Checking"}'

It prints:

{
  "transactions": [
    {
      "description": "Corner Grocer",
      "action": "add",
      "other": {
        "accountName": "Expenses:Groceries",
        "from": "bayes",
        "…": "…"
      },
      "…": "…"
    },
    {
      "description": "Salary ACME",
      "other": {
        "accountName": "Income:Salary",
        "from": "bayes",
        "…": "…"
      },
      "…": "…"
    }
  ],
  "…": "…"
}

MCP tool call

Tool call:

{"name":"import.preview","arguments":{"format":"csvTransactions","files":[{"text":"2024-06-03,Corner Grocer,-23.40\n2024-06-28,Salary ACME,2000.00\n"}],"layout":{"columns":["Date","Description","Amount"],"dateFormat":"y-m-d"},"baseAccount":"Assets:Checking"}}

Result:

{
  "structuredContent": {
    "transactions": [
      {
        "description": "Corner Grocer",
        "action": "add",
        "other": {
          "accountName": "Expenses:Groceries",
          "from": "bayes",
          "…": "…"
        },
        "…": "…"
      },
      {
        "description": "Salary ACME",
        "other": {
          "accountName": "Income:Salary",
          "from": "bayes",
          "…": "…"
        },
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Prices from a file with a date and a rate on each line:

Example: with a new, empty book open as book.gnucash.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"import.preview","params":{"format":"csvPrices","files":[{"text":"2024-06-28,1.0850\n"}],"layout":{"format":"csv","separators":",","skipStartLines":0,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Amount"],"fromCommodity":"CURRENCY::EUR","toCurrency":"USD"}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "…",
    "format": "csvPrices",
    "summary": {
      "add": 1,
      "errors": 0,
      "…": "…"
    },
    "prices": [
      {
        "index": 0,
        "commodity": "CURRENCY::EUR",
        "currency": "CURRENCY::USD",
        "date": "2024-06-28",
        "amount": {
          "num": "10850",
          "denom": "10000"
        },
        "action": "add",
        "existing": null,
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash import.preview '{"format":"csvPrices","files":[{"text":"2024-06-28,1.0850\n"}],"layout":{"format":"csv","separators":",","skipStartLines":0,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Amount"],"fromCommodity":"CURRENCY::EUR","toCurrency":"USD"}}'

It prints:

{
  "id": "…",
  "format": "csvPrices",
  "summary": {
    "add": 1,
    "errors": 0,
    "…": "…"
  },
  "prices": [
    {
      "index": 0,
      "commodity": "CURRENCY::EUR",
      "currency": "CURRENCY::USD",
      "date": "2024-06-28",
      "amount": {
        "num": "10850",
        "denom": "10000"
      },
      "action": "add",
      "existing": null,
      "…": "…"
    }
  ],
  "…": "…"
}

MCP tool call

Tool call:

{"name":"import.preview","arguments":{"format":"csvPrices","files":[{"text":"2024-06-28,1.0850\n"}],"layout":{"format":"csv","separators":",","skipStartLines":0,"dateFormat":"y-m-d","currencyFormat":"period","encoding":"utf-8","columns":["Date","Amount"],"fromCommodity":"CURRENCY::EUR","toCurrency":"USD"}}}

Result:

{
  "structuredContent": {
    "id": "…",
    "format": "csvPrices",
    "summary": {
      "add": 1,
      "errors": 0,
      "…": "…"
    },
    "prices": [
      {
        "index": 0,
        "commodity": "CURRENCY::EUR",
        "currency": "CURRENCY::USD",
        "date": "2024-06-28",
        "amount": {
          "num": "10850",
          "denom": "10000"
        },
        "action": "add",
        "existing": null,
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Accounts, in the layout GnuCash's account export writes:

Example: with a new, empty book open as book.gnucash.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"import.preview","params":{"format":"csvAccounts","files":[{"text":"Type,Full Account Name,Account Name,Account Code,Description,Account Color,Notes,Symbol,Namespace,Hidden,Tax Info,Placeholder\nBANK,Savings,Savings,,,,,USD,CURRENCY,F,F,F\n"}]}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "…",
    "format": "csvAccounts",
    "newAccounts": [
      {
        "name": "Savings",
        "type": "BANK",
        "commodity": "CURRENCY::USD"
      }
    ],
    "accounts": [
      {
        "index": 0,
        "fullName": "Savings",
        "action": "add",
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash import.preview '{"format":"csvAccounts","files":[{"text":"Type,Full Account Name,Account Name,Account Code,Description,Account Color,Notes,Symbol,Namespace,Hidden,Tax Info,Placeholder\nBANK,Savings,Savings,,,,,USD,CURRENCY,F,F,F\n"}]}'

It prints:

{
  "id": "…",
  "format": "csvAccounts",
  "newAccounts": [
    {
      "name": "Savings",
      "type": "BANK",
      "commodity": "CURRENCY::USD"
    }
  ],
  "accounts": [
    {
      "index": 0,
      "fullName": "Savings",
      "action": "add",
      "…": "…"
    }
  ],
  "…": "…"
}

MCP tool call

Tool call:

{"name":"import.preview","arguments":{"format":"csvAccounts","files":[{"text":"Type,Full Account Name,Account Name,Account Code,Description,Account Color,Notes,Symbol,Namespace,Hidden,Tax Info,Placeholder\nBANK,Savings,Savings,,,,,USD,CURRENCY,F,F,F\n"}]}}

Result:

{
  "structuredContent": {
    "id": "…",
    "format": "csvAccounts",
    "newAccounts": [
      {
        "name": "Savings",
        "type": "BANK",
        "commodity": "CURRENCY::USD"
      }
    ],
    "accounts": [
      {
        "index": 0,
        "fullName": "Savings",
        "action": "add",
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Effect: read.

Params

The params of import.preview: the common ones and each format's own, chosen by format.

Type: PreviewParam.

Result

The Import proposal.

  • id (string, required): The proposal's ID, for import.apply and import.discard.
  • format (string, required): The format, as given.
  • bookRevision (integer (uint64), required): The Book revision it was made at: the number of Mutations the session had applied.
  • thresholdDate (Date or null): The auto read-only threshold date at the time of the preview, or null with no threshold.
  • summary (Summary, required): Counts.
  • ignoredLines (array of IgnoredLineWire, required): Lines the reader skipped.
  • errors (array of RowErrorWire, required): Rows that can't be imported, with GnuCash's message. None of their records appear below.
  • warnings (array of WarningWire, required): Things the caller should know about the whole import; each transaction's own are in its warnings.
  • newAccounts (array of NewAccountWire, required): Accounts the import will create, by full name, parents first.
  • newCommodities (array of NewCommodityWire, required): Commodities the import will create (QIF securities); none for CSV.
  • transactions (array of ImportedTransactionWire, required): One per transaction the file holds, in the order the importer builds them.
  • csv (CsvWire or null): CSV's own state: each account name the file uses and where it resolved.
  • documents (array of DocumentWire or null): csvDocuments: the documents, by index.
  • owners (array of OwnerWire or null): csvOwners: the customers or vendors, by index.
  • qif (QifWire or null): QIF's own state: the date formats to choose between, the account, category and payee maps, and the securities.
  • accounts (array of AccountRecordWire or null): csvAccounts: one per account row, in file order.
  • prices (array of PriceRecordWire or null): csvPrices: one per price line, in file order.