Collecting on a standing instruction? The eight steps and the 2026 e-mandate limits: Recurring Payments: How to Build It →
Moving money across the border? The eight steps, the PA-CB rules, and where the FX cost hides: Cross-Border Payments: How to Build It →
Selling cover inside your own checkout? The eight steps, who is allowed to sell, and what changes on 1 January 2027: Embedded Insurance: How to Build It →
Building on the UPI rails themselves? PSP banks, NPCI certification, the deemed state, and what the September 2026 MDR notification changes: UPI Switch Infrastructure: How to Build It →
Turning paper cheques into data? The eight steps, the CTS image specification, and what the October 2025 clearing change means: Cheque Reading: How to Build It →
Deciding whether to let a business accept payments through you? The eight steps, the 2025 PA Directions, and the marketplace rule that makes you answerable for sellers you never onboarded: Merchant Onboarding: How to Build It →
Wondering what happens when an AI agent initiates the payment? What is known about NPCI’s Unified Agent Protocol, the liability question nobody has answered, and what to do now: Agentic Payments: How to Prepare →
Every tool for this module, how to use each one, what it costs, the best combinations and three recommended builds: Payments Build Sheet →
What reconciliation actually is
You think you moved money. The bank thinks something happened. Your ledger says one thing, the settlement file says another. Reconciliation is the process of proving those views agree ’ and finding the ones that do not.
Every payment touches at least three records:
- Your ledger — what your system believes happened
- The processor or scheme — what the payment rail reports
- The bank account — what money actually arrived or left
When all three agree, nothing needs doing. When they disagree, someone’s money is in the wrong place and it is your problem to find out whose.
This is the least glamorous module in the section and the one that most often decides whether a fintech survives its first audit. A company can have excellent fraud detection and a beautiful app, and still fail because it cannot prove where its customers’ money is.
Why it is harder than matching two lists
If every payment had a unique reference that appeared identically in all three systems, this would be a database join. It does not.
| What goes wrong | Why |
|---|---|
| Timing differences | A transaction happens on Tuesday and settles on Thursday. Both records are correct; they disagree on Wednesday. |
| Netting | The processor settles 400 transactions as one bank credit, minus fees. One deposit, four hundred records. |
| Fees deducted at source | You expected ₹10,000; ₹9,823 arrived. The difference is a fee you have to derive. |
| Partial payments | One invoice paid across three transfers. Or three invoices paid with one lump sum. |
| Missing references | The customer paid with no reference at all, which is extremely common. |
| Reversals and refunds | Which original does this refund belong to? Often not stated. |
| Currency and rounding | Conversion applied at a rate you did not choose, rounded in a direction you did not pick. |
The last one on that list ’ a payment with no reference ’ is where most reconciliation software quietly fails.
What AI can and cannot do here
| Task | How well AI does it |
|---|---|
| Match transactions with clean references | Trivially. Deterministic rules handle this; no AI needed. |
| Match with tolerance for timing and rounding | Very well. Still rules, just better rules. |
| Match a payment with no reference to an open invoice | Well. Amount, timing, payer history, partial-text similarity. This is where AI earns its place. |
| Many-to-many matching | Reasonably. Combinatorially hard and the main source of residual exceptions. |
| Explain why two records did not match | Well. Genuinely useful for the exception queue. |
| Decide that a difference is acceptable | It should not. That is a write-off decision with accounting consequences. |
| Sign off a reconciliation | No. Someone is accountable for that signature. |
Mature platforms report auto-match rates between 90% and 99%, and published benchmarks show reconciling 1,000 records dropping from around 7.2 hours manually to about 1.6. Those gains are real. They are also gains on matching, not on accountability — do not automate matching and remove human sign-off in the same project.
The structural fact: money moves on a different clock
The single idea that makes reconciliation make sense: the transaction clock and the settlement clock are different clocks.
A card payment is authorised instantly, captured later, settled in batch, and the money lands in your account a day or more after the customer saw "payment successful". A UPI payment appears instant to the user and still settles between banks in defined cycles.
Everything in this module follows from that gap. Exceptions are usually not errors — they are records observed at different points on two different clocks. The skill is telling apart a timing difference that will resolve itself from a genuine break that will not.
In India this is codified. The RBI harmonised turn-around-time framework sets the expected auto-reversal window for failed transactions, and the NPCI dispute rails are built around settlement cycles rather than wall-clock time. Designing your reconciliation on wall-clock assumptions guarantees false exceptions.
The matching cascade
Run the most certain rules first. Every stage you clear cheaply is a stage the expensive ones never have to consider.
RECORDS FROM BOTH SIDES
|
1. EXACT REFERENCE unique id present and identical on both sides
| -> should clear 60-80% instantly. If it does not,
| fix your reference propagation before anything else.
|
2. EXACT AMOUNT + DATE same amount, same value date, one candidate only
|
3. TOLERANCE MATCH amount within fee/rounding tolerance,
| date within settlement window
| -> tolerances are POLICY, versioned and approved
|
4. DERIVED-FEE MATCH expected_gross - known_fee_schedule = observed_net
|
5. ONE-TO-MANY one settlement credit vs N transactions
| -> subset-sum within tolerance
|
6. MANY-TO-MANY N payments against M invoices
| -> the genuinely hard case
|
7. PROBABILISTIC no reference: score on amount, timing, payer
| history, narration similarity
| -> SUGGESTS a match, a human confirms
|
8. EXCEPTION categorise, age, assign an owner
|
NEVER let stages 5-7 auto-post without review until you have measured
their precision on your own data for at least one full close cycle.from dataclasses import dataclass
from datetime import date, timedelta
from decimal import Decimal
@dataclass(frozen=True)
class Tolerance:
"""Tolerances are POLICY. Versioned, approved, logged with every match.
Widening a tolerance to clear a backlog is a control change, not a
configuration tweak."""
version: str
amount_abs: Decimal # absolute paise/cents tolerance
amount_pct: Decimal # proportional tolerance for fee variance
date_days: int # settlement window
def amount_within(a: Decimal, b: Decimal, tol: Tolerance) -> bool:
diff = abs(a - b)
return diff <= tol.amount_abs or (b and diff / abs(b) <= tol.amount_pct)
def match_pass(ledger, bank, tol: Tolerance):
"""Returns (matches, unmatched_ledger, unmatched_bank).
Each match records WHICH RULE fired - that is what makes the
reconciliation auditable rather than merely complete."""
matches, used_bank = [], set()
# Stage 1: exact reference. Highest certainty, do it first.
bank_by_ref = {}
for b in bank:
if b.get("reference"):
bank_by_ref.setdefault(b["reference"].strip().upper(), []).append(b)
for l in ledger:
ref = (l.get("reference") or "").strip().upper()
cands = [b for b in bank_by_ref.get(ref, []) if id(b) not in used_bank]
if ref and len(cands) == 1:
b = cands[0]
used_bank.add(id(b))
matches.append({"ledger": l, "bank": b, "rule": "exact_reference",
"confidence": 1.0, "tolerance_version": tol.version})
# Stage 2-3: amount + date within tolerance, ONE candidate only.
# Ambiguity is an exception, never a guess.
rem_l = [l for l in ledger if not any(m["ledger"] is l for m in matches)]
for l in rem_l:
cands = [b for b in bank
if id(b) not in used_bank
and amount_within(Decimal(str(l["amount"])),
Decimal(str(b["amount"])), tol)
and abs((l["value_date"] - b["value_date"]).days) <= tol.date_days]
if len(cands) == 1:
b = cands[0]
used_bank.add(id(b))
exact = Decimal(str(l["amount"])) == Decimal(str(b["amount"]))
matches.append({"ledger": l, "bank": b,
"rule": "amount_date_exact" if exact else "amount_date_tolerance",
"difference": Decimal(str(b["amount"])) - Decimal(str(l["amount"])),
"confidence": 0.95 if exact else 0.85,
"tolerance_version": tol.version})
matched_l = {id(m["ledger"]) for m in matches}
return (matches,
[l for l in ledger if id(l) not in matched_l],
[b for b in bank if id(b) not in used_bank])Record which rule fired
The field that makes a reconciliation auditable is not whether it matched ’ it is why. "Matched by exact reference" and "matched by amount within a 2% tolerance" carry very different confidence, and an auditor will ask you to separate them.
If your exact-reference stage is not clearing the majority of volume, stop building matching logic and go fix reference propagation instead. A reference that survives from your ledger through the processor to the bank statement is worth more than any amount of fuzzy matching downstream.
One-to-many and the ambiguity rule
A processor settles four hundred transactions as a single bank credit, net of fees. Matching that credit back to its components is a subset-sum problem, and subset-sum is exponential.
from itertools import combinations
from decimal import Decimal
def subset_match(settlement_amount, candidates, tol, max_items=6, max_combos=50000):
"""A single settlement credit against N underlying transactions.
Brute force is 2^N - bound it hard and fall through to exception.
Returns the UNIQUE subset if exactly one fits. Multiple fits means
ambiguity, and ambiguity goes to a human. Picking one arbitrarily
is how reconciliations become confidently wrong."""
target = Decimal(str(settlement_amount))
hits, tried = [], 0
# Prune first: nothing larger than the target can be in the subset
pool = sorted((c for c in candidates
if Decimal(str(c["amount"])) <= target + tol.amount_abs),
key=lambda c: -Decimal(str(c["amount"])))
for size in range(1, min(max_items, len(pool)) + 1):
for combo in combinations(pool, size):
tried += 1
if tried > max_combos:
return {"status": "search_exhausted", "tried": tried}
total = sum(Decimal(str(c["amount"])) for c in combo)
if abs(total - target) <= tol.amount_abs:
hits.append(combo)
if len(hits) > 1:
return {"status": "ambiguous", "candidate_count": len(hits)}
if len(hits) == 1:
return {"status": "matched", "items": hits[0], "rule": "one_to_many_subset"}
return {"status": "no_match"}Two design decisions in that code matter more than the algorithm. Bound the search, because an unbounded combinatorial match will hang your close. And treat ambiguity as an exception — if more than one subset fits, a human decides. Picking the first fit is how a reconciliation becomes confidently and invisibly wrong.
In practice, most settlement files include a batch or settlement identifier that makes this unnecessary. Use it if it exists. Subset matching is the fallback for processors whose files do not.
The exception taxonomy
Unmatched items are not one thing. Categorising them is what turns a queue into a workflow.
| Category | Meaning | Typical action | Ages to |
|---|---|---|---|
| Timing | In one system, not yet the other | Wait for the next cycle | Auto-resolves, or becomes a real break at T+n |
| Fee variance | Net differs from expected by an undocumented amount | Reconcile against the fee schedule; if persistent, raise with the processor | Revenue leakage |
| Missing in bank | Your ledger says paid; no money arrived | Investigate urgently | Real loss or a failed payment not handled |
| Missing in ledger | Money arrived you did not expect | Identify the payer; do not spend it | Unapplied cash, and a liability |
| Amount mismatch | Both exist, amounts differ beyond tolerance | Determine which is correct | Adjustment or dispute |
| Duplicate | Same payment appears twice | Check idempotency; refund if genuinely double-charged | Customer complaint |
| Ambiguous | Multiple plausible matches | Human decision | Stays until someone decides |
The one people underestimate
"Missing in ledger" — money that arrived and you cannot identify — is the most dangerous category. It looks like a windfall and it is a liability. Somebody paid you for something, and until you know who and why, that money is not yours.
Unapplied cash sitting in a suspense account for months is a standard audit finding and a standard route to customer complaints, because the customer who paid believes they have paid and your system believes they have not.
India: the dispute and settlement rails
Indian payment disputes run on specific infrastructure with specific timing, and the rules changed materially.
Turn-around time
The RBI harmonised turn-around-time framework (circular RBI/2019-20/67, 20 September 2019, as subsequently amended) sets expected auto-reversal windows for failed transactions across payment systems. For failed UPI transactions the auto-reversal expectation is T+1 working day, with compensation payable for delay beyond it.
Design consequence: a debit with no corresponding credit is not immediately a break. It is an item inside a defined reversal window. Alerting on it at T+0 generates noise; failing to alert at T+2 is a compliance problem.
URCS, UDIR and the TCC/RET mechanism
UPI disputes are handled through the UPI Dispute Resolution System, with the Unified Dispute and Issue Resolution interface for customer-initiated queries. Two codes do most of the work:
- TCC — Transaction Credit Confirmation. The beneficiary bank confirms the credit was applied.
- RET — Return. The beneficiary bank returns the funds because the credit could not be applied.
The deemed-acceptance trap that was fixed
Worth understanding because it shows how settlement timing becomes a financial risk.
Previously, a remitting bank could file a chargeback in URCS from T+0 — often before the beneficiary bank had finished reconciling. The beneficiary bank would raise a return, find the chargeback already filed, and the chargeback would close with deemed acceptance. Banks were penalised by the RBI for the resulting mess.
NPCI revised the framework so that from 15 February 2025, URCS automatically accepts or rejects a chargeback based on the TCC or RET raised by the beneficiary bank in the subsequent settlement cycle — giving the beneficiary bank a cycle to reconcile first. The change applies to bulk upload and UDIR paths rather than front-end dispute options.
The lesson generalises beyond UPI: if your dispute process can conclude before your reconciliation process has run, you will lose money to deemed outcomes. Sequence disputes behind settlement, not in parallel with it.
Customer-facing timelines
RBI data indicates UPI complaints exceeded 1.2 million per month in early 2026, with around 60% being "amount debited but not credited". Customers who are unsatisfied can escalate to the RBI Ombudsman through the CMS portal after the bank window elapses. The Reserve Bank - Integrated Ombudsman Scheme 2026 replaced the 2021 scheme from 1 July 2026, with award limits of up to ₹30 lakh for consequential loss and up to ₹3 lakh for time, expense and harassment.
Build your internal service levels inside those windows, not up against them.
The registry
Reconciliation platforms
Verified May 2026Payment rails and data sources — India
Verified May 2026Build-your-own components
Verified May 2026Registry reflects what was publicly visible in May 2026. NPCI dispute rules in particular have changed more than once; verify the current circular set with your sponsor bank before designing around any timing assumption.
A prompt for designing your reconciliation
You are a payments operations lead who has built reconciliation
for high-volume fintechs.
My situation:
- Rails I use: [e.g. UPI via Razorpay, cards via a PG, NACH mandates]
- Daily transaction volume: [number]
- Settlement pattern: [e.g. T+1 net settlement, gross, multiple]
- Systems holding records: [ledger, PG dashboard, bank statement, ERP]
- Current process: [describe, or "spreadsheets"]
- Team size on reconciliation: [number]
Give me:
1. A matching cascade for MY rails - the specific stages in order,
and what share of volume each should clear.
2. The tolerance bands I should start with for amount and date,
with the reasoning for each rail.
3. My exception categories, and the action and owner for each.
4. Which exceptions are timing artefacts that will self-resolve, and
at what point each becomes a genuine break I must investigate.
5. The India-specific timing rules I must respect - TAT windows,
settlement cycles, dispute sequencing.
6. What to log so that a year from now I can prove where a specific
customer's money went.
7. The three ways this reconciliation will silently go wrong.
Be concrete about numbers and say where they must be calibrated on
my own settlement data.Design the ledger so breaks cannot happen
Most reconciliation problems are ledger design problems that became visible at settlement. Three decisions prevent the majority of them.
-- Money is never a column you UPDATE. It is a sequence of entries
-- you APPEND. Balances are derived, never stored as mutable truth.
CREATE TABLE ledger_entry (
entry_id BIGSERIAL PRIMARY KEY,
transaction_id UUID NOT NULL, -- groups the legs together
account_id TEXT NOT NULL,
direction CHAR(2) NOT NULL CHECK (direction IN ('DR','CR')),
amount_minor BIGINT NOT NULL CHECK (amount_minor > 0),
currency CHAR(3) NOT NULL,
effective_at TIMESTAMPTZ NOT NULL, -- when it counts (value date)
recorded_at TIMESTAMPTZ NOT NULL DEFAULT now(), -- when we learned
idempotency_key TEXT NOT NULL,
external_ref TEXT, -- the reference that must survive
metadata JSONB NOT NULL DEFAULT '{}',
UNIQUE (idempotency_key)
);
-- Every transaction must balance. Enforce it, do not assume it.
CREATE OR REPLACE FUNCTION assert_balanced(txn UUID) RETURNS VOID AS $$
DECLARE d BIGINT; c BIGINT;
BEGIN
SELECT COALESCE(SUM(amount_minor) FILTER (WHERE direction='DR'),0),
COALESCE(SUM(amount_minor) FILTER (WHERE direction='CR'),0)
INTO d, c FROM ledger_entry WHERE transaction_id = txn;
IF d <> c THEN
RAISE EXCEPTION 'Unbalanced transaction %: DR=% CR=%', txn, d, c;
END IF;
END; $$ LANGUAGE plpgsql;
-- THREE THINGS THAT PREVENT MOST RECONCILIATION PAIN:
--
-- 1. amount_minor as BIGINT in the smallest unit (paise, cents).
-- Never floating point. Never. 0.1 + 0.2 != 0.3 and you will
-- discover this during a month-end close.
--
-- 2. effective_at separate from recorded_at. The two clocks from the
-- Beginner lane, made explicit in the schema. This is what lets you
-- answer "what did we believe on Tuesday" versus "what was true".
--
-- 3. idempotency_key UNIQUE. A retried webhook, a double-clicked
-- button, a replayed settlement file - all become no-ops instead
-- of duplicate money.Idempotency is the one to get right first
Payment systems retry. Webhooks arrive twice. Settlement files get reprocessed after a partial failure. Networks time out after the money moved but before you heard about it.
Without an idempotency key on the write path, every one of those becomes a duplicate ledger entry, and duplicates are the hardest reconciliation break to unwind because both entries look legitimate.
The rule worth adopting: a payment is identified by a key the caller supplies, not by one you generate. If the caller retries with the same key you return the original result rather than creating a second transaction. This single pattern removes an entire category of exception.
Measuring it honestly
Auto-match rate is the number everyone quotes and it is easy to make look good.
1. AUTO-MATCH RATE, by rail and by rule
matched automatically / total items
Mature platforms report 90-99%. Track it MONTHLY by rail - a drop
in one rail is a signal, a blended figure hides it.
Break it down by RULE: a high rate achieved mostly through wide
tolerances is not the same as one achieved by exact reference.
2. EXCEPTION AGING
The single most important number. No unmatched item older than
30 days without a documented owner and a plan.
Report the distribution, not the average: 0-3d / 4-7d / 8-30d / 30d+
3. VALUE AT RISK IN EXCEPTIONS
Sum of unmatched amounts, by category and age.
500 exceptions worth Rs 200 each is an annoyance.
3 exceptions worth Rs 40 lakh each is an incident.
4. REVIEWER HOURS: PREPARING vs APPROVING
Before automation the ratio is heavily weighted to preparing.
It should invert within two close cycles. If it has not, the
automation moved work rather than removing it.
5. DAYS TO RECONCILE
Target a 50% reduction within two close cycles.
WHAT NOT TO REPORT AS SUCCESS
- auto-match rate alone, with no rule breakdown
- exceptions CLOSED, with no distinction between resolved
and written off
- a blended rate across rails with very different profilesThe way auto-match rate gets gamed
Widen the tolerances and the auto-match rate rises immediately. The exceptions do not disappear ’ they get absorbed into matches that are slightly wrong, and the error accumulates somewhere invisible.
This is why tolerance changes should be treated as control changes: versioned, approved, dated, with the auto-match rate reported before and after so the improvement is attributable to the right cause.
If auto-match rate improves sharply and exception value does not fall proportionately, someone widened a tolerance. Ask.
Disputes and chargebacks as a system
A dispute is a reconciliation problem with a deadline and a counterparty.
The lifecycle
- Trigger — customer complaint, failed credit, or a scheme-initiated claim
- Evidence assembly — the transaction record, the authorisation, delivery proof, prior history
- Representment or acceptance — contest with evidence, or accept the loss
- Resolution — funds move, or do not
- Post-mortem — feed the outcome back into fraud and product
Where AI genuinely helps
Evidence assembly is the slow part and it is mechanical. Pulling the transaction, the device fingerprint, the delivery confirmation, the customer contact history and prior dispute record into a single pack is exactly the kind of retrieval task that should be automated.
Deciding whether to contest is not. That is a commercial judgement about the cost of representment against the probability of winning against the customer relationship.
The economics people get wrong
Contesting a dispute has a cost ’ staff time, sometimes a scheme fee, sometimes a penalty if you lose. For small amounts, accepting is frequently the rational answer and teams contest anyway out of principle.
Model it: expected value of contesting is (probability of winning × amount) minus cost of representment. Set a threshold below which you accept automatically, and review it quarterly against actual win rates rather than assumed ones.
Watch the dispute ratio as a separate metric from the dispute count. Schemes and regulators care about the ratio, and a rising ratio with flat volume signals a product problem — not a fraud problem — far earlier than revenue figures will.
Where reconciliation silently fails
| Failure | How it looks | How to catch it |
|---|---|---|
| Silent file truncation | Settlement file arrives short; everything in it reconciles perfectly | Reconcile the control totals in the file header, not just the rows |
| Timezone drift | Items land in the wrong day; month-end is persistently wrong by a few items | Store everything in UTC with an explicit value date; never infer |
| Float arithmetic | Tiny unexplained differences that accumulate | Integer minor units everywhere. This is not negotiable. |
| Tolerance creep | Auto-match rate quietly improving over quarters | Version tolerances; alert on changes |
| Suspense account growth | Unapplied cash accumulating unnoticed | Age and value the suspense balance in the same report as exceptions |
| Reprocessed files | A file re-ingested after a failure creates duplicates | Idempotency on file ingestion as well as on transactions |
| Fee schedule drift | Processor changes fees; your derived-fee matching degrades | Track fee variance as a monitored metric, not an exception category |
Control totals deserve particular attention. A settlement file that is missing its last 200 rows will reconcile with a perfect match rate on the rows present. Nothing looks wrong. The only defence is reconciling against the count and total the file itself declares.
The audit trail, and where this module ends
{
"run_id": "rec_2026-05-23_upi_01",
"rail": "upi",
"period": {"from": "2026-05-22T00:00:00Z", "to": "2026-05-22T23:59:59Z"},
"executed_at": "2026-05-23T04:15:00Z",
"sources": [
{"name": "internal_ledger", "records": 41288, "control_total_minor": 918442100},
{"name": "psp_settlement_file", "file": "stl_20260522.csv",
"records": 41290, "declared_records": 41290,
"control_total_minor": 916118400, "checksum": "sha256:9a1c..."},
{"name": "bank_statement", "records": 37, "control_total_minor": 916118400}
],
"control_total_check": "passed",
"configuration": {
"cascade_version": "recon-cascade-v9",
"tolerance_version": "tol-v4",
"tolerances": {"amount_abs_minor": 100, "amount_pct": 0.002, "date_days": 2},
"tolerance_approved_by": "finance_controller_2026-04-02"
},
"results": {
"matched": 41205,
"by_rule": {"exact_reference": 39880, "amount_date_exact": 1102,
"amount_date_tolerance": 198, "one_to_many_subset": 25},
"auto_match_rate": 0.998,
"exceptions": 85,
"exceptions_by_category": {"timing": 61, "fee_variance": 14,
"missing_in_ledger": 7, "ambiguous": 3},
"exception_value_minor": 2323700
},
"aging": {"0_3d": 61, "4_7d": 17, "8_30d": 6, "over_30d": 1,
"over_30d_owner": "ops_lead_04", "over_30d_plan_ref": "JIRA-8812"},
"signoff": {"prepared_by": "system", "reviewed_by": "analyst_12",
"approved_by": "finance_controller", "approved_at": "..."}
}Three fields carry disproportionate weight. control_total_check, because it catches truncated files that otherwise reconcile perfectly. by_rule, because it distinguishes a genuinely clean reconciliation from one achieved through wide tolerances. And over_30d_owner, because an aged exception without a named owner is an aged exception nobody is working.
Where this module ends
- Fraud detection is Module 03. A dispute may originate in fraud, but reconciliation is about where the money is, not who took it.
- AML transaction monitoring is Module 04 and runs on the same transaction data for a different purpose. Share the pipeline, not the logic.
- Customer communication during a dispute is Customer Operations, and what you may say is constrained by the tipping-off rules in Module 04.
- Core banking and ledger infrastructure choices are Infrastructure.
- Settlement obligations and TAT compliance sit in the India regulatory spine page.
Illustrative throughout. A production ledger and reconciliation system handling customer money needs an independent financial controls review, and the ledger schema in particular should be reviewed by someone accountable for the accounting treatment before it holds real balances.
Sources
Every figure, rule and date on this page, and where to check it. Entries are typed so you can see which are primary-sourced and which are industry reporting.
- officialRBI (Regulation of Payment Aggregators) Directions, 2025 — PA-O / PA-P / PA-CB, escrow and settlement. www.rbi.org.in
- officialPayment and Settlement Systems Act, 2007 — the statutory basis for payment system regulation in India. www.rbi.org.in
- officialNPCI — UPI volumes, dispute handling and settlement mechanics. www.npci.org.in
- officialRB-IOS and the RBI CMS portal — the complaint route and award limits. cms.rbi.org.in
Tooling, pricing and cost sources for this module are on its build sheet: sources →
Checked September 2026. Regulation in this area is actively developing; the date is part of the claim.
Ask an AI about this page
Opens your assistant with this page as the source, and a question rather than a summary. It will ask what you are building before it answers.
Nothing is sent from here. The link carries only this page’s title and address.