M

Payment Application

Designing for the messy reality of money

Role
Product Designer
Year
2024
Tools
Figma, Claude
Experience the prototype ↗

Overview

Payment matching sounds simple until money meets the real world.

Puzzle automatically matches payments to invoices/bills when it can confidently determine the relationship. But real-world payments aren’t always clean or one-to-one: a single payment might cover several invoices/bills, only partially cover what’s owed, or be larger than the amount being applied. Processing fees can also get deducted before a payment lands, so the amount that actually arrives doesn’t line up with the invoice/bill at all. Sometimes the customer/vendor is known even when the specific invoice/bill isn’t.

Automation can’t always resolve that on its own, and even when it does match automatically, it can occasionally get it wrong. Either way, an accountant needs a clear way to step in and fix it. The challenge was to make that manual work feel less like an exception and more like a natural part of the product.

The problem

The accounting model looks straightforward on paper: payment maps to invoice/bill. The real-world relationships are much messier.

The product couldn’t treat matching as simply finding one corresponding record, not with edge cases like these in play. It needed to support the actual relationship between money and the records it affects.

The design principle

The system often has useful context: a bank transaction may already be associated with a customer/vendor, starting from an invoice/bill gives that document’s context, starting from a specific transaction tells us what the accountant is trying to resolve. That context should make the workflow faster, but it shouldn’t become a constraint.

Start narrow when the system has context. Let the accountant broaden the search when they need to.

That meant surfacing likely matches and relevant records without ever preventing the accountant from searching, filtering, selecting different records, or changing the allocation.

One workspace, multiple ways in

Rather than designing a separate workflow for every scenario, I designed a single, reusable matching workspace that stays consistent no matter where it’s entered from:

The payment matching workspace with a bank transaction selected on the left and invoices listed on the right, not yet matched
Bank transactions on one side, invoices/bills on the other, one workspace regardless of where you start

One of the biggest opportunities was cutting down how much searching an accountant had to do. If the originating transaction already has a customer/vendor associated with it, that context can narrow the records shown on the other side: instead of every possible invoice/bill, the accountant sees the ones most likely to matter.

The invoice list filtered down to a single customer's invoice, matching the selected bank transaction
The invoice list narrowed to the transaction's customer/vendor, before the accountant broadens it

But filtering shouldn’t become a dead end. The accountant can always search, adjust filters, or broaden the results when the initial context isn’t enough.

Context → likely results → accountant judgment. Not context → forced decision.

Transaction Has context → fewer results No context → full list Accountant always decides
Context narrows the results, but never forces the outcome

That distinction mattered for a financial workflow where the system can’t always know the full story behind a payment.

Matching isn’t always the final answer

Finding the right invoice/bill only gets an accountant halfway there. The harder question is how the payment should actually be applied, and the workspace treats that as part of the same flow instead of a separate step:

Underneath all three is the same running math: payment amount, applied amount, and remaining balance stay visibly connected throughout, so it’s always clear whether a payment is fully resolved or still needs attention.

Payment amount Applied amount + Remaining amount
The three numbers that stay connected on every payment, updating live as an allocation changes
The same payment split across two invoices, $500 applied to one and $350 to the other, with the remaining balance at $0.00
One payment, split across two invoices: applied amount and remaining balance update live

A workspace that adapts

The core interaction is a two-sided workspace: payment/transaction on one side, invoice/bill on the other, which makes the relationship between the two explicit. But accountants don’t always approach the problem from the same direction, so the workspace adapts: horizontal or vertical layout, flipping which side is which, independent search and filtering, multi-select, and different starting contexts.

The goal wasn’t a visually clever interface. It was a workspace that could accommodate different starting points and different ways of resolving the same underlying accounting relationship.

The same workspace switched to a vertical layout, bank transactions stacked above invoices instead of side by side
Stacked vertically instead of side by side
The workspace with its two halves swapped, invoices on the left and bank transactions on the right
Halves swapped: invoices on the left, transactions on the right

Key design decisions

The bigger challenge

Financial software tends to look clean in diagrams. In reality, money doesn’t always arrive with the information the system needs, so the product has to accommodate ambiguity, exceptions, partial information, and human judgment.

For payment matching, that meant treating the manual workflow as a first-class experience rather than a fallback for automation. The result is a reusable matching workspace that combines automation, context, flexibility, and accountant control: the system does the easy work, and when it can’t, the accountant still has a clear path forward.

What I took away

The most important insight from this work was that financial workflows shouldn’t be designed around the ideal transaction. The exceptions are where trust is won or lost. When the numbers don’t line up, when a payment doesn’t have enough context, or when one payment needs to affect several records, the interface needs to make the situation understandable, not hide the complexity.

Good financial software doesn’t eliminate complexity by hiding it. It makes complexity manageable.