Source provenance
Each source file is tied to its content hash, length, source identity, and the actor who uploaded it — so you can trace exactly what came in and who sent it.
FintechBear relates records that represent the same financial movement across banks, processors, wallets, and internal systems — on one canonical model — so a difference has an explanation instead of a manual investigation.
An internal system books the gross amount. The processor takes its fee, batches hundreds of payments, and sends the bank a single transfer. A refund lands in the next day's report. A chargeback arrives weeks later. The transaction date and the value date don't line up.
Match on amount alone and you'll pair unrelated transactions that happen to look the same — and miss the ones that actually belong together. The engine's scope is built on stating, explicitly, what each source says, under what conditions records match, and which review process runs when a difference appears.
Illustrative example — not a specific customer or integration
When the bank credits $1,460 instead of $1,470, that $10 difference has to show which records and which calculation it came from. If there's no approved tolerance or other explaining rule, a case is opened. Quietly editing the fee afterward to make the table balance would just bury a difference whose source was never explained — so the engine won't do that.
A fast import from the wrong table is still wrong. Ingestion is treated with the same care as the matching engine.
Each source file is tied to its content hash, length, source identity, and the actor who uploaded it — so you can trace exactly what came in and who sent it.
One file has payment_ref, another transaction_reference. They only
match if the mapping says they mean the same thing. A date field might be the
transaction time in one source and the value date in another — naming them alike would ask
the matcher the wrong question from the start.
Required fields, data types, number and date formats, time zones, and duplicate source identities are validated. Missing, null, empty string, and zero are kept distinct.
The relationship between the original value and the converted value is kept, so how an amount or date arrived and how it was processed stays inspectable.
The engine contract defines one-to-one, bounded one-to-many, bounded many-to-one, and a staged three-way reconciliation. You can relate a single bank transfer to several transactions, or compare internal-to-processor first and the result to the bank next.
Rules cover composite keys from the reference and other fields, amount and time tolerances, the gross–fee–net relationship, and explicit FX policy. Trying every combination of thousands of records to find a matching total would make resource use uncontrollable as volume grows — so candidate count, group size, and run limits are explicit, and record-consumption rules stop one record from being used in several accepted matches.
| Model | Status |
|---|---|
| One-to-one | Validated |
| One-to-many | On the roadmap |
| Many-to-one | On the roadmap |
| Three-way (staged) | On the roadmap |
Each model beyond one-to-one is validated before we present it as available.
Amounts are carried as an integer coefficient, a decimal scale, and a currency.
Coefficient 12345, scale 2, currency USD means
$123.45. The contract caps the coefficient at 38 digits; the reviewed implementation
parses and adds with big integers — never float or double.
If an FX conversion happens, the rate, direction, rounding, and residual policy must be stated. The system never picks a fee rate or FX policy on its own, and how excess precision is handled is explicit — silent rounding produces differences that are hard to explain later.
Given the same canonical data, rule version, contract, and currency metadata, you get the same financial result — regardless of the file's row order or which worker ran it.
A run is tied to the dataset, rule, and contract versions it used. You can inspect which inputs produced a past result and keep the link needed to replay it.
The financial result has a stable identity of its own. Operational details like how long a run took are kept separate, so they never change what the result means.
Cancellation, timeout, and engine error are handled explicitly. A completed reconciliation is kept distinct from a failed attempt, so a half-finished job never reports records as unmatched.
Alongside matched and unmatched, records can be inconsistent, duplicate, invalid, ambiguous, or conflicted. The review flow shows the related source records, the rule applied, the reason for the difference, and prior actions together.
A difference can be assigned to an owner, annotated with evidence, and proposed as a manual match or an accepted difference. For critical items, the person who prepares and the person who approves are different. What the engine produced, what the user proposed, and who approved it — with what justification — are tracked separately. Three months later, “why was this closed?” has an answer.
A shared .NET Control Plane owns tenants, authorization, policies, workflows, persistence, and API coordination. Two engines — a .NET Reference Engine and a C++ Native Engine — implement the same language-independent contract and are expected to produce the same financial result from the same input.
.NET Control Plane; a React / TypeScript / Vite web console that runs operations through the backend and renders backend-computed values — it does not do its own matching or rounding in the browser.
Engines run in separate process or container boundaries. Internal communication is gRPC / Protobuf; the external integration boundary is REST / OpenAPI. The C++ engine is not exposed as a public API.
PostgreSQL carries transactional state, workflows, idempotency records, and audit indexes. S3-compatible object storage holds source files, datasets, reports, and evidence. Redis, if used, is limited to cache, coordination, or rate limiting.
A C++ performance advantage can only be stated with a comparative benchmark; none is published here.
Core ingestion formats are CSV and JSONL. An Integration API lets a customer push records from their own application and consume results — distinct from the engine reaching into a bank to fetch movements.
Covers sources, imports, rules, reconciliation runs, results, cases, exports, and audit data. Long jobs are tracked asynchronously; idempotency for repeated requests, version control for concurrent updates, and a webhook model with signatures and redelivery (the same event may arrive again).
Bank statements, PSP settlement reports, wallet movements, and accounting records can map onto this model. But claiming a ready connector for a specific bank, SAP, Logo, Visa Direct, or Ria requires that connection's own test and acceptance evidence. A model that can work with these sources is not the same as every connection being built.
We separate what a controlled demo has shown from what the design targets. The version's actual supported features are determined by test and acceptance records.
Scope is confirmed per engagement. We tell you plainly what's available today and what's on the roadmap.
Bring the systems and reports where your money's story breaks. We assess scope and fit against your real data — and we tell you plainly what's proven and what isn't.