Skip to content

From a file

Settings → Data → Your data → Import a file is the restore button, and it is also the one bulk way in that needs neither an API key nor an MCP client. It reads a JSON file in the format Export your data writes, and merges its contents into the account you are signed in as. The file does not have to come from an export: one written by hand, or converted by a script from whatever your bank or a spreadsheet gives you, goes in the same way.

Only the file’s version is checked. Its contents are written as they stand, so getting the format below right is up to you, and the report the page prints afterwards tells you what was taken and what was not.

  • Version. The file carries schemaVersion, and this build reads 1, 2, 3 and 4. An export today writes 4, and a file you write should say 4 too. A file with no version, or another one, is refused whole, with nothing written.
  • Size. 25 MB at most. The page refuses a larger file before reading it, and the API refuses a larger body for the same reason; an export of years of operations stays far below it.
  • Amounts. Every amount, quantity and price is a decimal string, "1234.56", never a JSON number. A file containing one is refused before a single row is written, because a JSON number has already lost digits by the time it is read.
  • Encryption. A sealed export asks for its passphrase first. A file you write yourself is a plain one.

A file is one object. Everything but the version is optional, and a key left out means “nothing to say”, never “delete what is there”. The smallest useful file is an account, its balance and an operation:

{
"schemaVersion": 4,
"accounts": [
{
"name": "Joint account",
"type": "checking",
"currency": "EUR",
"manualBalances": [{ "date": "2026-09-30", "balance": "2140.18", "currency": "EUR" }],
"transactions": [
{ "date": "2026-09-28", "amount": "-64.90", "currency": "EUR", "label": "Groceries" }
]
}
]
}

An account needs a name and a type, and one without either is skipped and counted in the report. The type is one of the eleven the application knows: checking, savings, cto, pea, av, crypto_wallet, crowdlending, real_estate, loan, object and other. The restore does not check it, and an account under any other word is created all the same and valued as other, so spell it exactly.

Inside an account:

Key One entry is
manualBalances a balance on a day: date, balance, currency
transactions an operation: date, amount (negative is money out), label, currency
holdings a held line: an asset (its kind, isin or ticker, name) and a quantity
trades a dated order: the asset of its line, date, side (buy or sell), quantity, unitPrice, amount, currency

Write each key the table names. An order without its currency, for one, is not recognised on a second import and is written again.

Dates are written YYYY-MM-DD. An operation may also carry a fee, a tax, a note and a categoryName, which files it under the category of that name if you have one; one with no category lands filed nowhere, and Recategorize on Settings → Categories files it by your rules afterwards. The quickest way to see every other key, and the exact spelling of each, is to export your own account and open the file: the plain export is meant to be read in a text editor.

The restore merges. It never empties a table first, and it matches every row it reads on a natural key, never on a database id:

Row Matched on When it is already there
An account its name and its type, then its institution if two tie updated with the file’s
A balance its account and its day replaced by the file’s
An operation its fingerprint: date, amount and label in lower case left alone
A held line its account and its asset (ISIN, else ticker) updated with the file’s
A dated order every one of its figures counted, not written again
A category its name and its parent left alone
A price its asset and its day left alone

So the same file imported twice reports zeroes the second time, and a file sent again after you corrected one figure in it changes that figure and nothing else. So you can safely rework a converted file: import it, read the report, fix the file, import it again.

An operation written without a fingerprint of its own gets the one the import route would give it, so a month brought in from a file and later sent again by your assistant is not written twice. The same rule has a downside inside one file: two identical operations on one day collapse into one, and the report counts the one it dropped. To keep both, give each a dedupHash of its own, any text that differs, which is what the export does for an operation typed by hand.

Merging also means a file never removes anything. A row the file leaves out stays in your account, and an operation can only be deleted in one place: its own tab.

Putting back an export after something went wrong, or resuming a restore that was cut off halfway, is the operator’s side of this button: Restoring an export.