Audit trail
Every change to a document in inletAP is written to an audit log: what changed, who or what changed it, and when. This page describes what is recorded, what is not, and how to get an answer out of it when somebody asks where a number came from. Workspace configuration is largely in the log too, with one exception named below: approval tiers.

It is worth reading if you close the books, answer auditor questions, or have to explain an approval to an owner six months after the fact.
What one entry records
| Part of the entry | What it holds |
|---|---|
| Timestamp | When the change happened, to the second. |
| Actor type | user, system or rule. |
| Actor | The person's name, when the actor was a person. |
| Event type | What happened — extracted, fields_updated, approved, exported and so on. |
| Document | The invoice the entry belongs to, where the event concerns one. |
| Before | The previous value, on the events that carry one: field edits, status changes, restores, allocation edits, role changes, member removals and revoked invitations. |
| After | The value it holds now, plus any detail the event carries. |
The trail names the actor, the moment and both values for every field edit, so "who changed this total, when, and what did it say before" is answerable from the one entry. A field edit records the value it was changed to and the value it was changed from, on the same keys, so the two sides diff against each other field by field. A field the invoice did not have before reads as empty rather than as missing, which is how "was blank, now $4,000.00" stays different from "this edit did not touch the total". The before value covers the keys that edit changed, not the rest of the document. Field edits are not the only events that carry one — status changes, restores, allocation edits, role changes, member removals and revoked invitations record a previous value too, as the table above says. What has no previous value to record is a decision rather than a change: an approval, a rejection, a routing decision or an export attempt is written with its detail and no before side.
Actor types
There are three, and they are kept apart deliberately.
| Actor type | Means |
|---|---|
user | A person, named. Field edits, approvals, rejections, restores. |
system | The pipeline itself. Parsing, extraction, holding on quota, export attempts. |
rule | A suggestion the product generated from your history, such as a proposed split. Coding-rule matches are recorded under system today, alongside the rest of the pipeline. |
The distinction is the reason the log is worth keeping. An auditor's first question about automation is never "does it work", it is "how do I tell what the machine did from what a person did". Filtering the log to people only, or to automation only, answers that in one action.
Field sources
Separately from the actor, each extracted field records where its value came from.
| Source | Means |
|---|---|
ocr | Read off the document itself. |
body | Read from the text of the email rather than an attachment. |
rule | Written by one of your rules — a default GL account, for example. |
user | Typed or corrected by a person. |
A GL account with source rule and a GL account with source ocr are very different claims about the same number. The first is your standing instruction; the second is something a model believes it saw printed on a page. Keeping them distinct is what lets you decide how hard to look.
What is logged
Documents accumulate entries from the moment the message arrives: parsing, extraction with its confidence, a rule match and what it set, a hold on plan quota, a filtered document and a later restore, field edits, a duplicate marked against its original, the send for approval, each approval or rejection with its comment, and each successful export with the ledger record it created. Export failures and retries are in the trail as well. A bill that stops without reaching your ledger writes export.failed, carrying the batch, the destination, the invoice where the failure belongs to one, and the fault code or message the ledger returned; a batch that ends with bills needing a person writes one of its own for the batch as a whole. Pressing Retry writes export.retried against the person who pressed it, once per retry that actually ran — a second click on the same batch queues nothing and records nothing. One deliberate exception: a bill the ledger already holds writes no failure event, because it posted, and export.failed beside exported for the same bill would say otherwise. Read export failures for what to do about one; the trail is the record that it happened.
Membership changes are recorded too — invitations sent, accepted and revoked, role changes and removals — because "who was allowed to approve in March" is a question that outlives the person's employment.
Append-only, and why that is not a small thing
No role has an edit path or a delete path into the log. Not the AP specialist, not the controller, not the admin, not the owner of the company. There is no interface for it because there is no route for it.
This sounds like a technicality and it is the whole value of the thing. A log that a sufficiently senior person can tidy is not evidence of anything; it is a record of what the most senior available person wanted to be true. The moment an administrator can remove one line, every remaining line is worth less, including all the honest ones.
The practical consequence is that mistakes stay visible. If you code an invoice to the wrong building and fix it an hour later, both facts are in the trail for good. That is the correct outcome. A correction with its original attached is a stronger record than a clean one, and anybody who has sat through a review knows which of the two an auditor finds reassuring.
It also means the log cannot be used to hide a disagreement. A rejection keeps its comment. An approval that was later reversed keeps both events.
Using it at month end
The Audit Log screen carries two rows of filters, and the line between them is the answer to the only question that matters here: am I looking at the trail, or at a page of it?
The first row asks the server, across the whole trail. A record id, a from date and a to date, one person, and one action type. Each of those narrows every entry in the workspace, however far back it goes.
The second row narrows only the entries this browser has already loaded. That is the free-text search across records, fields and values, and the People / Automation switch. Neither can be sent to the server — the endpoint has no full-text parameter, and an automation row carries no actor to filter by — so they work on what is in hand, and the screen says so beside them.
The list loads 100 entries at a time, newest first, and Load older entries fetches the next hundred. A line above it states the window you asked for and whether anything sits behind it: either older entries exist and you can reach them, or every entry that matches is loaded. That sentence is there because an empty result and an empty trail are different answers, and on a compliance screen telling them apart is the job.
To follow one invoice, paste its record id into the first box. It is a server filter, so it reaches the whole trail rather than the page in front of you. The dates are whole days in your own time zone.
Three habits cover most of month end.
- Reconcile the exports. Filter to export events and compare what you see against what landed in your ledger. An
exportedentry is a bill that posted, so a mismatch is a bill that never got there — and theexport.failedandexport.retriedentries beside it say why it stopped and who sent it again. The Exports screen still holds the attempt history and the Retry button. - Review what automation decided. Filter to automation only. This is where you find a rule that has quietly been coding a vendor to the wrong account since you wrote it, which is a far more common failure than a rule that does nothing at all.
- Check the corrections. Filter to people only and look at
fields_updated. A vendor whose totals are corrected by hand every month is telling you either to write a rule or to expect that vendor's layout to keep costing you time.
Export trail writes a CSV with timestamp, actor, role, action, record, field, before and after as columns. Three things to know before you hand that file to an auditor.
The export is not what is on screen. It goes back to the server and walks the whole trail under the filters in the first row — the dates, the person, the action type, the record — however many pages deep that reaches. The rows on screen are only the first hundred of the same question. This is the opposite of the old behavior, and it means you no longer have to load the trail by hand before exporting it.
It stops at 5,000 entries, and it tells you. A workspace's trail has no upper bound, so the walk needs an end. Reach it and the file still downloads, with a warning that names the ceiling and says to narrow the dates and export again to reach the rest. A successful export gets the count and the date window instead. Neither message is silent about which one you got.
The two narrowings in the second row are applied afterwards, to what was fetched. So a value search or the People / Automation switch can hand you a much shorter file than 5,000 rows while the ceiling was still reached — the cap counts entries fetched, not entries written. When the warning appears beside a small file, that is what happened. Narrow the dates and go again.
The column headed role says whether a person, the pipeline or automation acted — Person, System or Automation — not what job title that person holds. The audit endpoint returns no role, and inventing one on a compliance trail would be worse than leaving it out.
Proving an export covered what you asked for
An auditor's file is worth what you can say about it, so check three things before you send it.
- Read the message you were given. The success message names the number of entries and repeats the window — "the whole trail, newest first", or the dates you set. The warning names the 5,000 ceiling. If you saw the warning, the file is a prefix and nothing else you check will change that.
- Compare the count with the file. The number in the message is the number of data rows in the CSV. A spreadsheet that opens with a different count is a different file.
- Check the ends against the question. Sort the CSV by timestamp. The oldest and newest rows should sit inside the dates you filtered on, and if you asked for the whole trail with no dates, the screen should have been saying every entry that matches is loaded before you exported.
One habit makes all three easy: set the dates first and export one question at a time. A month of one workspace's trail is a file somebody can read; a year of everything is a file that hits the ceiling and answers nothing.
Limits worth knowing
What is not logged
Document history is complete. Workspace configuration is almost complete, and the gap is worth naming rather than discovering.
- Approval tiers are not logged. Adding, editing or deleting a tier writes no audit row today. That is the one configuration change an auditor can ask about and we cannot answer from the trail.
- Property aliases are not logged either, which matters less: an alias changes how a building is recognized, not who signs for it or what it costs.
Everything else in the workspace writes a row. Membership changes — invitations sent, accepted and revoked, role changes and removals. Workspace settings, including split coding and the separation-of-duties switch, with the keys that changed and both values. A property's primary approver, backup approver, auto-approve threshold, default GL account and cost center, under their own property.approval_changed event. Properties, units, vendors, vendor aliases, legal entities and the ledger company an entity points at. Intake mailboxes when they are created.
The log records what happened inside inletAP. It does not record what happened afterwards in your ledger — if somebody edits a posted bill in QuickBooks Online or Xero, that edit is in your ledger's own history, not here.
Audit records are kept for as long as your workspace is active, because they are part of your accounting record. There is no per-workspace retention setting today, and we would rather say so than describe an absent feature as a policy decision. See security and data for the rest of that picture.
Where to go next
- Security and data — tenant separation, retention and what we do not have.
- Roles and permissions — who can do what, which is what the actor column reflects.
- Invoice statuses — the states the log records transitions between.
- Month-end export — the close this trail is usually read alongside.