Most banking QR systems were designed for domestic payment networks. They work well inside one country or one regional banking area, but they start failing once you move into international transfers, correspondent banking, or cross-border fintech apps like Revolut.
The newer payto:// standard changes that by introducing universal payment links for bank transfers.
Instead of proprietary QR payloads, payto:// creates interoperable payment URIs that can work across browsers, wallets, banking apps, and international SWIFT rails.
This article explains:
- how traditional banking QR systems work
- why they fail internationally
- limitations of Pay by Square and EPC QR
- why
payto://bicmatters - how to construct international payment URIs
- how to generate QR codes
- how to create deeplinks and payment buttons
- how apps like Revolut could support it
The Problem with Existing Banking QR Systems
Most QR banking standards are local by design.
| System | Region | International? | Notes |
|---|---|---|---|
| EPC QR / GiroCode | EU SEPA | Partial | Mainly SEPA-only |
| Pay by Square | Slovakia | No | Slovak banking ecosystem |
| Swiss QR Bill | Switzerland | Limited | Swiss payment rails |
| PIX QR | Brazil | No | Domestic transfers |
| UPI QR | India | No | Indian banks only |
| PromptPay | Thailand | No | Thai-only |
These systems work because banks inside one network agreed on:
- one QR format
- one clearing system
- one routing method
- one account structure
International banking does not work that way.
Example: Traditional EPC / SCT QR Payload
Older European banking apps often used EPC SEPA Credit Transfer payloads like this:
BCD
002
1
SCT
DEMOUS33XXX
ACME GLOBAL LTD
99887766554433221
USD
Invoice 2025-001
Intermediary: TESTGB2LXXX
This format contains:
| Field | Meaning |
|---|---|
BCD |
EPC QR identifier |
002 |
Version |
SCT |
SEPA Credit Transfer |
DEMOUS33XXX |
BIC/SWIFT |
ACME GLOBAL LTD |
Beneficiary |
99887766554433221 |
Account number |
USD |
Currency |
Invoice 2025-001 |
Payment reference |
TESTGB2LXXX |
Correspondent/intermediary bank |
While this works for some banking apps, it has major limitations internationally.
Why Legacy Banking QR Codes Are Not Enough
The problems begin once the payment leaves the original banking region.
Many apps:
- ignore intermediary bank information
- only support SEPA transfers
- cannot deep link into banking flows
- cannot open from browsers
- require manual copy/paste
- cannot interoperate between wallets
Apps like Revolut internally support:
- SWIFT transfers
- BIC routing
- multiple currencies
- correspondent banks
But there is no universal payment URI standard connecting them.
That is the missing piece.
Why Pay by Square Is Still Regional
Pay by Square works extremely well in Europe because local banks standardized around one QR format.
But globally:
- IBAN is not universal
- account formats differ
- correspondent routing differs
- SWIFT instructions vary
- intermediary banks may be required
This means a QR payload alone cannot reliably describe an international payment.
International Banking Is More Complex
A real international wire transfer may require:
| Field | Why It Matters |
|---|---|
| BIC/SWIFT | identifies destination bank |
| Account number | identifies recipient |
| Beneficiary name | compliance/KYC |
| Currency | settlement |
| Reference | reconciliation |
| Intermediary bank | routed SWIFT transfers |
| Fee mode | SHA/BEN/OUR |
| Address | regulatory checks |
Most QR standards omit several of these.
That is why users still manually enter banking details for international transfers.
RFC 8905: Universal Payment URIs
RFC 8905 introduced a universal payment URI scheme:
Basic structure:
payto://<network>/<target>?params
Examples:
payto://iban/DE75512108001245126199
or:
payto://bic/DEMOUS33XXX
This changes payment handling completely.
Instead of QR codes encoding proprietary banking text formats, the payment becomes a universal URI.
Exactly like:
mailto:tel:bitcoin:
but for banking.
payto://bic Matters
BIC/SWIFT is globally recognized.
Unlike IBAN:
- it works internationally
- it supports SWIFT routing
- it can represent correspondent banking flows
- it is already understood by banks and fintech apps
This makes payto://bic ideal for cross-border transfers.
Minimal example:
payto://bic/DEMOUS33XXX
With metadata:
payto://bic/DEMOUS33XXX
?receiver-name=ACME%20GLOBAL%20LTD
&amount=USD:120
&message=Invoice-2025-001
Why This Helps Apps Like Revolut
Today the flow usually looks like this:
- scan QR
- manually copy details
- open banking app
- create SWIFT transfer manually
- paste fields one-by-one
With payto://bic:
- scan QR
- app opens automatically
- transfer form prefilled
- user confirms payment
This creates a real browser-native payment experience.
Constructing a payto://bic Transfer
Minimal
payto://bic/DEMOUS33XXX
With Amount
payto://bic/DEMOUS33XXX?amount=USD:100
Full International Example
payto://bic/DEMOUS33XXX
?receiver-name=ACME%20GLOBAL%20LTD
&account=99887766554433221
&amount=USD:250
&message=Invoice-2025-001
&corr=TESTGB2LXXX
This structure is:
- human readable
- QR compatible
- browser compatible
- deeplink compatible
- extensible
Why Intermediary Banks Matter
One major weakness of traditional QR standards is correspondent routing.
For example:
Intermediary: TESTGB2LXXX
This is critical for many international transfers.
Older QR systems often treat this as free-form text, making parsing unreliable.
payto://bic can preserve this structurally:
&corr-bank-bic=TESTGB2LXXX
This makes routing deterministic and machine-readable.
Suggested Extended International Format
A practical SWIFT-compatible structure could look like:
payto://bic/DEMOUS33XXX
?account=99887766554433221
&receiver-name=ACME%20GLOBAL%20LTD
&amount=USD:100
&message=Invoice-2025-001
&corr-bank-bic=TESTGB2LXXX
This is far more interoperable than opaque banking QR payloads.
Generating QR Codes
Because payto:// is just a URI, generating QR codes becomes trivial.
JavaScript Example
import QRCode from "qrcode";
const uri =
"payto://bic/DEMOUS33XXX?amount=USD:100";
QRCode.toCanvas(canvas, uri);
Any QR library works.
Deeplinking From the Browser
This is where payto:// becomes powerful.
Simple Link
<a href="payto://bic/DEMOUS33XXX">
Pay via International Bank Transfer
</a>
Triggering Native Apps
On mobile:
window.location.href =
"payto://bic/DEMOUS33XXX?amount=USD:250";
Apps registered for the payto:// protocol can intercept the payment request automatically.
Exactly how:
mailto:tel:bitcoin:
already work today.
Example UI
Modern implementations can generate:
- QR codes
- payment buttons
- deeplinks
- wallet passes
- mobile payment previews
Recommended Architecture
Merchant Side
Generate:
payto://bic/...
Store:
- amount
- currency
- reference
- branding
- transfer metadata
Render:
- QR code
- deeplink
- payment button
- wallet pass
Wallet / Banking App Side
Register handler:
payto://
Parse:
- BIC
- account
- amount
- reference
- correspondent bank
- fee settings
Then prefill the international transfer UI automatically.
Why This Is Better Than IBAN Alone
IBAN is regional.
BIC is global.
Many countries:
- do not use IBAN
- require correspondent banks
- use local account formats
- require extra routing instructions
payto://bic becomes:
- rail-agnostic
- internationally routable
- wallet-friendly
- browser-native
Why This Matters
Banking still lacks:
- universal payment URLs
- interoperable payment deeplinks
- browser-native bank transfer flows
payto:// fills the same role for banking that:
-
mailto:did for email -
tel:did for phones -
bitcoin:did for crypto wallets
And payto://bic may finally make international bank transfers portable across:
- wallets
- banking apps
- QR systems
- fintech platforms
- browsers
without requiring users to manually type SWIFT instructions again.
Try generate PayTo BIC yourself.
Libraries
References
All banking identifiers shown in this article are fictional examples for demonstration purposes only.
Top comments (0)