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 from to 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

← All v2 use cases