Skip to Content
DevelopersThe capture parser

The capture parser

POST /v1/capture/text turns a short message like gave mum 5k yesterday into a draft entry for the person to confirm. It uses rules only: no AI model, no cost, and nothing leaves the server. A model is only ever meant to be a fallback for messages the rules cannot read.

What it understands

PartExamples
Amounts500, 5k, 2.5k, 1.5m, 1,500, ₦500, N500, #500, NGN 3000, 500 naira, 53.75
Number wordstwo thousand five hundred, five hundred and fifty, one million
The price, not the quantity2 bags rice 45k is 45,000 (not 2). bus 300 for 2 people is 300
Dates, in your timezoneyesterday, last night, 2 days ago, monday, 12/10 (day first)
Money in or outsalary 150k, mum sent me 10k, received 20k from Ada are income. gave mum 5k, paid rent are spending
CategoriesThe built-in Nigerian categories, with everyday and Pidgin words (okada, keke, suya, esusu, nepa, aso ebi…), plus your own category names
AccountsMatches the accounts you have by name (opay, gtb, cash), or suggests adding one you mentioned

Phone and account numbers are ignored. The result is always whole kobo.

It explains itself, and does not guess silently

Every draft carries the word that decided the category (matched), a confidence and level, and plain-words reasons to double-check. It will:

  • refuse to invent an amount: no number means canSave: false;
  • flag two different amounts in one message instead of picking quietly;
  • say so when it cannot tell the category, and offer “Other” for the person to change.

Pasted bank alerts

Paste a credit or debit alert into the same box and it is read by a separate, stricter path:

  • The label decides the direction. Credit: (or CR, “credited”) is money in; Debit: (or DR, “debited”) is money out. Nothing else in the message can change that.
  • The amount is the one beside the label. The balance (Bal:) is never taken, and it is removed before the pasted text is stored.
  • The alert’s own time is used, in the person’s time zone. A time in the future, or one that is not a real date, is ignored and the draft says so.
  • The person behind a transfer is pulled out of the description (routing codes such as FT and Moni are dropped), and the account number is never kept.
  • It only counts as an alert when it has a second marker (an account line, a balance, a description or a time). A short phrase like “credit 5000” still goes down the normal path.
  • The category is honest about being a guess: money in from a person might be a gift, sales or pay, so the draft asks for a check.

What is proven so far: one real layout (Credit / Acct No / Desc / Bal / Time). Debit handling and other banks’ layouts are covered by synthetic examples only, and the plan’s target (300 real alerts, at least 95% right on amount and direction) is not met until real samples are collected. Each new layout is added with a real sample and a test.

How accurate is it? An honest answer

Test setFully correctAmountDirectionCategory
217 phrases the team wrote, used while building100%100%100%100%
59 fresh phrases, never tuned against86.4%94.9%98.3%89.8%

The first row is flattering by construction: the parser was improved until it passed those phrases. The second row is the realistic estimate.

Neither set is real user data. The product target is 90% on real Nigerian phrases, and that is not yet proven. To prove or improve it we need real messages. The app records, on each confirm, whether the person changed the draft, so real accuracy and real corrections will accumulate from the first pilot users.

Known weak spots: quantities written as x2, sums like keke 100 + okada 300, and words that mean different things in different places (for example dash means “gift” to most people, and “borrowed” money is not income).

How the two repositories stay in step

The web app keeps a light copy of the parser for instant previews, even offline. The API’s answer is authoritative. Both are tested against the same phrase file, phrases.v1.json, which must stay byte-for-byte identical in both repositories (its checksum is checked). A phrase file is never edited after it is published: a new set is a new version (phrases.v2.json).

Learning from corrections

When the person confirms a draft, POST /capture/{id}/confirm compares what they saved with what we drafted. If they changed the amount, direction, category, account or date, that is kept as a labelled example. This is also the “parse accuracy” metric: the share of drafts saved without edits.

The text people type is personal data. It is stored with the capture, and encryption of those fields is planned (see Security).

Last updated on