An AI-assisted financial reconciliation platform that combines deterministic financial controls with bounded AI investigation.
- Overview
- Problem
- Solution
- Core Design Principle
- Architecture
- End-to-End Reconciliation Flow
- Razorpay Integration
- Razorpay Ingestion
- Money Handling
- Reconciliation Engine
- Decision Policy
- AI Investigation
- Bounded Agent
- Investigation Tools
- Evidence
- Auditability
- Idempotency
- Transaction State Management
- Database
- Project Structure
- Tech Stack
- Getting Started
- Environment Configuration
- Database Setup
- Running the Backend
- Running the Frontend
- API Endpoints
- Frontend
- Synthetic Demo Dataset
- Testing
- Test Coverage
- Current Validation
- Security and Financial Control Model
- Production Roadmap
- Demo Story
- Why This Architecture?
- Project Philosophy
- License
Razorpay AI Finance Controller is a finance operations platform designed to reconcile payment and settlement data from Razorpay.
The system is built around a simple principle:
AI investigates. Deterministic policy decides.
Instead of allowing an AI model to directly make financial decisions, the platform uses deterministic reconciliation rules and a Decision Policy as the financial source of truth. AI is introduced only when a transaction requires further investigation.
The platform provides:
- Razorpay API ingestion
- Payment and settlement reconciliation
- Deterministic candidate retrieval
- Financial validation rules
- Decision Policy
- Evidence generation
- Exception management
- Audit trails
- Bounded AI investigation
- OpenAI and Gemini model support
- PostgreSQL persistence
- REST APIs
- Finance operations dashboard
Financial reconciliation is more than comparing two transaction amounts.
A finance team may need to determine:
- Whether an order has a corresponding payment
- Whether the payment amount is correct
- Whether currency matches
- Whether transaction dates are consistent
- Whether a transaction is duplicated
- Whether a payment was refunded
- Whether a payment was included in a settlement
- Whether a settlement amount is correct
- Why a transaction failed reconciliation
- What evidence supports a reconciliation decision
Traditional rule-based reconciliation can identify many straightforward cases, but ambiguous cases often require investigation.
The challenge is therefore to combine:
- Reliable deterministic financial controls
- Traceable evidence
- AI-assisted investigation
- Human-reviewable outcomes
without allowing AI to directly control financial state.
The Finance Controller uses a layered reconciliation architecture.
Razorpay
│
▼
Razorpay API
│
▼
Ingestion & Validation
│
▼
PostgreSQL
│
▼
Candidate Retrieval
│
▼
Deterministic Reconciliation
│
▼
Decision Policy
/ | \
/ | \
MATCHED NO_MATCH REVIEW
│
▼
Bounded AI Investigator
│
▼
Investigation Evidence
│
▼
Decision Policy
│
▼
Final Reconciliation
│
┌─────────┴─────────┐
▼ ▼
Evidence Audit
The AI investigator is deliberately separated from the financial decision layer.
AI can:
- Investigate ambiguous transactions
- Inspect approved financial evidence
- Call controlled investigation tools
- Identify relationships between Razorpay entities
- Explain potential causes
- Produce structured investigation observations
AI cannot:
- Directly mark transactions as matched
- Directly mark transactions as reconciled
- Issue refunds
- Modify settlements
- Mutate financial records
- Bypass the Decision Policy
- Override deterministic financial controls
This keeps financial authority deterministic while still using AI where reasoning is valuable.
The application is implemented as a modular monolith.
graph TD
A["Frontend<br/>Dashboard · Reconciliation · Investigation · Audit"]
B["API Layer<br/>Routes · Controllers · Validation · Services"]
C["Reconciliation Layer<br/>Candidate Retrieval · Deterministic Rules · Razorpay Reconciliation · Decision Policy · Evidence · State Management"]
D["Investigation<br/>Bounded Agent · Tool Registry · Tool Validation · Timeout Protection · Policy Guard · OpenAI / Gemini"]
E["PostgreSQL<br/>Transactions · Razorpay Records · Candidates · Evidence · Results · Exceptions · Audit Events"]
A --> B --> C
C --> D
C --> E
1. Select reconciliation date range
↓
2. Fetch Razorpay data
↓
3. Validate API responses
↓
4. Normalize Razorpay records
↓
5. Persist records in PostgreSQL
↓
6. Create reconciliation batch
↓
7. Retrieve candidates
↓
8. Apply deterministic rules
↓
9. Generate financial evidence
↓
10. Apply Decision Policy
↓
11. MATCHED / NO_MATCH
│
└── REVIEW_REQUIRED
↓
AI Investigation
↓
Investigation Evidence
↓
Existing Decision Policy
↓
Final Result
↓
Audit + Exceptions
Razorpay is treated as the source financial system.
The application fetches Razorpay data and maintains a normalized local representation in PostgreSQL.
The application does not write reconciliation decisions back to Razorpay.
The data model supports:
- Orders
- Payments
- Refunds
- Settlements
- Settlement reconciliation records
Order
│
└── Payment
│
└── Refund
Payment
│
└── Settlement
│
└── Settlement Reconciliation
This relationship graph is used by Razorpay-specific reconciliation and investigation tools.
Razorpay ingestion is implemented under:
src/ingestion/razorpay/
Important components include:
razorpay.client.ts
razorpay.ingestion.ts
razorpay.mapper.ts
razorpay.pagination.ts
razorpay.schemas.ts
razorpay.types.ts
API Client — Handles communication with Razorpay APIs.
Pagination — Handles collection endpoints that return multiple pages.
Schemas — Validates incoming Razorpay API objects.
Mapper — Converts Razorpay objects into normalized application data.
Ingestion Service — Coordinates fetching, validation, normalization and persistence.
Razorpay amounts are represented in paise.
The ingestion layer converts amounts into decimal monetary values.
Example:
99900 paise
↓
₹999.00
Financial values are stored using PostgreSQL numeric precision rather than JavaScript floating-point arithmetic for persisted monetary amounts.
The reconciliation engine is located under:
src/reconciliation/
It is divided into several responsibilities.
Candidate retrieval identifies records that may correspond to a source transaction.
The system supports:
- Exact retrieval
- Fuzzy retrieval for the generic/legacy reconciliation path
- Razorpay-native candidate retrieval
Candidate retrieval itself is deterministic. AI is not used to discover arbitrary financial matches.
The reconciliation engine evaluates financial attributes using deterministic rules.
Examples include:
- Amount
- Currency
- Date
- Reference
- Duplicate detection
These rules produce structured evidence that can be consumed by the Decision Policy.
The Decision Policy is the authoritative financial decision layer.
Location:
src/reconciliation/policy/decision-policy.ts
Representative outcomes include:
| Condition | Decision |
|---|---|
| Exact reference match | MATCHED |
| Exact amount + currency + date | MATCHED |
| Amount mismatch | NO_MATCH |
| Currency mismatch | NO_MATCH |
| Duplicate candidate | REVIEW_REQUIRED |
| Date within tolerance | REVIEW_REQUIRED |
| Reference mismatch | REVIEW_REQUIRED |
| Insufficient evidence | REVIEW_REQUIRED |
The policy also produces reason codes and confidence information used by the application.
AI is used when deterministic reconciliation identifies an ambiguous case.
The investigation system is located under:
src/investigation/
REVIEW_REQUIRED
│
▼
Bounded Agent
│
├── Tool Registry
├── Tool Validation
├── Timeout Protection
└── Policy Guard
│
▼
Investigation Model
│
├── OpenAI
└── Gemini
│
▼
Structured Investigation Observation
│
▼
Existing Decision Policy
│
▼
Final Result
The agent is intentionally constrained.
The bounded-agent architecture ensures that an investigation cannot become an unrestricted autonomous financial workflow.
Controls include:
- Tool allowlisting
- Input validation
- Output validation
- Timeout protection
- Policy guards
- Structured model output
Razorpay-specific investigation tools are located under:
src/investigation/tools/razorpay/
They can investigate:
- Payment/refund relationships
- Settlement relationships
- Settlement reconciliation
- Financial evidence
- Razorpay transaction relationships
The tools expose controlled information to the investigator rather than granting unrestricted database or financial-system access.
Evidence is a first-class concept in the system.
A reconciliation result can contain field-level evidence such as:
Field: amount
Source: 999.00
Candidate: 999.00
Explanation: Amount matches exactly.
Other evidence may include:
- Currency comparison
- Date comparison
- Reference comparison
- Candidate score
- Payment relationship
- Refund relationship
- Settlement relationship
- Investigation observations
This makes the final decision explainable.
The system maintains an audit trail for reconciliation operations.
The database includes concepts for:
- Reconciliation results
- Candidates
- Evidence
- Exceptions
- Audit events
The result can therefore be traced through:
Source Transaction → Candidate → Rule Evaluation → Evidence
→ AI Investigation → Decision Policy → Final Result → Audit Event
Reconciliation runs are designed to be idempotent.
The reconciliation result includes an idempotency key and uniqueness constraints to prevent duplicate reconciliation results from being created for the same transaction.
This is important for financial workflows where jobs may be retried.
Transactions move through controlled states.
Representative states include:
PENDING → CANDIDATES_FOUND → INVESTIGATING → MATCHED / NO_MATCH / REVIEW_REQUIRED
Failures are represented explicitly through a FAILED state. This prevents uncontrolled state transitions.
PostgreSQL is used as the primary database.
The application uses:
- PostgreSQL
- Drizzle ORM
- Relational constraints
- Foreign keys
- Unique indexes
- Numeric monetary fields
- Database transactions
The system requires strong relational consistency across:
Batches, Source Files, Transactions, Orders, Payments, Refunds,
Settlements, Settlement Reconciliation, Candidates, Evidence,
Results, Exceptions, Audit Events
PostgreSQL is therefore a better fit than a lightweight local-only database for the architecture being demonstrated.
ai-finance-controller/
│
├── src/
│ │
│ ├── api/
│ │ ├── contracts/
│ │ ├── controllers/
│ │ ├── routes/
│ │ ├── services/
│ │ └── validation.ts
│ │
│ ├── db/
│ │ ├── repositories/
│ │ ├── schema/
│ │ ├── migrations/
│ │ ├── client.ts
│ │ └── seed.ts
│ │
│ ├── domain/
│ │
│ ├── ingestion/
│ │ ├── csv/
│ │ └── razorpay/
│ │
│ ├── investigation/
│ │ ├── agent/
│ │ ├── providers/
│ │ │ ├── openai/
│ │ │ └── gemini/
│ │ └── tools/
│ │ └── razorpay/
│ │
│ └── reconciliation/
│ ├── metrics/
│ ├── policy/
│ ├── razorpay/
│ ├── retrieval/
│ ├── rules/
│ └── state/
│
├── frontend/
│ ├── app/
│ ├── components/
│ ├── hooks/
│ └── types/
│
├── test/
│ ├── unit/
│ └── integration/
│
├── drizzle.config.ts
├── eslint.config.js
├── package.json
├── tsconfig.json
└── README.md
Backend
- Node.js
- TypeScript
- Express
- Zod
- Drizzle ORM
- PostgreSQL
Frontend
- Next.js
- React
- TypeScript
- Tailwind CSS
AI
- OpenAI
- Gemini
Testing
- Vitest
- Unit testing
- Integration testing
- API end-to-end testing
Install:
- Node.js
- npm
- PostgreSQL
- Razorpay Test Mode credentials
From the project root:
npm installInstall frontend dependencies:
cd frontend
npm install
cd ..Create your local environment configuration.
Example:
DATABASE_URL=your_postgresql_connection_string
RAZORPAY_KEY_ID=your_razorpay_test_key_id
RAZORPAY_KEY_SECRET=your_razorpay_test_key_secret
OPENAI_API_KEY=your_openai_api_key
GEMINI_API_KEY=your_gemini_api_keyUse Razorpay Test Mode credentials for development and the buildathon demo.
Never commit secrets to Git. Recommended files that should remain untracked:
.env
.env.local
Use .env.example for documenting required variables without exposing credentials.
Generate migrations:
npm run db:generateApply migrations:
npm run db:migrateSeed demonstration data:
npm run db:seedStart the development server:
npm run devThe backend runs on http://localhost:5000.
Start the Next.js application:
cd frontend
npm run devThe frontend runs on http://localhost:3000.
POST /api/reconciliation/syncExample body:
{
"from": "2025-09-01",
"to": "2025-09-30"
}Synchronizes Razorpay records for the selected date range.
POST /api/reconciliation/:batchId/runRuns reconciliation for the selected batch.
GET /api/reconciliation/:id/statusReturns the current reconciliation status.
GET /api/reconciliation/:id/resultsReturns reconciliation results.
GET /api/reconciliation/:id/exceptionsReturns reconciliation exceptions requiring attention.
GET /api/reconciliation/:id/auditReturns the audit trail for the reconciliation batch.
The frontend provides a finance operations interface.
Dashboard
- Reconciliation overview
- Batch status
- Exception visibility
- Recent audit activity
- Razorpay synchronization
Reconciliation
- Batch status
- Transaction results
- Match status
- Exceptions
- Evidence
Investigation
- Review-required transactions
- Investigation status
- Investigation observations
- Supporting evidence
Audit
- Operational history and traceability
Razorpay Test Payment
- A Razorpay Test Mode payment flow for demonstrating real Razorpay test transactions
The project includes a synthetic seed dataset for testing reconciliation behavior.
The seed creates 300 transactions across multiple scenarios:
| Range | Scenario |
|---|---|
| 1–210 | Exact Match |
| 211–240 | Amount Mismatch |
| 241–255 | Missing Payment |
| 256–270 | Refund |
| 271–285 | Settlement Mismatch |
| 286–300 | Duplicate |
This dataset is intended for regression testing, reconciliation demonstrations, edge-case testing, and stress testing.
It should not be represented as real merchant production data. Razorpay Test Mode data and synthetic seeded data are separate sources.
Run the complete test suite:
npm run testRun TypeScript validation:
npm run typecheckRun ESLint:
npm run lintBuild the application:
npm run buildThe test suite includes coverage for:
- Transaction persistence
- Database behavior
- Exact candidate retrieval
- Razorpay candidate retrieval
- Reconciliation service
- Reconciliation orchestration
- Reconciliation API
- Exception persistence
- Audit persistence
- Decision Policy
- Decision Policy boundaries
- Deterministic engine
- Amount rule
- Currency rule
- Date rule
- Reference rule
- Duplicate rule
- Transaction state machine
- Razorpay schemas
- Razorpay mapper
- Razorpay pagination
- Razorpay client
- Razorpay reconciliation
- Payment/refund reconciliation
- Payment/settlement reconciliation
- Settlement reconciliation
- Investigation tools
- Investigation policy
- Bounded agent
- Tool validation
- Investigation timeout
- OpenAI provider
- Gemini provider
- CSV ingestion
- Fuzzy search
- Financial evidence
At the current development checkpoint:
Test Files: 55 passed
Tests: 247 passed
TypeScript: PASS
The repository is being finalized for the buildathon presentation.
The project deliberately separates:
Reasoning ≠ Financial Authority
AI provides reasoning and investigation assistance. Deterministic code provides financial authority.
This separation reduces the risk of:
- Hallucinated financial decisions
- Unauthorized mutations
- Untraceable decisions
- Uncontrolled agent behavior
- AI bypassing business rules
The buildathon implementation can be extended toward production with:
Authentication and Authorization
- User authentication
- Role-based access control
- Finance approval workflows
Razorpay Integration
- Production credentials
- Webhook ingestion
- Signature verification
- Incremental synchronization
- Retry and recovery workflows
Infrastructure
- Background reconciliation workers
- Queue-based processing
- Distributed locking
- Observability
- Metrics
- Alerting
Financial Controls
- Immutable audit storage
- Reconciliation period locking
- Approval workflows
- Stronger accounting controls
AI Governance
- Model/version tracking
- Prompt versioning
- Investigation replay
- Model cost controls
- Human escalation
- Additional output validation
The recommended buildathon demo:
- Start with Razorpay — Show that Razorpay is the source system.
- Synchronize — Select a date range and synchronize Razorpay data.
- Reconcile — Run reconciliation and show
MATCHED/NO_MATCH/REVIEW_REQUIRED. - Open an Exception — Select a review-required case and show the underlying evidence.
- Investigate with AI — Demonstrate that the investigator can inspect approved Razorpay financial relationships.
- Explain the Control Boundary — Show the flow: AI Investigation → Evidence → Decision Policy → Final Financial Result.
- Show Auditability — Finish by showing the evidence and audit trail behind the result.
Key message:
The AI does not decide where money goes. It investigates why a case is ambiguous, while deterministic policy remains the financial authority.
A financial system should not depend on probabilistic reasoning at the point where financial authority is exercised.
The architecture therefore combines:
- Deterministic rules
- Deterministic decision policy
- Controlled AI investigation
- Evidence
- Auditability
This provides the benefits of AI without turning the AI model into an uncontrolled financial decision-maker.
Use deterministic systems for financial authority and AI for investigation.
The goal is not to replace finance controls with an AI model. The goal is to build a finance controller that can:
- Reconcile reliably
- Explain its decisions
- Investigate ambiguous cases
- Preserve evidence
- Maintain auditability
- Scale toward production workflows
while keeping the final financial authority deterministic.
This project was created as a buildathon prototype. It is provided for demonstration and evaluation purposes.