Skip to main content
All articles Guide

Building a PFM Layer on Your Neobank Without a Full Data Team

Adaeze Mensah · 10 min read
Building a PFM layer on a neobank without a data team

A neobank we spoke with last year had a roadmap item that had been sitting in the backlog for eight months: "Add spending categories and insights." The two engineers on the backend team knew how to build it in principle. They had looked at open-source options, evaluated a couple of enrichment vendors, and done a rough in-house spike. The item kept getting deprioritized because the scoping kept expanding every time they dug in.

The spending categories feature required merchant name cleaning to be useful. Merchant name cleaning required a training dataset. The training dataset required labeling. Labeling required someone to define and maintain the taxonomy. The taxonomy needed to account for their specific user base, which skewed toward gig workers and had a different transaction mix than generic consumer banking populations. Eight months later, the feature was not shipped.

This is the transaction intelligence trap. It looks like a 2-week feature and turns into a 6-month infrastructure project. This post is a realistic breakdown of what a small team can actually ship in 30 days using an enrichment API, and where the seams are.

What You Can Ship in 30 Days

The 30-day timeline assumes two engineers with backend experience and access to your transaction data via your existing data pipeline. It does not assume any ML experience, any data science team, or any existing category infrastructure. Here is what is achievable:

Days 1-3: API integration and data model. Connect to the Openaggr enrichment endpoint. Set up enrichment on ingest so every new transaction gets enriched when it posts. Set up a batch backfill job for historical transactions. Update your transaction data model to store the enrichment response fields: category (primary, confidence), merchant (name, normalized, MCC), and recurrence (is_recurring, pattern_type, expected_next_date).

The data model decision made on day 1-3 determines how much friction you will encounter in days 4-30. Store enrichment fields as first-class columns on your transaction record, not as a JSON blob or a separate enrichment table you have to join against. The query patterns for PFM features (aggregate by category over date range, filter by recurring flag, compute projected cashflow) all benefit from indexed columns, not JSON extraction from a blob.

Days 4-10: Spending summary view. Build the category aggregation query: sum debit transactions by category_primary where confidence is above your threshold (0.7 is a reasonable default) for the last 30 days. Group by category. Return the top 5-8 categories with totals. This is the core of a spending breakdown view.

The frontend for this is a ranked list or a simple bar chart. Do not start with a pie chart. Pie charts require every category to sum to a meaningful total and users find them hard to read for more than 5 segments. Start with a ranked horizontal bar chart where each bar is a category and the bar width is the spend total. This is readable in one glance.

Days 11-18: Recurring bills view. Query transactions where is_recurring = true and confidence is above 0.7. Group by merchant name and pattern type. Display as a list of "committed spending" items with the expected amount (or amount range for variable bills) and the expected next date.

This view is higher-value than the category breakdown for most users because it answers the question they actually have: "What is already decided for this month?" Committed spending (rent, utilities, subscriptions, insurance) is not discretionary and users know this. Surfacing it separately from variable spending creates the mental separation that makes the variable category actionable.

Days 19-25: Period comparison. Compare the current 30-day window against the prior 30-day window by category. Compute the delta (absolute and percentage). Surface the categories where spending changed most. This is the most engagement-driving feature of the three because it shows change, and change is what users notice and respond to.

The query is straightforward: run the same category aggregation twice (current period and prior period), join on category, compute delta. The display should show the category name, current total, prior total, and the delta with a direction indicator. Color-code by direction if your design permits: warmer color for increases, cooler for decreases.

Days 26-30: Polish and edge cases. Every integration has edge cases that surface only when you test with real transaction data. Common ones: transactions with confidence below your threshold (decide whether to show as "Uncategorized" or exclude from summaries), merchants that appear in multiple categories (gas stations with convenience stores), and the first 30 days when a new user has limited history and recurring detection has not yet fired.

What Takes Longer Than 30 Days

Being direct about what this timeline does not cover:

Cashflow forecasting requires at least 60-90 days of enriched transaction history before the recurring detection has enough data to produce reliable forward projections. You can build the UI for forecasting in week 1, but it will not be useful until the data has seasoned. Plan to soft-launch this feature for users who have been connected for more than 90 days, and progressively enable it as users' history builds.

Custom category taxonomy takes longer than using ours. The standard Openaggr taxonomy works well for most consumer banking populations, but some neobanks serve specific user communities where the standard taxonomy does not reflect the actual spending distribution. Gig economy workers, for example, have a spending pattern with higher fuel and vehicle maintenance and lower dining spending than salaried consumers. If your users fall outside the mainstream distribution, the standard top-level categories will be accurate but the composition within each category may not reflect your users' priorities. Custom taxonomy configuration is a Scale-tier feature and requires a few days of setup work to map your preferred display labels and groupings.

User-facing category editing, the ability for users to correct a categorization, is a feature that takes more thought than the enrichment integration itself. You need to decide whether user edits apply just to that transaction or to future transactions from the same merchant, whether they feed back into a retraining pipeline, and how you handle conflicting signals (the enrichment API says dining, the user says business expense). We have a detailed writeup on this in the docs under "User Feedback Flows."

The In-House Alternative: A Realistic Estimate

We want to be fair about the in-house option because it is the right choice for some teams. If you have significant ML engineering capacity, a large proprietary dataset to train on, and a user base with genuinely unusual transaction patterns that standard enrichment would not cover well, building in-house produces a better long-term outcome than relying on a third-party API.

The honest estimate for in-house transaction categorization built to production quality for a neobank: 4-6 months for a team of two to three engineers with ML experience. This covers merchant name cleaning, a baseline classifier trained on labeled data (plan 2-4 weeks of labeling work alone), a recurring detection module, a serving layer, and ongoing maintenance. The model will need retraining every 2-4 months as merchant patterns shift.

We are not saying in-house is a bad path. We are saying the "quick internal spike" version that gets built in 2 weeks will not have the merchant coverage, taxonomy depth, or recurring detection quality of a system that has been purpose-built and iterated on. The question is whether building and maintaining that system is a core competency your team wants to develop, or whether it is infrastructure that frees your engineers for the features that actually differentiate your product.

What Good Integration Looks Like

The integrations that produce good user experiences share a few characteristics. They store enrichment fields as structured data, not raw strings. They use the confidence score to decide what to include in summaries rather than showing everything and hoping it looks right. They build the committed/variable spending split from recurring detection rather than treating all transactions as equal. And they give themselves a 90-day window before evaluating whether the PFM features are useful, because the features depend on data that accumulates over time.

The integrations that struggle are the ones that treat enrichment as a display layer on top of balance history. Enrichment data is a database primitive, not a presentation feature. If it is stored and queried as a first-class data model, the PFM layer builds quickly. If it is bolted onto an existing balance-centric model as an afterthought, the friction multiplies at every query.

The 30-day timeline above is a ceiling, not a floor. Teams who have done the data model work upfront and are building clean new endpoints ship faster. Teams who are retrofitting enrichment onto an existing transaction model take longer. The bottleneck is almost never the API integration itself. It is the data model you build around it.

Back to Blog
Ready to integrate? Get your free API key