DocReadi

Master data

Master data

Master data is what DocReadi knows about the world beyond the document in front of it: your own legal entities, the vendors and customers you deal with, and — if you use it — your chart of accounts. Extraction, validation, and (where enabled) GL posting all lean on these registries, and they get more accurate the more you use DocReadi, because confirming a match teaches the registry for next time. Managing master data requires the Admin role; correcting a GL posting on a specific document only requires Reviewer.

Entities

Open Settings → Master data → Entities (also reachable directly as /entities). Entities are the names on your side of a deal — the legal entities that are you, not a vendor or customer. DocReadi uses your confirmed entity list for direction validation: on an AP invoice, the buyer named on the document should match one of your entities; on a sales invoice, the issuer should. If it doesn't, DocReadi raises a validation warning rather than assuming you made a mistake — it's often a sign the document was classified as the wrong direction (an invoice you issued, misread as one you owe) or genuinely misclassified, and in some cases DocReadi will detect and correct the direction automatically, leaving a note on the document explaining what it changed.

If your workspace has no entities recorded yet, the page offers to add your signup company name as your first one — a single click, never automatic, because one wrong entity silently poisons every direction check that follows.

Each entity carries a Company name, optional Keywords (distinctive words that identify it even when the name on a document varies slightly), an optional VAT number, and Notes. New entities detected in your documents first appear as candidates — tagged "Needs Review" — and only count toward direction validation once you confirm them; confirming a candidate also re-checks any of your documents that were flagged against that name, clearing stale "unknown entity" warnings automatically.

From the entity list you can Edit or Delete a row, toggle it Active, or use the bulk-action bar (select rows first) to confirm, dismiss, toggle, delete, or move to counterparty — for a row that turns out to be a vendor or customer of yours rather than one of your own entities. A move that finds a matching VAT on an existing counterparty folds in as an alias rather than creating a duplicate; a genuine name clash is blocked so you can reconcile it by hand. ↓ Export CSV and ↑ Import CSV round-trip the whole entity list — useful for a one-time bulk load when you're setting up. If you're starting from scratch, Download the CSV template above the list gives you a header row plus one example row in the shape DocReadi expects — only canonical_name is required, and re-importing the same file later updates existing rows by name rather than duplicating them.

