Journals / Case study

How Brex put a name on every card swipe

In December 2021 three Brex data scientists described Auto Merchant Cat, the system that turns cryptic card descriptors into a business name, website and category. The order is the lesson. Rules first, then a maps lookup, then a crowd, then a small model with strict thresholds, and staff for whatever is left. Brex reports an error rate well below 5%.

05 NOV 202611 min readClassification · Data enrichment · Human in the loop · Fintech Based on: Brex, 2021
Diagram. At the top, a raw card descriptor, TST* LITTLE SKIL, becomes a clean record: Little Skillet, San Francisco, a website and one of 48 business categories. Below, a day's flow of about 2,000 new merchants: 10 to 20 percent are handled by fixed rules; of the rest, Google Places identifies about half and Mechanical Turk workers the other half; small classifiers categorise over half of the volume; 10 to 20 percent end with the support team; and a small random sample of finished merchants is checked by support too.
Diagram: MORARI. Source: Brex

Open a company card statement and half the lines are riddles. The post opens with two of them: an Amazon order that reads AMZN Mktp CA, and a meal at Little Skillet in San Francisco that reads TST* LITTLE SKIL. For one person that is a nuisance. For a finance team closing the books, thousands of riddles a day are a real cost. On 21 December 2021 Bryant Chen, Daisy Qian and Swetha Revanur of Brex described how the corporate card start-up solves them, with a system its support team named after a cat.

The problem: the card network does not say who you paid

Each card payment arrives with a short merchant descriptor and a four-digit merchant category code, the MCC. Neither is enough. The descriptor is cut short and carries the card processor's prefix. The post calls the MCC "often unreliable". Brex wanted to give customers clear "doing business as" (DBA) names, and websites, "as well as an accurate categorization that helps businesses to track and understand their expenses."

At first people did it by hand: "our amazing and diligent support team would actually manually Google every single new merchant that showed up in Brex transactions". That stopped working "once we started seeing thousands of transactions daily".

How they built it

The system has two jobs. Identification finds the real business. Categorization then maps it to "one of 48 Brex categories that are more amenable to business accounting." A merchant moves on only when the step before it passed.

Cheap and certain steps first. "About 10–20% are processed by hardcoded rules." Everything else goes to Google Places, which the post describes as "essentially an API for a Google Maps search."

Clean the descriptor, then search. The system strips the processor tags, "(e.g. TST, SQ, WPY*, etc.)", adds the city the network supplied, and runs the search. It then throws out every result "whose name is not similar enough to the merchant descriptor or whose city differs from the network-provided city." The most relevant place left is the match. Its place types, such as restaurant or store, become an input for the next step.

A crowd when the lookup fails. Merchants that Places cannot find go to Amazon Mechanical Turk, a paid crowd-work marketplace, which the post says is "more expensive" and is "only used if the former fails". The quality rules are strict. Workers pass Brex's own tests first, and over time only the best keep a custom qualification. Each task goes to at least two workers, with a bonus when answers match. "If the first two responses do not agree with each other, an additional assignment will be sent." Two out of three votes win; anything else goes to staff.

A small model for the category. Two classifiers do the categorization. Both read the identified name and the MCC. The one for Places matches also reads the place types. The team tried word counts and a pre-trained sentence encoder for the name, and random forests against logistic regression. The winner was "the multi-class logistic regression with L2 penalty, with InferSent encoding the identified merchant names." InferSent is a sentence model Facebook published in 2017.

Diagram of the pipeline. A new merchant first meets hard-coded rules. If no rule fits, the descriptor is cleaned of processor tags and searched in Google Places with the city; results are kept only if the name is similar and the city matches. If a place is found, classifier 1 reads the name, MCC and place types. If not, Mechanical Turk workers identify the merchant, two per task with a third on disagreement, and classifier 2 reads the name and MCC. Each classifier's answer is kept only above a probability threshold set per category; below it, the crowd categorizes. Whatever fails a check goes to the support team. A random sample of finished merchants also goes to support for quality checks. Airflow runs it every twelve hours and retrains the models monthly.
Every step has a gate; anything that fails it goes one step closer to a person. Diagram: MORARI. Source: Brex

Accept only what the model is sure of. This is the part that makes the rest work. The team sets probability thresholds "both on overall and category level and only take predictions with probability above the threshold." For each category the threshold is set so that precision clears a target. Anything below goes to the crowd, and failing that, to staff.

Keep checking. "Lastly, a small random sample of merchants that are both identified and classified by Auto Merchant Cat are still sent to Support for quality assurance." Airflow runs the whole flow "every twelve hours", and the models "are automatically retrained on a monthly basis with latest data". The labels for training and testing came from the merchants Support had already sorted by hand.

What it delivered

All figures are Brex-reported. The system "processes ~2K net new merchants every day." After the rules, "Google Places is able to successfully identify about half of the merchants, while the other half is sent to Mechanical Turk." The classifiers "are able to categorize over 50% of the volume". Still, "we have 10–20% of the merchants that fail at either identification or categorization step" and go to Support. The headline: "The overall error rate of the Auto Merchant Cat system has been maintained well below 5%".

The one comparison is with an outside vendor in June 2020. On a 5,000-merchant set, "the vendor was only able to cover less than 10% compared to our 80% coverage rate at that time."

