Skip to main content
Sooner or later somebody hands you fifty thousand rows. The wrong way to handle that is to read them through an AI model: it costs the client real money, and a model reading row forty thousand can drift into a different interpretation than it had at row two — producing a ledger that is plausible and wrong. Zeno splits the job. The agent works out the shape from a sample of about fifteen rows. The engine applies that shape to every row deterministically: exact decimal money, one date parser, and a warning for each row it could not read.

Look before you read

Start by inspecting the file. That costs almost nothing and answers the only questions that matter up front: what format it is, and — for a spreadsheet or CSV — its headers, a handful of sample rows, and which columns actually parse as dates and amounts. Some formats describe their own columns, and the inspection says so: A file already sitting in the inbox can be imported where it is. There is no need to re-upload it.

A spreadsheet or CSV

Work out from the sample what each column means, then hand over a column map. Required: a date, an amount, and a kind — one kind throughout, or a column naming the kind per row for a mixed register. Optional: the counterparty, account, item, quantity, class, memo, reference number, due date, and a source reference. Values the file does not carry at all can be supplied as constants. Two options are worth knowing:
  • groupBy — when several rows make one document. A bill register keyed by bill number is many lines and few bills; without this, every row becomes its own transaction.
  • invertAmounts — when the export signs money the other way round.
The column map is shown to the reviewer as part of the plan, so a column read as the wrong thing is caught before anything posts, not after.

A QuickBooks Desktop file

An IIF export becomes a plan in one step. IIF has a published grammar, so it is parsed by a parser rather than read by a model. The name lists in the file — accounts, customers, vendors, items, classes, terms, payment methods — become the plan’s lists section, and the transactions become its entries. That is what makes a migration reviewable as one thing: the chart of accounts, the customer list, and the history that references them arrive together, and a reviewer can strike a proposed name as readily as a proposed entry.
Read the warnings out loud before approving. They carry every block that did not reconcile against its own total, every transaction kind QuickBooks Online has no equivalent for, and every payment that will post unapplied. They are the difference between a migration you can stand behind and one that merely finished.
Where QuickBooks Online has no equivalent at all — inventory adjustments, assemblies, sales orders, item receipts, price levels — the import says so by name rather than approximating something.

Dates

An import is historical by nature, so both import paths default to a migration date policy: far-past dates are expected, and their notes are downgraded to information rather than warnings. Ask for the standard policy when you want old and far-future dates to warn — which is right for a file that is supposed to be current.

It is still a plan

Nothing above writes to QuickBooks. Each of these produces an ordinary plan, and it goes through plan, review, apply, reverse like everything else: somebody reads the approval table, approves it in their own words, and the run that applies it returns the id that undoes it. On a fifty-thousand-row import, review the shape rather than each line: the totals by kind, the date range, the count of blocked names. The plan renders both.

When an import went wrong

If a batch posted and should not have, reverse its run — that is the first answer and usually the only one needed. For everything else — duplicate bills from two different imports, a wrong-month batch, a mass recode — there is a bulk cleanup plan: void, delete or correct many documents already in QuickBooks as one approval table and one reversible run. Each target is pinned to the revision it carries at planning time, so a document somebody edited between the approval and the apply is refused rather than acted on. Every action is journalled with the document’s pre-image before anything happens, so the run reverses: a void or an edit is restored onto the same document, a deleted one can only come back under a new id, and the reversal says which it did.
Void keeps the number and the audit trail, and is the right default. Delete leaves nothing. For a single document, use the single-document tools instead — a batch of one makes an approval table lie about what it is.
The tools behind this page are listed under importing a file and correcting what is already posted.