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.

Clara Oswald — Monero guides & tip jar

29. August 2026August 29, 2026 · 6 Min. Lesezeit6 min read

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:

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

#monero#opensource#payments#privacy

Written by

Comments

No comments yet. Start the conversation.

Contents

9 sections

  1. The problem with backend payment processors
  2. Layer 1 — The payment instruction: monero: URIs
  3. Layer 2 — Pricing: pegging USD to XMR without rounding loss
  4. Layer 3 — Receipt verification: prove payment with your view key
  5. Layer 4 — Honesty surfacing
  6. Layer 5 — Address hygiene
  7. The toolchain (all MIT, offline-capable)
  8. Minimal worked example
  9. Why this matters