The gaps matter. The post gives no thresholds, no sample sizes, no costs and no baseline, such as how well the MCC alone does. It does not define coverage or error rate. Its classifiers reach "above 75% for classifier 1 and 70% for classifier 2" in accuracy, yet the system error is under 5%. Our reading is that the thresholds, the crowd and Support close that gap, but the post does not say so. The vendor test was run on Brex's own set, against one unnamed vendor.

One limit is ours to point out. Every step is built for US cards: US processor tags, Google Places in US cities, US crowd workers. The shape travels; the parts may not.

What has changed since

Brex's help pages describe a different first step today. "We’ve partnered with MasterCard to provide a direct connection to the card network, so our merchant identification infrastructure provides close to 100% accuracy." That is an undated, Brex-reported claim. The same page adds: "Though we use a custom machine learning model to improve the data, our systems may not always assign the correct merchant category." The 48 categories survive. Brex's expenses page still names "one of 48 different business categorizations reflective of the vendor’s industry." Whether Places and the crowd are still in the loop is not public.

Brex changed owners. On 22 January 2026 Capital One said it would buy Brex "in a combination of stock and cash transaction valued at $5.15 billion." The deal closed on 7 April 2026, and "Franceschi will continue as CEO of Brex."

The recipe became a product. A Visa UK report dated 3 November 2022 describes a service where "Snowdrop takes the raw transaction data," "cleans it up, identifies the merchant, and" enriches it, using the "Google Maps Platform Places API." That is Brex's first step, sold to banks. Card networks now also push banks to show it: according to vendor Meniga, Mastercard's rule AN 4569 "became fully effective on 14 October 2023", and Visa set a deadline of 23 January 2027 for issuers in most of Europe. We could not read either network's own text. API vendors such as Plaid and Ntropy sell merchant enrichment as a service.

Large language models arrived, and they have not replaced the small model. A September 2025 paper reports that general LLMs "do not significantly outperform small proprietary models in the specific context of financial transaction understanding." The sentence encoder Brex chose is frozen: Facebook's InferSent repository is archived, and its last update was in August 2021.

Why it matters for your business

Indonesia's merchant data is messier, and there is more of it. QRIS, Bank Indonesia's national QR standard, went national on 1 January 2020 and was built "dengan menggunakan standar internasional EMV Co." In its 21 October 2026 release BI counted 70.6 million users and 49.4 million merchants, with transactions up 75.80% year on year. From 1 October 2026 the zero merchant fee covers transactions up to Rp100,000 in every merchant category, and Indonesian credit cards can pay through QRIS, per BI's August release. More company spending will show up as small QR payments to small shops.

There is a helpful part. Every QRIS merchant sits in a national register: BI's PADG 21/18/PADG/2019 sets up a National Merchant Repository to "menatausahakan data pedagang (merchant)." The EMV QR format behind QRIS carries a merchant name, city and MCC, as EMVCo's public slides show. Whether an expense or accounting app gets those fields after the payment depends on the bank or wallet. Bank transfers often carry only a free-text note.

Local tools still lean on rules. Mekari Jurnal's bank reconciliation works through "penarikan mutasi otomatis, pencocokan transaksi, dan penjurnalan otomatis berdasarkan bank rules", in line with SNAP, BI's open API standard for payments. Rules written by each customer are a good start. They do not learn across customers.

The lesson is not InferSent. It is the order of work: the cheapest certain answer first, a model only where it is sure, and a person for the rest.

How we would build it today

Diagram of merchant naming for an Indonesian expense or accounting app in three bands. Inputs: card lines with a descriptor and MCC, QRIS payments with a merchant name, city and MCC where the provider passes them on, and bank transfers with only a free-text note. Resolve: normalise the text by stripping channel prefixes and codes, check a hand-kept alias table and a memory of merchants already resolved, then a maps lookup as one signal. Categorize: a small model with a probability threshold per category; below it, a second opinion from a language model with names and account numbers masked, then a review queue. Learn: user corrections become merchant rules, a random sample is checked each week, and categories map to the chart of accounts. Underneath: what to measure.
Rules, then memory, then a model, then people. Diagram: MORARI. Source: Brex
  1. See what data you really get. Card lines carry a descriptor and an MCC. QRIS payments may carry name, city and MCC, if the provider passes them on. Transfers carry a note. The mix decides the design, so check it before promising anything.
  2. Normalise and remember. Strip channel prefixes, terminal codes and city abbreviations. Keep a hand-written alias table and a memory of every merchant already resolved, keyed by the cleaned string and city. Like Brex's rules, this should settle a good share for free.
  3. A small model for the category. Logistic regression on character n-grams of the name, plus the MCC where present. Character pieces suit short, cut-off Indonesian strings better than whole words.
  4. Thresholds per category. Set them on a held-out sample to hit a target precision, and send everything below to review. Report coverage and precision separately.
  5. An LLM only for the leftovers. Use it as a second opinion on rejected items, or to grow the category list, with a fixed list of allowed answers. Mask names and account numbers first, and log every call.
  6. Corrections become rules. When a user fixes a category, store it as a rule for that merchant and company, and feed it into the monthly retrain. Keep Brex's random QA sample.
  7. Publish a baseline. Compare against MCC-only and rules-only on a frozen labelled sample from your own data, the number Brex did not give.
  8. Map to the books. Categories should map to the customer's chart of accounts, so the output is ready for closing.

For an app with a few hundred companies, steps 1, 2, 6 and 8 are enough. Add the model when the review queue costs more than an afternoon a week.