DocReadi can also fill in an entity's VAT number for you: once documents from two or more different vendors name that entity as the buyer or issuer and carry the same VAT number, DocReadi records it — but only into a blank VAT field, never overwriting one you've set by hand. Click history next to an entity's VAT number to see where that number came from: the panel groups every observation by VAT number, shows how many distinct vendors' documents backed each one (with a current badge on the VAT the entity holds today), and lists each observation's vendor, a link to the source document, and when it was seen. Use it to audit a VAT DocReadi filled in automatically, or to see why a VAT hasn't been filled yet (it needs a second, independent vendor's document before it will).

Counterparties

Open Settings → Master data → Counterparties (/counterparties). This is your vendor and customer registry — every counterparty DocReadi has seen or you've added by hand, used to improve classification, pre-fill extraction, and catch anomalies.

Adding or editing a counterparty by hand carries the usual Name, Type (vendor, customer, or both), VAT number, Keywords, Aliases, address, and bank details, plus four contact/locale fields: Email, Phone, Currency (a 3-letter code, e.g. ZAR — the currency this counterparty usually bills in) and Country (a 2-letter code, e.g. ZA). DocReadi rejects an obviously malformed value on save — an email without an "@", or a currency/country code that isn't the right length — and stores currency and country in uppercase.

Payment terms is a "counted from" menu plus a number: days after the invoice date (the default), the end of the invoice month (leave the number empty), the end of a following month (the number is months, so 1 covers "30 days from statement"), days after the end of the invoice month, or a day of the following month or of the invoice month. When a document has no due date and prints no terms, an export uses these terms before the workspace default (see Default payment terms).

The Docs column shows how many documents are booked to each counterparty — click the count, or the Documents link next to Edit/Delete, to open your document list filtered to that one vendor or customer. The filtered list shows a "Vendor: <name>" chip with a ✕ to clear it, and the filter stays in place as you page through, approve, reject, or delete documents from the list.

GL defaults

If your workspace has loaded a chart of accounts or tax codes (see "GL accounts, tax codes, and posting defaults" below), the edit form for a counterparty gains a GL defaults row:

These only take effect once GL determination itself is switched on (see below) — setting them here just records the default for when it is.

Once a chart of accounts is loaded, the confirmed list also grows a GL column on vendor rows so you can tag defaults without opening the edit form: click the account code (or the em-dash if none is set) to open a searchable picker, choose an account to save it on the spot, or pick — none — to clear it. The Missing GL button in the toolbar filters the list down to the vendors that still have no default account, so you can work through them before, say, pushing contacts to Xero.

Candidates

A counterparty DocReadi hasn't seen confirmed before is added as a candidate, listed separately with a "Needs Review" pill. A candidate auto-confirms into your main registry once it's been observed consistently (matching name and VAT) enough times — 3 by default. You can change this under Settings → Review and approval → Counterparty auto-confirm: turn auto-confirm off entirely (every new counterparty waits for a human) or adjust the number of observations required. Candidates with no activity for 90 days can be swept away with Dismiss stale; a dismissed candidate is simply re-suggested if the same name shows up again. Per-row Confirm and Dismiss are also available, along with a bulk-action bar for confirming, dismissing, or moving a batch of candidates to the entity registry instead (for a row that turns out to be one of your own entities, not a counterparty). The bank accounts read from a candidate's documents are listed on its row marked pending: confirming it accepts an account only when exactly one was seen (see Anomaly baselines).

Aliases

An alias is an alternate name that resolves to the same counterparty — a document written to "ACME Suppliers (Pty) Ltd" should still match your existing "Acme Suppliers" record. DocReadi learns aliases automatically: renaming a counterparty preserves its old name as an alias, and a confident match (an exact VAT or an existing alias) writes the name variant it just saw back into the registry so the same document reads correctly next time. A weaker fuzzy or keyword match never writes an alias on its own — that would risk teaching the registry the wrong name from a one-off guess. The counterparty list shows an alias count per row.

The Aliases field on the add and edit forms (comma-separated) is where you review or correct the list by hand. Editing it replaces the stored list, which is deliberate: if a weak match ever taught the registry a wrong name, removing it here is how you un-learn it. Renaming a counterparty still auto-preserves the outgoing name as an alias even if you also edited the Aliases field in the same save, so a rename never orphans the documents already recorded under the old name. You can also bulk-edit aliases through CSV export/import or the API.

The same confident matches also fill in a counterparty's Email or Currency when that field is still empty, reading the value straight off the matched document (the vendor's printed email address, or the document's currency). This only ever fills a blank — a value you typed yourself, or one already on record, is never overwritten, and a weaker fuzzy or keyword match never triggers it.

Anomaly baselines

Once a counterparty is confirmed, DocReadi compares what a new document says about it against what's on file, and raises a warning if something looks off:

These show up as validation warnings on the document itself.

Bank accounts wait for an admin. A bank account DocReadi reads on a document from a confirmed counterparty, and that isn't one of its accepted accounts, is recorded as pending — never accepted automatically. Every document carrying a pending account shows the New bank account warning: the first one, the second one and every one after it, whether or not the first was approved or rejected. Rejecting a document does not accept or remove its account. The warning stays until an Admin decides:

Only the Admin role can accept or reject a bank account; a Reviewer sees the warning but not the buttons, and nothing a Reviewer does — Edit Fields, approving, rejecting — accepts one. A bank account or IBAN typed or corrected in Edit Fields is treated like one read from the document: when saved it is recorded as pending on the counterparty (it shows under "Bank account pending"), and the document warns until an Admin accepts it — saving it, even as an Admin, is not accepting it. DocReadi records who decided and their note. The same account written differently ("Acc No. 4099 887-7665" and "40998877665") counts as one account. Pending accounts are never exported, never pushed to Xero, and never shown in the edit form's accepted list.

Two cases are accepted without asking:

For an address, accept it from the warning on the document the same way. Until someone accepts it, an unrecognised-address warning stays on that document through re-validation and edits, even though DocReadi has already noted the address against the counterparty; a later document from the same address isn't flagged again. Adding an account or address that isn't on the counterparty yet yourself — in its edit form, or through a registry import — counts as accepting it too, from each document's next re-validation. Merging counterparties keeps the warning on the merged documents unless the counterparty you keep already had that account or address; pending and rejected accounts stay pending and rejected after a merge.

Merge

Select two or more confirmed counterparties and choose Merge to fold duplicates together. Pick the counterparty that survives — every other selected row folds into it (names, keywords, bank accounts, addresses; the survivor's own values win on conflict) and is then deleted. Every document, GL alias, and posting that pointed at a folded-in row is repointed to the survivor automatically. A conflicting VAT number between two selected rows blocks the whole merge rather than silently picking one. This cannot be undone — use Merge, not Delete, for a genuine duplicate; plain deletion does not repoint the documents that referenced the row (their counterparty link is cleared instead, so they show no counterparty afterwards).

Bulk actions and other tools

Beyond merge, the bulk-action bar covers confirm, dismiss, toggle active, delete, and move-to-entity, mirroring the entity list. ↓ Export CSV and ↑ Import CSV round-trip the full registry (names, type, VAT, addresses, bank accounts, aliases, keywords) — the fastest way to bulk-load a vendor list or edit alias data outside the app; imports upsert by name and report how many rows were created, updated, or skipped, with the first error shown if any row failed. If you're migrating a vendor list from another system, Download the CSV template above the list gives you the header row plus one example row in the shape DocReadi expects — only canonical_name is required, columns it doesn't recognise are ignored, and you can rename an existing export's name column to canonical_name and import it directly. The typical_vat_rate column takes the rate as a percentage or a fraction — 15, 15%, 0.15 and 0,15 all mean 15%. A value that isn't a VAT rate skips that row, like any other row error.

If a counterparty disputes an auto-approved document

Any fully automated decision — an auto-approved document — must give the person it affects a way to contest it. If a counterparty you've billed disputes a document you auto-approved, it comes back to your workspace automatically: the document is flagged with their stated reason and lands back in your review queue for a fresh manual look.

GL accounts, tax codes, and posting defaults

Open Settings → Master data → GL accounts (/gl-accounts). This is where you load your chart of accounts if you want DocReadi to determine a GL posting for each line on an approved document — entirely opt-in: the chart-of-accounts screens work whether or not this is switched on, but nothing posts until you both load your accounts and enable GL determination under Settings → Feature flags. With it off, DocReadi extracts and validates documents exactly as usual; it simply doesn't attempt to say which account each line belongs to.

GL accounts support ↓ Export CSV / ↑ Import CSV for bulk loading a chart of accounts; tax codes are managed through the form (there are rarely more than a handful). Marking a tax code default moves the default there — only one code is the default at a time.

On the Defaults page, an Approval gate control — Require every GL line assigned before approval — lets you turn GL determination from advisory into a hard requirement. Off (the default), a document approves normally even if some lines couldn't be resolved to an account. On, a document of a GL-posting type (AP and sales invoices and their credit notes, and receipts) whose lines can't be resolved from your vendor defaults, learned aliases, or a doc-type default is held for review instead of approving — see Approving with unresolved GL lines for what the reviewer sees.

When GL determination is enabled, DocReadi decides each line's account through a deterministic cascade, trying more specific rules before more general ones: an explicit match, then a learned alias for that counterparty, then — if the counterparty's GL default mode is set to Always use — its default account for every remaining line, otherwise a keyword match on the line description, falling back to the counterparty's default account (when set to Prefer) if no confident keyword match is found, then the document type's default, and finally the suspense account. A second, separate flag lets an LLM take a tiebreaker pass on lines nothing else could classify (this costs one credit per document where it runs).

Postings review and the learning loop

Once GL determination is on, open GL postings from a processed document's viewer to see how it posted: each line's type (expense, income, or tax), account, amount, and which cascade tier decided it, with a confidence score. Tax and control-account postings are derived and can't be edited directly; expense and income postings can. To correct one, type the right account into the line and choose Set. If the per-line VAT accrual didn't reconcile with the document's VAT total when the postings were built, a notice at the top of the tab shows the difference — check the line VAT rates, fix via Edit Fields if needed, and re-approving rebuilds the postings and clears it. (Ordinary cent-level rounding across many lines is tolerated and won't trigger the notice.)

A default, vendor default, or tax code that points at an account that is inactive, or whose role no longer fits (for example a tax code whose account isn't a tax account any more, after a change in Xero), is skipped rather than posted to. The tab then lists each skipped account with its reason under Some configured accounts were skipped when these postings were built; the lines fall through to the next rule. Point the setting at a usable account and re-approve to rebuild the postings.

If the paid AI tiebreaker is switched on but didn't decide this document's lines, the tab says The AI tiebreaker didn't run for this document and gives the reason: there were no credits left when it was approved, the credit check failed, it could not be started, or the AI model did not return an answer. If postings were built, the lines it would have decided were posted to the document type's default or the suspense account, so correct them on the tab, or re-approve to try again; if none were built, re-approve the document to try again. If a setting couldn't be read while the postings were built, a notice reads Some settings couldn't be read when these postings were built and names it (your tax country, or the auto-override threshold); re-approve to rebuild the postings.

If the build itself failed at approval, the tab shows Postings could not be built with the cause (a database error or an internal error) in place of the usual "No postings yet" text. The document was approved without GL postings. Re-approving it rebuilds them; if it fails again, contact support with the document's link.

Correcting a posting also teaches the engine: if the document's counterparty is a resolved, confirmed record, your correction is remembered for that counterparty's future invoices with a matching line description — so a class of expense you correct once for a given supplier posts correctly from then on. If the counterparty on this particular document isn't resolved, the correction only applies to this document.

Next steps

Looking for the developer/API reference? See /api/docs-guide. Can't find an answer? Email [email protected].