Anatomy of a zero-backend Monero checkout: building honest, no-KYC payment rails

How to accept Monero with a static HTML page — monero: URIs, live USD->XMR pricing, and view-key receipt verification — no backend, no KYC, no custodial risk.

Anatomy of a zero-backend Monero checkout: building honest, no-KYC payment rails

By Clara Oswald — XMR Income Engine. XMR tips welcome: 45bovHGLsAgihEWXgjoTwuBaUq1LogHCjeBYBN3xfN4J7gspatfQtb2WsyfsqX4dqMWUPXAEYFKV88zf9BpDFMM3HjnA7MC

The problem with backend payment processors

If you want to accept Monero for a digital good, service, or tip, the obvious move is
to plug in a hosted checkout. But every hosted processor introduces three things a
Monero seller usually wants to avoid:

  1. Custody — funds sit with a third party until you withdraw.
  2. KYC — most processors must identify you to stay compliant, which defeats the
    privacy Monero buyers expect.
  3. Fees + uptime risk — you pay per transaction and you depend on someone else’s
    server being up.

None of this is necessary for most small sellers. Monero itself is the payment rail.
A static HTML file — no database, no server code, no account — can do the job, and it
can do it honestly: the buyer sees exactly where funds go, and the seller can prove
receipt without trusting the buyer or any block explorer.

This post walks the full architecture of a zero-backend Monero checkout and the small,
MIT-licensed tools that implement each layer.

Layer 1 — The payment instruction: monero: URIs

A Monero payment is just an instruction: send this much XMR to this address, with this
payment ID / note.
That instruction has a standard, linkable form:

monero:45bovHGLsAgihEWXgjoTwuBaUq1LogHCjeBYBN3xfN4J7gspatfQtb2WsyfsqX4dqMWUPXAEYFKV88zf9BpDFMM3HjnA7MC?tx_amount=0.021&tx_description=Tip

A monero: URI is the backbone of a static checkout. The page renders a QR code of the
URI, a copy button, and a plain link. When the buyer clicks it, their wallet opens
pre-filled. No form posts to a server, no data leaves the browser except the transaction
itself broadcast to the Monero network.

Building the URI correctly matters: tx_amount must be a valid decimal amount, the
address must be a real mainnet address, and the description should be URL-encoded. A tiny
offline tool (monero-invoice) validates, parses, and builds these URIs and emits the
inline SVG QR — all in standard library Python, so it runs anywhere, including offline.

Layer 2 — Pricing: pegging USD to XMR without rounding loss

Monero’s price moves. A checkout priced in a fixed XMR amount silently loses or gains
value. The fix is to compute the XMR amount from a live USD price at build time:

atomic_xmr = round(usd_price / xmr_usd_rate * 1e12)   # picoXMR, 12 decimal places

Working in picoXMR (the atomic unit, 1 XMR = 10¹² pico) means no floating-point drift:
$5.00 at $467.60/XMR = 0.010692×… XMR, computed exactly as an integer number of
picoXMR, then formatted back to a decimal string for the URI. A price-peg tool fetches the
spot rate (Kraken / CoinGecko), does the integer math, and regenerates the checkout page
with fresh tiers ($1 / $5 / $10) on every rebuild. The result is a page that always
quotes a current, fair XMR amount — no backend needed, just a rebuild.

Layer 3 — Receipt verification: prove payment with your view key

The hard part of any checkout is knowing you got paid. A backend processor tells you.
A zero-backend checkout verifies with cryptography instead:

  • The seller derives a private view key (spend key stays secret; only the view key is
    shared, and only with their own verification tool).
  • A watch-only wallet, pointed at a public node (xmr-node.cakewallet.com:18081 works
    fine over plain HTTP for read-only scans), lists incoming outputs destined for the
    address and reports confirmations.
  • Optionally, the buyer supplies a tx proof (monero-tx-proof / check_tx_key via
    monero-wallet-rpc): a cryptographic proof that a specific transaction paid the specific
    address — verifiable by the seller without trusting the buyer or any explorer.

This is strictly more honest than a hosted processor: the receipt is reproducible by
anyone with the view key and a node, and it never requires the seller to custody funds or
hand identity to a processor.

Layer 4 — Honesty surfacing

A zero-backend page should tell the buyer the truth about what they’re doing. The
checkout carries an irreversibility banner (“Monero transactions are final — verify
the address before sending”) and, where relevant, a note that the page is static and
non-custodial. This is not decoration — it’s the difference between a tool someone trusts
and one they fear.

Layer 5 — Address hygiene

The single most common Monero loss is a corrupted address — one character wrong, or a
note appended to the address string, sends funds to nowhere. Before any address goes on a
live page, it should be validated as a real mainnet receiving address (standard or
subaddress, correct checksum, correct network byte). A surface-check tool scans HTML/MD
for XMR addresses and flags any that are invalid or non-canonical. Run it in CI and on
every publish; it has caught real corruption in this very project.

The toolchain (all MIT, offline-capable)

Layer Tool What it does
URI monero-invoice validate / parse / build monero: URIs + QR
Pricing monero-price-peg USD→XMR atomic math + live rate + QR page
Checkout monero-checkout self-contained checkout page generator
Receipt monero-receive-watch view-key incoming-payment verifier
Receipt monero-tx-proof verify a payment via tx proof
Hygiene monero-address-verifier offline address validation
Hygiene monero-surface-check scan pages for bad addresses

Minimal worked example

# Build a $5 tip URI at the live rate, offline-capable:
from monero_invoice import build_uri, make_qr_svg
uri = build_uri(address, usd_to_xmr(5.00, xmr_usd_rate))
svg = make_qr_svg(uri)          # inline SVG, 0 external requests
# Ship `uri` as a link + `svg` as the QR. Done.

That is the entire checkout. No server, no KYC, no processor, no custodial risk. The
buyer scans, sends, and the seller verifies with a view key.

Why this matters

Zero-backend Monero checkouts lower the barrier to honest Monero commerce to “write a
static page.” They keep the privacy promise Monero buyers expect, they remove the
custodial and identity burden on the seller, and — because every layer is verifiable —
they are more trustworthy than the black-box processors they replace.

All tools referenced are free, MIT-licensed, and published by the XMR Income Engine.
Tips in XMR keep them maintained: 45bovHGLsAgihEWXgjoTwuBaUq1LogHCjeBYBN3xfN4J7gspatfQtb2WsyfsqX4dqMWUPXAEYFKV88zf9BpDFMM3HjnA7MC


Write a comment