Skip to content

Part 4 of 7 · Subscription audit bot series ~5 min read

How a subscription gets an owner

Everything up to here has been mechanical. This is the part with judgement in it, and it is also the part that produces the money. A charge with no owner is not a bug in the data; it is very often a real thing that nobody has been responsible for in three years, and finding it is the point of the exercise.

Key takeaways

  • Three ways to attribute: the owner tab, the cardholder, and asking.
  • The merchant string is resolved to a product name so the question is answerable.
  • An unowned subscription is a finding, and usually the most valuable one.
  • The annual figure is attached to everything, always. It is what changes decisions.
  • A resolved owner is written back to the tab, so the archaeology only happens once.

Three ways to find an owner

How a subscription is attributed to an ownerA vertical chain of four steps entered by a box labelled A subscription, carrying merchant, amount and interval. Step one asks whether it is in the owner tab, matched on merchant; a hit exits to Owned, with a name and a purpose. Step two asks whose card it is, using the card list mapping cards to people; a known card exits to Provisionally owned, with the cardholder asked to confirm. Step three asks what the merchant actually is, using a single Bedrock call grounded by a table of merchants already resolved. Step four is Unowned, a real finding carrying an annual figure. A note says the last box is not an error state and is what the first pass mostly produces.AWS ACCOUNTA subscriptionmerchant, amount, intervalIn the owner tab?matched on merchantOwner tabfilled in over timeOwnedname and purposeyesWhose card is it?from the card listCard listcard to personProvisionally ownedask them to confirmknown cardWhat is the merchant?one Bedrock callKnown merchantsseen before, resolvedUnowneda real finding,with an annual figureThe last box is not an error state. It is what the first pass mostly produces.
Fig 1. Attribution in three steps with a deliberate fourth outcome. Unowned is the expected result of a first pass and the reason the system is worth running.
  • Database
  • App integration
  • Machine learning
  • Management
  • People

Turning a merchant string into a product

“SP * PROJTOOL”, “FS *NOTIONLABS”, “PADDLE.NET* ACME” and “STRIPE *CO 4471” are all real shapes of statement line, and the last one is genuinely unresolvable — it tells you a payment processor and a reference and nothing else. Resolution goes in three steps: an exact match against merchants already resolved for this business, a match against a small built-in list of common processor prefixes and well-known services, and then one model call with the raw string.

The model’s job is narrow: given a statement descriptor, name the likely product and say how confident it is. It is grounded with the merchants this business has already resolved, so the second occurrence of anything is free and certain. Where it cannot name a product, it says so, and the question to a human quotes the raw descriptor — which is fine, because a person looking at “STRIPE *CO 4471” on their own card statement often recognises it instantly from context the system does not have.

Why unowned is the valuable outcome

In a first pass over two years of feed at a business of about thirty people, a typical result is forty to sixty distinct subscriptions, of which somewhere between a quarter and a half have no identifiable owner. That is not a data quality problem. Those are real recurring payments that no living person is responsible for.

The result of a typical first subscription audit passA horizontal row of five boxes. Found: fifty-two subscriptions. Owned already: eighteen were in the owner tab. Cardholder knew: twenty-one were recognised by whoever's card they were on. Nobody knew: thirteen had no identifiable owner. Stopped: nine were cancelled, worth four thousand one hundred pounds a year. A note says the fourth number is the finding and the fifth is why anybody builds this.A TYPICAL FIRST PASSFound52 subscriptionsOwned already18Cardholder knew21Nobody knew13Stopped9, £4,100/yrThe fourth number is the finding. The fifth is why anybody builds this.
Fig 2. What a first pass over two years of transactions typically produces. The thirteen nobody recognised are the reason the system exists.
  • Machine learning
  • Management
  • Analytics
  • People

The annual figure, everywhere

Every subscription carries an annual cost from the moment it is recognised, and every message states it. This is the smallest change in the whole design with the largest effect on outcomes. “£14.40 a month” reads as trivial and gets a shrug. “£172.80 a year” reads as a number and gets a decision. They are the same fact.

For a probable annual subscription seen only twice, the annual figure is simply the charge. For a per-seat subscription with a drifting amount, it is twelve times the most recent charge, stated as “about”, with the trend noted if it has risen more than ten per cent over the year — because a per-seat tool growing with headcount is a completely different conversation from one that is not.

Writing the answer back

  • Every confirmed owner and purpose is written back to the owner tab, so the same archaeology never happens twice.
  • Every resolved merchant string is written to the known-merchants table, so the second occurrence costs no model call and carries no uncertainty.
  • A “nobody knows” answer is also written down, with the date. A subscription that has been unowned for two consecutive years and is still being paid is its own kind of finding.
  • The tab is the record, not the database. If this system is switched off tomorrow, the useful output — a list of what you pay for and why — survives in a spreadsheet.

Next: the renewal question itself, and why asking once a year is the whole design.

All posts