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": 4, "hits": [
  { "$p": 0.853, "$value": "E002" },
  { "$p": 0.082, "$value": "R001" },
  { "$p": 0.032, "$value": "E001" } ] }

E002 is Cloud Services (AWS/GCP) โ€” at 85% confidence, against a 49% base rate. The probability is calibrated, so a threshold like $p > 0.9 โ†’ auto-post behaves the way the number says it should.

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": 3, "hits": [
  { "$p": 0.506, "$value": "Alice Johnson" },
  { "$p": 0.248, "$value": "Bob Brown" },
  { "$p": 0.246, "$value": "Jane Smith" } ] }

Show your work โ€” $why

Auditors don't accept "the model said so". Add "$why" to the select and every suggestion carries its factor tree โ€” base rate, calibration, 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 the exact evidence ({"Description": {"$match": "cloud services"}}) and how much it moved the probability โ€” reusable verbatim 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"]
}
{ "accuracy": 1.0, "baseAccuracy": 0.487, "meanRank": 1.0, "n": 25 }

On the demo dataset the description determines the account โ€” 100% against a 49% base rate. 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 by construction. Wrap the query in a nested from to scope base rates and candidates to one client entity โ€” 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