An automated transaction reconciliation system for fintech, built in Python with a FastAPI service.
Every fintech company processes thousands of daily transactions across two systems:
- An internal ledger (our record of what happened)
- A payment gateway report (the provider's record of the same transactions)
These two never match perfectly. Failed webhooks, timing differences, duplicates, and rounding errors mean 30% of transactions typically disagree. Manual reconciliation takes days. Errors mean real money lost.
This engine classifies every transaction automatically:
MATCHED- both systems agreeMISSING_IN_GATEWAY- we recorded it, gateway did notMISSING_IN_LEDGER- gateway recorded it, we did notAMOUNT_MISMATCH- both agree it exists, disagree on amountDUPLICATE_IN_GATEWAY- gateway recorded it more than once
It produces a value-at-risk report - the total naira amount that needs investigation - so finance teams know exactly where to focus.
The matching engine uses a hash map for O(1) lookups, reducing complexity from O(n squared) to O(n).
The same business logic is exposed two ways:
- CLI mode - run the scripts directly
- API mode - call the FastAPI endpoints
- Python 3.10+
- Pandas (data manipulation)
- Faker (synthetic test data)
- FastAPI + Uvicorn (HTTP API)
- Pytest (testing)
data_gen.py- generates synthetic ledger and gateway CSVsingestion.py- loads and cleans CSVsmatching.py- the core matching algorithm (hash map based)reporting.py- summary, value-at-risk, and exportsapi/main.py- FastAPI application with three endpointstest_matching.py- five unit tests for the matching enginetest_api.py- five integration tests for the API
| Method | Path | Purpose |
|---|---|---|
| GET | /health |
Liveness check |
| POST | /reconcile |
Upload two CSVs, get summary JSON |
| GET | /reconcile/{run_id} |
Fetch a previous result |
Interactive docs (once running): http://localhost:8000/docs
Install dependencies:
pip install -r requirements.txtGenerate test data:
python data_gen.pyRun the API:
uvicorn api.main:app --reloadRun the tests:
pytest test_matching.py test_api.py -vMATCHED : 702
MISSING_IN_GATEWAY : 161
MISSING_IN_LEDGER : 81
AMOUNT_MISMATCH : 93
DUPLICATE_IN_GATEWAY : 44
value_at_risk_naira : 485,046.93
- Hash maps reduce matching complexity from O(n squared) to O(n)
- Financial data must be stored as integers (kobo), never floats
- Idempotency is non-negotiable in fintech
- Edge cases (empty inputs, duplicates) are where production bugs hide
- Separating transport layer (FastAPI) from business logic makes both easier to test
- Type annotations in FastAPI generate validation and docs automatically
Anuoluwapo Daniel Ojo Full Stack Software Engineer | Lagos, Nigeria