How to read this build sheet
The Payments and Reconciliation module explains why money that has obviously moved still will not match. This page is the parts list: what to buy, what to build, what each one costs per transaction, and where each breaks.
Every price here carries a Verified September 2026 stamp. Payment pricing is the most negotiable number in this section — published rate cards are the starting position for anyone doing meaningful volume. Treat the figures as budgeting anchors and as a way to tell whether a quote is out of shape.
Payments is four jobs, not one. They get bought from different vendors, break in different ways, and the third one is the one nobody budgets for.
| Job | What it does | Can you skip it? |
|---|---|---|
| Acceptance | Take money from a customer: UPI, cards, net banking, wallets. | No. This is the one everyone buys first and thinks is the whole problem. |
| Payouts | Send money out: refunds, vendor settlements, salaries, disbursals. | Only if money never leaves. Marketplaces, lenders and gig platforms cannot. |
| Reconciliation | Prove what you think happened matches what the bank says happened. | No, and it is not optional in the way people treat it. This is where the finance team's month goes. |
| Disputes | Chargebacks, UPI complaints, refund failures, ombudsman escalations. | No. It arrives whether or not you built for it. |
A gateway integration solves the first. It gives you a partial answer to the second, a data feed for the third, and a dashboard for the fourth. The gap between "we have a payment gateway" and "we can close the books" is most of the work on this page.
The economics that decide everything
In every other build sheet in this section, cost is a line item. Here it is a percentage of revenue, forever, and it is the single number that decides which build you can afford.
Two facts do most of the work.
First: UPI is free to accept, and that is about to stop being universally true. MDR on UPI and RuPay debit was set to zero in January 2020 to drive adoption, and it worked — UPI now carries roughly 88% of India's digital payments, running past 24 billion transactions and close to ₹30 lakh crore a month. The cost has been carried by banks, NPCI, the payment industry and a government incentive scheme.
The Taxation and Other Laws (Amendment) Bill, 2026, passed by the Lok Sabha in August 2026, amends the Payment and Settlement Systems Act, 2007 to let the government notify categories of digital transactions that may carry charges. The Finance Ministry has said consumers pay nothing and all person-to-person transfers stay free. What is under discussion is an MDR in the region of 0.25% to 0.4%, applying only to large merchants (turnover thresholds around ₹1–1.5 crore have been reported) on transactions above ₹2,000 — which would leave roughly 95% of UPI transactions untouched.
Rates and thresholds are not notified yet. The Bill is an enabling provision; the actual categories and rates come later by notification. Do not design a pricing model around a specific number today. Do build the ability to apply a per-rail, per-ticket-size fee and to recompute unit economics when it lands, because if your margin only works at 0% UPI MDR, your margin is a policy position rather than a business model.
Second: zero MDR never meant zero cost. MDR is what the acquiring side charges. Your payment aggregator's platform fee is a separate commercial term. Published rate cards commonly show UPI at 0%, and merchants still find a fee on the invoice, because the aggregator is charging for its own service rather than passing through MDR. Read the contract for the rail-by-rail fee, not the marketing page.
And the fee attracts 18% GST. On the fee, not on the transaction value — so a 2% platform fee is really 2.36% before anything else. That is not a rounding error at scale and it is never in the headline number.
How to rank gateways — and how not to
The instinct is to rank gateways on TDR. It is the wrong first axis, and the arithmetic shows why.
Legacy gateways quote 1.6–1.8% and the modern ones quote around 2%. On ₹1 crore of monthly volume that spread is about ₹30,000 a month. Vendor-reported success rates differ by far more than that — the modern gateways claim 85–90% against 65–75% for older stacks. Treat those specific figures sceptically, because every one of them is published by a party with an interest, but the shape of the argument holds: a 10-point difference in success rate on ₹1 crore of attempted volume is ₹10 lakh of orders, not ₹30,000 of fees.
So rank on four things you can actually measure during a trial:
- Success rate on your own traffic, split by rail, by bank and by ticket size. Not their number. Yours. Run both gateways in parallel on split traffic for a fortnight.
- Settlement timing and what early access costs. T+1 versus T+2 is working capital. Instant settlement is a loan priced as a feature — see the cost block.
- Reconciliation data quality. Does the settlement file carry a stable identifier that matches your order id, fee breakdown per transaction, and a control total? This is the field nobody evaluates and the one that decides whether your month-end takes a day or a week.
- Failure behaviour. Webhook reliability, replay tooling, and what happens to your account when the risk team gets nervous. Sudden account freezes are a documented pattern across Indian aggregators and they are an existential operational risk, not a support ticket.
Add one commercial question to the technical evaluation: what is the exit path? Getting a gateway in takes a day. Getting customer card tokens, mandates and subscription state out is the part that takes a quarter, and it is the reason single-gateway merchants accept bad terms at renewal. Ask about token portability before you sign, not after.
Raw materials — acceptance and rails
| Material | What it does | Verify at |
|---|---|---|
| Razorpay | The default for Indian online acceptance. Cleanest API and docs, strongest subscription tooling, UPI AutoPay support. | razorpay.com/docs |
| Cashfree | Lowest published TDR of the majors, strong on marketplace payouts and batch disbursal. | docs.cashfree.com |
| PayU | Enterprise and cross-border reach, dedicated account management, established chargeback handling. | payu.in |
| CCAvenue / BillDesk | Legacy breadth of bank acceptance. Lower headline TDR, but setup and annual fees change the total. | ccavenue.com |
| Stripe | The right answer when your customers are mostly international. Not the right answer for a domestic Indian book. | stripe.com/docs |
| UPI indirect | The dominant rail. Reached through a PA or a sponsor bank, never directly. | npci.org.in |
| NPCI URCS / UDIR indirect | UPI dispute resolution and the TCC/RET mechanism. Reached through your sponsor bank or PSP. | npci.org.in |
| RBI CMS portal direct | The ombudsman complaint system. Customer-facing — monitor what reaches it, because it is a supervisory signal about you. | cms.rbi.org.in |
Notice how much of this is indirect. You do not integrate with UPI. You integrate with a payment aggregator or a sponsor bank that integrates with NPCI. Every timing assumption, every dispute window and every settlement file format you build against is theirs, and changes when you switch. Budget for that when you plan a migration.
Raw materials — reconciliation and ledger
| Material | What it does | Verify at |
|---|---|---|
| DuckDB oss | In-process analytical SQL. Joins a month of settlement files against your ledger on a laptop, no warehouse needed. The highest-leverage tool on this page. | duckdb.org |
| Polars / pandas oss | Dataframe matching. Polars is materially faster on large settlement files. | pola.rs |
| RapidFuzz oss | String similarity for narration-based matching on bank statement lines. | github.com/rapidfuzz |
| dbt oss | Versioned, tested transformation logic. Reconciliation rules are exactly the kind of logic that must be testable and reviewable. | getdbt.com |
| Apache Arrow / Parquet oss | Columnar archive for settlement files you must retain and re-query years later. | arrow.apache.org |
| Osfin / Cointab / Nanonets | Reconciliation automation with real India market presence and native settlement-file formats. | osfin.ai |
| Ledge | Built for high-volume real-time fintech and marketplace matching. Faster to first production match than the enterprise suites. | ledge.co |
| HighRadius / BlackLine / Trintech | Enterprise record-to-report and financial close. Mature, heavy, audit-oriented, three-to-six-month implementations. | blackline.com |
How to use each one — accepting money
Acceptance integration is well-documented by every vendor and you do not need us to repeat it. What the vendor docs do not tell you is which three things you will get wrong.
Webhooks: the part that decides whether your ledger is trustworthy
import hmac, hashlib
from flask import request, abort
SECRET = b"your_webhook_secret"
@app.post("/webhooks/payments")
def payments_webhook():
# BUG 1: verifying the signature against parsed-then-reserialised JSON.
# The signature is over the RAW BYTES. request.get_json() reorders keys and
# changes whitespace, so the digest never matches -- or worse, you "fix" it
# by skipping verification.
raw = request.get_data() # bytes, before any parsing
sent = request.headers.get("X-Signature", "")
calc = hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(calc, sent): # constant time, not ==
abort(400)
ev = json.loads(raw)
# BUG 2: treating delivery as exactly-once and in-order. It is neither.
# payment.failed can arrive AFTER payment.captured for the same payment.
# Order by the event's own timestamp; never by arrival.
with db.begin():
prior = db.get_event(ev["id"])
if prior:
return "", 200 # already processed, idempotent
current = db.get_payment_state(ev["payload"]["payment_id"])
if current and ev["created_at"] <= current.state_as_of:
db.record_event(ev["id"], outcome="stale_ignored")
return "", 200 # out-of-order, safely dropped
# BUG 3: trusting the webhook body for the amount. The signature proves
# it came from the PSP; it does not prove your order is for that amount.
order = db.get_order(ev["payload"]["order_id"])
if order.amount_paise != ev["payload"]["amount"]:
db.flag_for_review(order.id, "amount_mismatch")
return "", 200 # 200 stops the retry storm
db.apply(ev)
db.record_event(ev["id"], outcome="applied")
return "", 200
# WHAT TO CHECK
# [ ] signature computed over raw bytes, compared with compare_digest
# [ ] the event id is stored and checked BEFORE any state change, in the same
# transaction as the state change -- otherwise a retry during processing
# double-applies
# [ ] out-of-order handling driven by the event timestamp, not arrival order
# [ ] amounts in integer paise. Never float. 0.1 + 0.2 != 0.3
# [ ] non-2xx only for "retry me". A 500 on a malformed event you will never be
# able to process buys you that event, forever, at increasing intervals
# [ ] webhook handler does NOT call the PSP synchronously. Enqueue and return;
# a slow handler becomes a retry storm becomes a duplicate storm
# [ ] replay tooling exists and has been used once in anger before you need it
The gotcha nobody documents: a webhook is a notification that something may
have changed, not a statement of fact about your money. The authoritative record of what you
were actually paid is the settlement file, which arrives later and disagrees more often than teams
expect. Build the ledger so the webhook moves a payment to captured and only the
settlement file moves it to settled. Merging those two states into one is the root of a
large share of reconciliation breaks.
Refunds are not negative payments
Almost every ledger starts by modelling a refund as a payment with a minus sign. It works until partial refunds interleave with reversals, and then it stops working permanently.
A refund has its own lifecycle (created, processed,
failed), its own settlement timing that does not line up with the original payment's,
and its own failure mode where the money leaves your escrow and does not arrive with the customer.
A failed refund is not a refund that did not happen — it is money in flight with a customer
who is already unhappy. Give refunds their own table, their own idempotency key and their own
exception queue.
How to use each one — reconciliation
Reconciliation is not a product you buy first. It is a query you run, and the useful realisation is how far a single tool gets you.
DuckDB is the answer for most teams for longer than they expect
Settlement reconciliation is a join between two files. Until you are doing millions of transactions a day, that join runs in seconds in an in-process analytical database against CSVs on disk. No warehouse, no ingestion pipeline, no vendor. Teams routinely buy a platform to do something their data volume does not justify, and then discover that the platform still needs them to define every matching rule.
-- Run this against the settlement file and your ledger. DuckDB reads the CSV
-- in place; no warehouse, no ingestion pipeline.
-- STEP 1: control totals FIRST, before any matching.
-- A file missing its last 200 rows reconciles with a perfect match rate on the
-- rows that are present. Match rate is silent about what is not in the file.
WITH declared AS ( -- from the file header / manifest, not the rows
SELECT 48213 AS row_count, 9182734500 AS total_paise
),
actual AS (
SELECT COUNT(*) AS row_count, SUM(amount_paise) AS total_paise
FROM read_csv_auto('settlement_2026_09_12.csv')
)
SELECT CASE
WHEN a.row_count <> d.row_count OR a.total_paise <> d.total_paise
THEN 'ABORT: file integrity failed' ELSE 'ok' END AS gate,
d.row_count AS declared_rows, a.row_count AS actual_rows,
d.total_paise - a.total_paise AS paise_difference
FROM declared d, actual a;
-- STEP 2: match, and record WHICH RULE fired for every row.
SELECT
COALESCE(l.order_id, s.merchant_ref) AS order_id,
CASE
WHEN l.psp_payment_id = s.psp_payment_id THEN 'exact_psp_id'
WHEN l.order_id = s.merchant_ref
AND l.amount_paise = s.amount_paise THEN 'ref_plus_amount'
WHEN l.order_id = s.merchant_ref
AND ABS(l.amount_paise - s.amount_paise)
<= s.fee_paise + s.tax_paise THEN 'net_of_fees'
ELSE 'unmatched'
END AS match_rule,
l.amount_paise AS ledger_paise, s.amount_paise AS settled_paise,
s.fee_paise, s.tax_paise,
l.amount_paise - (s.amount_paise + s.fee_paise + s.tax_paise) AS residual_paise
FROM ledger l
FULL OUTER JOIN read_csv_auto('settlement_2026_09_12.csv') s
ON l.psp_payment_id = s.psp_payment_id OR l.order_id = s.merchant_ref;
-- WHAT TO CHECK
-- [ ] control totals run BEFORE matching and ABORT the run. A silently
-- truncated file is the single most dangerous input here, because every
-- downstream metric looks healthy.
-- [ ] FULL OUTER JOIN, not LEFT. A row in the settlement file that is in no
-- ledger is the interesting case -- money you were paid and cannot explain.
-- [ ] match_rule stored per row. "94% auto-matched" is meaningless without the
-- mix; a jump in net_of_fees means the PSP changed its fee reporting.
-- [ ] know whether your PSP deducts fees PER TRANSACTION or in one aggregate
-- debit. It changes the matching logic completely and it differs by PSP and
-- sometimes by plan within one PSP.
-- [ ] residual_paise must be exactly 0 on a clean match. Any tolerance you add
-- here is a control change: version it, date it, get it approved.
-- [ ] time zone. Settlement files are cut on IST business days. Aggregating in
-- UTC moves 5.5 hours of transactions into the wrong settlement day.
-- [ ] a debit with no credit inside the RBI reversal window is NOT a break yet.
-- Age it before you escalate it.
The gotcha nobody documents: whether fees are deducted per transaction or as a single aggregate debit at the end of the cycle. It varies by aggregator, and sometimes by plan within one aggregator. Per-transaction deduction means your settled amount never equals your ledger amount and every match must be net-of-fees. Aggregate deduction means the transactions match exactly and there is one large unexplained debit that belongs to no order at all. Building for one and receiving the other is a full rewrite of the matching layer. Ask before you integrate, and ask for a sample file.
Build the ledger so breaks cannot happen
Most reconciliation work is compensating for a ledger that allowed the break in the first place. Four decisions remove more exceptions than any matching engine:
- Integer minor units. Paise, as integers, everywhere. Floats in money columns are the single most avoidable defect in fintech.
- A caller-supplied idempotency key with a UNIQUE constraint. Not generated by you on receipt — supplied by the caller, so a retry of the same intent collapses to one record at the database level rather than in application logic.
effective_atseparate fromrecorded_at. The two clocks from the module. When the money moved, and when you learned it moved. Collapsing these makes late-arriving settlement data look like an error.- Append-only. A correction is a new entry, never an update. The ability to reconstruct what you believed on a given date is the entire audit trail.
How to use each one — payouts and the PA rules
Payouts feel like acceptance in reverse. They are not. Acceptance failures cost you a sale; payout failures cost you money you have already sent, and the recovery path runs through a bank.
import uuid, requests
def disburse(order_id, account, amount_paise, attempt_state):
# The idempotency key is derived from the INTENT, not from the attempt.
# Same intent retried -> same key -> PSP returns the original payout.
# A fresh uuid4() per retry is how platforms pay the same person twice.
key = f"payout:{order_id}"
r = requests.post(
"https://api.psp.example/v1/payouts",
json={"account": account, "amount": amount_paise,
"currency": "INR", "reference": order_id},
headers={"Idempotency-Key": key, "Authorization": f"Bearer {TOKEN}"},
timeout=(3, 30),
)
# A TIMEOUT IS NOT A FAILURE. It is an unknown. The payout may have been
# created. Never retry a timeout as a fresh request without the same key,
# and never mark it failed without asking the PSP what happened.
if r.status_code >= 500 or r.status_code == 408:
return reconcile_unknown(key, order_id)
r.raise_for_status()
return r.json()
def reconcile_unknown(key, order_id):
"""Ask, do not assume. Query by YOUR reference, not the PSP's id --
you may never have received the PSP's id."""
q = requests.get("https://api.psp.example/v1/payouts",
params={"reference": order_id}, timeout=(3, 30))
hits = q.json().get("items", [])
if hits:
return hits[0] # it existed all along
return {"status": "unknown", "action": "queue_for_human"}
# WHAT TO CHECK
# [ ] idempotency key derived from the intent and STORED before the call, not
# after. If the process dies mid-request you must be able to recover the key
# [ ] separate connect and read timeouts. A single timeout value means a slow
# PSP holds your worker pool
# [ ] timeouts and 5xx go to an UNKNOWN state, never to failed. "Failed" is a
# conclusion; only the PSP can give you that
# [ ] queryable by your own reference, not only by the PSP's identifier
# [ ] a daily sweep that lists PSP payouts with no matching local record. This
# is how you find the ones you paid and never booked
# [ ] beneficiary account validated (penny drop or name match) BEFORE the first
# payout, not after the first complaint
# [ ] payouts and refunds are different flows even though both send money out.
# A refund is tied to a payment and a customer right; a payout is not
The gotcha nobody documents: the timeout. Every payments team knows to use idempotency keys and most still treat a request timeout as a failure and retry with a fresh key. The PSP received the first request. It created the payout. Your side recorded a failure, retried, and created a second one. This is the single most expensive bug in this build sheet, and it only ever shows up under load, which is exactly when you are least able to investigate it.
If you are the aggregator: the 2025 Directions
Everything above assumes you use a PA. If you are one, or you are close enough to look like one, the rules changed materially and recently.
The RBI (Regulation of Payment Aggregators) Directions, 2025, notified 15 September 2025 and effective immediately, repealed and replaced the 2020 PA-PG Guidelines, the 2021 clarifications and the separate cross-border circular. The shape:
| Item | Requirement |
|---|---|
| Categories | PA-O online · PA-P physical (proximity) · PA-CB cross-border. PA-P is newly regulated — entities doing only PA-P had to apply by 31 Dec 2025 or wind down by 28 Feb 2026. |
| Net worth | ₹15 crore at application, rising to ₹25 crore and maintained on an ongoing basis. |
| Escrow | With a Scheduled Commercial Bank. Your own funds must not sit in it. Day-end balance must equal the amount realised. Pre-funding is permitted for domestic PAs only, and pre-funded amounts cannot be withdrawn. |
| PA-CB | Separate InCA (inward) and OCA (outward) accounts, never commingled. Per-transaction cap of ₹25 lakh. No direct dealing in foreign currency except through an authorised dealer. No interest on international balances. |
| Settlement | Liberalised from a fixed regulatory timeline to what the PA–merchant agreement provides, as long as it is fair, equitable and the timelines are transparently disclosed. |
| Card data | Only issuers and card networks may store card details. Everyone else tokenises or deletes. |
| Reporting | Monthly transaction statistics to RBI; quarterly auditor's certificate on escrow balances. FIU-IND registration required — see Build Sheet 04. |
A deadline lands this week. Merchants onboarded up to 31 December 2025 had to be brought into line with the new customer due diligence requirements by 15 September 2026. There is no equivalent leeway for merchants onboarded from 1 January 2026 onwards. Acquiring banks now also need their own policy for merchants acquired by non-bank PAs, and must be able to pull the PA's due-diligence records on demand — so this reaches your bank relationship, not only your compliance file.
Cost per unit
Payments — cost per unit
Verified September 2026Model cost per successful order, not cost per transaction. A gateway at 1.75% with an 80% success rate costs you more per completed order than one at 2% with 90%, before you count the customer who abandoned and did not come back. Compute: (fee × 1.18 GST) ÷ success rate, per rail, on your own traffic mix. That single number reorders most gateway shortlists, and it is the number no vendor will compute for you.
Three cost lines that arrive after the contract: chargeback handling fees on disputes you win, per-refund fees at some providers, and the working-capital cost of settlement timing, which is real money and never appears on any rate card.
Best combinations
| Combination | Works because |
|---|---|
| Two gateways with rule-based routing | Redundancy against outages, leverage at renewal, and real A/B data on success rate. The single highest-return architectural decision on this page. |
Webhook moves to captured, settlement file moves to settled | Two clocks, two states. Most reconciliation breaks are the two collapsed into one. |
| Append-only ledger + DuckDB matching | The ledger prevents the break; the query finds the ones that got through. Neither needs a vendor. |
| Domestic PA + specialist cross-border provider | Different problems. A domestic aggregator bolting on international acceptance is usually the most expensive way to receive foreign money. |
| Control totals + exception aging | Totals catch what is missing from the file; aging catches what you stopped looking at. Match rate alone catches neither. |
| Tokenisation at the network + your own subscription state | Card data stays where regulation requires it, and the mandate state stays portable enough that you can actually switch. |
Combinations that conflict
- One gateway and no fallback. Every Indian aggregator has had outages, and the freeze pattern is documented. A single point of failure on revenue is a business risk, not an engineering preference.
- Treating the webhook as the source of truth for money. It is a notification. The settlement file is the fact.
- Refunds modelled as negative payments. Works until partial refunds and reversals interleave, then never works again.
- A fresh idempotency key on retry. This is how you pay a supplier twice.
- Buying an enterprise close suite for a single-PSP book. Three-to-six months of implementation to automate a join you could write today.
- Widening tolerances to raise the auto-match rate. The number improves and the control degrades. If match rate jumps and exception value does not fall proportionately, someone moved a tolerance.
- Reconciling in UTC. Settlement files cut on IST business days. Five and a half hours of transactions land in the wrong day, every day.
Three recommended builds
Strong and expensive
Build: two payment aggregators with an orchestration layer routing by rail, bank and ticket size, plus a specialist cross-border provider, plus an enterprise reconciliation and close platform, plus a dedicated disputes function.
Use when: volume is high enough that a point of success rate is worth more than the entire tooling budget, and you have a finance team with a statutory close to meet.
Cost shape: blended TDR plus six figures a year in close tooling plus headcount.
Trade: the orchestration layer becomes its own system to maintain, and the close suite takes three to six months before it matches a single transaction.
Strong and reasonable — the default
Build: primary aggregator plus a second one kept live at low volume for failover and leverage → an append-only ledger with integer paise, caller-supplied idempotency keys and the two clocks separated → settlement reconciliation in DuckDB or dbt, run daily, rules in version control → an exception queue with named owners and aging → disputes handled in-house against a written playbook.
Use when: you have engineers and payments are core rather than incidental. This covers most fintechs, marketplaces and subscription businesses in India.
Cost shape: TDR plus GST, and essentially nothing for the reconciliation stack beyond the engineering time to write the rules.
Trade: you own the matching rules, which means you must test them like code. That is the right trade, because those rules encode your specific commercial arrangements and no vendor knows them better than you do.
Why the second gateway is in the default build rather than the expensive one. It is not primarily about redundancy. It is that running 5% of traffic through an alternative is the only way to get an honest success-rate comparison, and the only leverage you have at renewal. The cost of keeping it live is close to zero; the cost of not having it is discovered on the day you need it.
Strong and lean
Build: one aggregator on published pricing → the same ledger discipline, which costs nothing extra if you do it from day one → a single scheduled DuckDB query against the daily settlement file, with control totals → exceptions in a spreadsheet with an owner and a date.
Use when: pre-revenue or early, and every hour spent on payments infrastructure is an hour not spent on the product.
Cost shape: TDR only.
Trade: no failover and manual exception handling. Acceptable. What is not acceptable at any scale is the ledger shortcut — floats, no idempotency key, one timestamp. Those cost nothing to get right on day one and are close to unfixable once there is a year of data behind them.
Whichever grade you pick: do not automate reconciliation and remove human sign-off in the same project. Speed belongs on matching. Accountability stays on approval. A system that closes the books with nobody accountable for the number is worse than the slow manual process it replaced.
What next
Two numbers to watch that are not in anyone's dashboard by default.
Exception aging, as a distribution. Not the average. No unmatched item older than 30 days without a documented owner and a plan. The average hides the one item from March that nobody has looked at since.
Complaint rate reaching the ombudsman. UPI complaint volume passed 1.2 million a month in early 2026, around 60% of it "debited but not credited". RB-IOS 2026 replaced the 2021 scheme from 1 July 2026, with awards up to ₹30 lakh for consequential loss and ₹3 lakh for time, expense and harassment. What reaches the RBI CMS portal about you is a supervisory signal, and it is visible to your regulator before it is visible to you unless you are watching for it.
What this feeds
Fraud & Risk
Authorisation latency, step-up rather than block, and the chargeback evidence pack. Shares a queue with disputes.
AML & Compliance
Real-time payment screening runs inside this latency budget, and FIU-IND registration is a PA obligation.
Customer Operations
"Where is my refund" is the highest-volume contact reason in Indian fintech. Reconciliation quality is support volume.
Licensing & Access
PA authorisation, net worth thresholds and timelines if you are becoming the aggregator rather than using one.
Everything on this page is illustrative. Payment systems move customer money and carry statutory obligations under the Payment and Settlement Systems Act and the RBI PA Directions. Nothing here is legal or financial advice. Have your settlement design, your escrow arrangements and your dispute workflow reviewed by qualified counsel before they touch a real rupee.
Sources
Every figure, rule and date on this page, and where to check it. Entries are typed so you can see which numbers are primary-sourced and which are industry reporting — they are not equivalent, and treating them as if they were is how a confident wrong number gets repeated.
- officialRBI (Regulation of Payment Aggregators) Directions, 2025 — the PA-O / PA-P / PA-CB categories, net worth, escrow rules, the ₹25 lakh PA-CB cap, and the 15 September 2026 legacy-merchant CDD deadline. www.rbi.org.in
- officialPayment and Settlement Systems Act, 2007 — the statute the 2026 amendment Bill modifies to enable charges on digital transactions. www.rbi.org.in
- officialNPCI — UPI volume and value, the dispute mechanism, and the third-party market-share cap timeline. www.npci.org.in
- officialRBI Ombudsman Scheme (RB-IOS) — the award limits and the complaint route through the CMS portal. cms.rbi.org.in
- industryTaxation and Other Laws (Amendment) Bill, 2026 — reporting — the reported 0.25–0.4% range, the large-merchant turnover threshold and the ₹2,000 ticket floor. Rates are not notified. Treat as direction, not figures.
- vendorRazorpay, Cashfree and PayU published pricing — the ~2% domestic rate, ~3% premium and international, and settlement timing options. razorpay.com
- industryLegacy gateway pricing — the 1.6–1.8% headline plus setup and annual maintenance. Vendor-published and third-party compiled.
Checked September 2026. Pricing and draft regulation move; 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.