Automated GL Coding for Accounts Payable
Every incoming invoice needs a general-ledger account, a cost center, and an approver before it can be paid. In most AP teams that coding is manual, repetitive, and the single biggest source of month-end correction work. Aito learns the coding directly from your historical invoices β no rules to write, no model to train and deploy β and returns calibrated probabilities with an explanation for every suggestion, so you can auto-post the confident ones and route only the uncertain ones to a human.
All queries below run against the live v2 sandbox
(invoices linked to glCodes and employees β the standard AP shape).
Suggest the GL account
The invoice's free-text description is the evidence; the linked GLCode is the
prediction target:
{
"from": "invoices",
"where": { "Description": { "$match": "cloud services" } },
"predict": "GLCode",
"select": ["$value", "$p"],
"limit": 3
}
{ "offset": 0, "total": 10, "hits": [
{ "$p": 0.833, "$value": "E002" },
{ "$p": 0.044, "$value": "R001" },
{ "$p": 0.034, "$value": "E001" } ] }
E002 is Cloud Services (AWS/GCP) β at 83% confidence, against a
10.8% base rate. total is 10: every account in
glCodes is a candidate and limit decides how many come back (see
Candidates, evidence, and $f). Set a threshold
such as $p > 0.9 β auto-post after measuring your own data with _evaluate
(below).
Route to the right approver
Same evidence, different target β and numeric context via $numeric, which
matches an adaptive neighbourhood of the amount instead of the exact cents:
{
"from": "invoices",
"where": {
"Description": { "$match": "office cleaning services" },
"TotalAmount": { "$numeric": 2000 }
},
"predict": "Acceptor",
"select": ["$value", "$p"],
"limit": 3
}
{ "offset": 0, "total": 10, "hits": [
{ "$p": 0.725, "$value": "Jane Smith" },
{ "$p": 0.223, "$value": "Bob Brown" },
{ "$p": 0.05, "$value": "Alice Johnson" } ] }
Show your work β $why
Auditors don't accept "the model said so". Add "$why" to the select and
every suggestion carries its factor tree β the base rate, the normalizers, and
the lift contributed by each piece of evidence:
{
"from": "invoices",
"where": { "Description": { "$match": "cloud services" } },
"predict": "GLCode",
"select": ["$value", "$p", "$why"],
"limit": 1
}
The response shows each piece of evidence and how much it moved the probability
β here the words cloud and services as one $group β see the full tree in
the Quickstart. Each proposition is reusable as a where
condition to drill into the supporting invoices.
Measure it before you trust it
_evaluate runs a train/test split on your own data and reports the accuracy
you'd actually get:
{
"test": { "$sample": 25 },
"evaluate": {
"from": "invoices",
"where": { "Description": { "$get": "Description" } },
"predict": "GLCode"
},
"select": ["accuracy", "baseAccuracy", "meanRank", "n"]
}
{
"kind": "evaluation",
"data": {
"accuracy": 1,
"baseAccuracy": 0.52,
"meanRank": 0,
"n": 25
}
}
On the demo dataset the description determines the account β 100% accuracy on 25 held-out invoices, against 52% for always answering the most common account. On real AP data you'd typically threshold: auto-post above a confidence bound, queue the rest. See the Evaluation guide.
Why Aito for this
- No training pipeline. The prediction is computed from the live data at query time; new invoices improve the next suggestion immediately.
- Multi-tenant. Wrap the query in a
nested
fromto compute base rates over one client entity's invoices. The chart of accounts is a linked table, so every account stays a candidate; to suggest only the accounts a client uses, see Scoping candidates per customer β the accounting-bureau shape. - Honest failures. Unsupported operations return a typed
4xx, never a silently empty suggestion list.
Related: Query Reference Β· Inference guide Β· Sandbox