Back to blogIndia · Payments

UPI vs BharatQR — India payment QR guide (2026)

India does more QR payments than the rest of the world combined. UPI alone processes 18 billion transactions per month. Here's what every merchant, developer, and product manager needs to know about the formats, rules, and fees.

April 2026· 13 min read

TL;DR: For India-only merchants, UPI is free, instant, and covers 95%+ of smartphone wallets. BharatQR is a superset that also accepts RuPay, Visa, and Mastercard cards. For global apps, combine with other regional payment QRs.

The landscape in one paragraph

India has three overlapping payment-QR formats, all interoperable at the scan point:

  • UPI Intent — the upi://pay URI scheme. Opens any UPI app on the phone (PhonePe, Google Pay, Paytm, BHIM, etc.)
  • BharatQR — an EMVCo TLV-encoded QR string that includes UPI and RuPay / Visa / Mastercard rails
  • UPI QR (static / dynamic) — simply a QR image encoding a UPI intent URI

Format comparison

ModeExample / structureUse when
UPI Intentupi://pay?pa=merchant@okhdfc&pn=Shop&am=499.00&tn=Order-1234Peer-to-peer and merchant pay-to-VPA flows
BharatQR (EMVCo)EMVCo TLV with GUID A000000524010105 (UPI) or A000000727 (RuPay)Cards + UPI interoperable merchant QR
Static UPI QRupi://pay?pa=shop@okhdfc&pn=Shop&cu=INRFixed-amount or variable-amount shelf QR
Dynamic UPI QRGenerated per-transaction with unique transactionRefBilling counters, ticketing, subscription

The UPI intent URI — anatomy

A UPI intent is a URI with query parameters. The spec is short and strict:

upi://pay?pa=shop@okhdfc&pn=My%20Shop&am=499.00&cu=INR&tn=Order%201234

Parameters (RFC-style, all case-sensitive):

  • pa — payee address (the VPA / UPI ID, required)
  • pn — payee name (required; URL-encoded)
  • am — amount (optional; fixed if present, user-entered if absent)
  • cu — currency (must be INR for domestic UPI)
  • tn — transaction note (optional; shown in the UPI app)
  • tr — transaction reference (required for dynamic / merchant QRs)
  • mc — merchant code (MCC; required for merchants)

Escape your parameters

Non-ASCII characters, spaces, ampersands, and special chars must be percent-encoded. The #1 reason a QR “doesn't work” is an unescaped space in pn or tn.

BharatQR — when you need cards too

BharatQR is the common merchant QR promoted by RBI and NPCI. Unlike a pure UPI intent, it uses the EMVCo TLV format — the same format as PIX (Brazil), PromptPay (Thailand), and SGQR (Singapore). This means a single QR string works in multiple payment apps via different rails.

Structure (simplified):

00020101021126XX0016A000000524010105020212 52044900530...58025954...62...6304<crc16>

Each TLV record is three bytes + payload:

  • Tag (2 digits) — what kind of data this is
  • Length (2 digits) — how many bytes follow
  • Value (that many bytes) — the actual data

Common tags: 00=payload format, 01=point of init method, 26–51=merchant account info (nested), 52=MCC, 53=currency, 54=amount, 58=country, 59=merchant name, 60=city, 63=CRC.

The whole string is terminated with a CRC-16/CCITT-FALSE checksum. Get that checksum wrong, and every EMVCo parser will reject your QR. This is by far the most common integration bug.

MDR — what you actually pay

  • UPI peer-to-merchant (P2M), debit UPI, amount ≤ ₹2,000: 0% MDR — regulated by NPCI
  • UPI on RuPay credit card: ~1.1% (tiered, capped by NPCI/RBI from time to time)
  • BharatQR with Visa/Mastercard credit: Normal card interchange (1.9–2.5%+ GST)
  • BharatQR with RuPay debit: 0.4–0.9% typically

For a chai stall or kirana store doing ₹20 lakh/month in UPI debit transactions, you pay zero fees. That's why UPI has eaten the world.

Static vs dynamic — for merchants

Print a static QR once and stick it at your counter. Customer scans → types in the amount → pays. This is the ₹5 sticker you see on every chai stall and auto rickshaw. It works forever and costs nothing.

Generate a dynamic QR at the point of sale with amount + transaction reference. The customer scans and just confirms. Required if you want automated reconciliation and fast checkout. Most POS and billing software generate these on demand.

RBI / regulatory context

  • KYC: Merchants above ₹5 lakh/year in receipts must complete UPI merchant KYC
  • MDR waiver: Regulated under the Finance Act 2019 as clarified by CBDT; applies to UPI/RuPay debit for P2M
  • Transaction limits: Per-transaction ₹1 lakh (retail), ₹2 lakh for high-value categories, ₹5 lakh for tax/insurance. Daily caps set by issuer bank.
  • Cross-border: UPI now works in Singapore, UAE, Sri Lanka, Mauritius, and more — same QR format, different currency conversion layer

Common integration mistakes

Missing URL-encoding on merchant name

Always percent-encode `pn` and `tn`.

Hard-coded amount without `cu=INR`

Some UPI apps reject amount without explicit currency.

Wrong CRC-16 in BharatQR

Use a certified library — compute AFTER adding the length-04 CRC placeholder.

Same `tr` reused for different payments

Transaction reference must be unique per attempt; causes duplicate-detection rejections.

Using static QR for amounts > ₹10,000

RBI guidance — dynamic QRs strongly recommended above that threshold.

What QRMax provides

  • Both UPI intent and BharatQR (EMVCo TLV) encoders
  • Validated CRC-16/CCITT-FALSE implementation
  • Static + dynamic UPI QR generation with reconciliation webhooks
  • Cross-payment-format coverage — UPI, BharatQR, PIX, PromptPay, SGQR, Bitcoin BIP21, Lightning
  • Tested with PhonePe, Google Pay, Paytm, BHIM, CRED, Amazon Pay

Next steps

See UPI QR type for the live generator, or read about BharatQR. For merchant-platform integration see our finance workflow.