What StableInvoice is
A tool for building professional invoices and payment requests that settle in stablecoins, straight between wallets. There is no account, no custody and no database: an invoice lives inside its own link, and your client opens that link to pay from their own wallet.
Everything runs in your browser. Your keys never leave it, and neither does your invoice data — the payload rides in the part of the URL that browsers never send to a server.
It works for AI agents too. StableInvoice runs an MCP server at
https://www.stableinvoice.xyz/mcp, so an agent can issue, check and
verify invoices as tools while its own wallet keeps the keys. It is free and
needs no account — see For AI agents.
Three kinds of link
Payment links get forwarded. Which kind you send decides what the recipient can trust.
Unsigned
The default. Fast, and works without a wallet connected.
- Anyone holding the link can read it
- Anyone forwarding it can change the recipient address
- The payment page says exactly that, in plain words
Signed — recommended
One click. Binds the invoice to your Ethereum account.
- Recipient address, amount, token, chain and expiry are all covered
- Alter any of them and the payment page turns red and refuses to pay
- Still readable by anyone holding the link
Encrypted
For invoices whose contents are nobody else’s business.
- Only the holder of one X25519 key can read it
- Signed as well, so tampering is still detected
- Needs your client’s public key up front
What protects you
A correctly signed invoice can still be a fraudulent one. These cover that gap.
It remembers who you pay
The fraud that actually happens is not a stranger inventing a bill. It is a supplier you have paid eleven times, where the twelfth invoice quietly carries a different destination address. Everything else looks right because everything else is right — and no signature catches it, because the forged link is correctly signed by the forger.
So the payment page remembers which addresses you have paid each counterparty at. A familiar name with an unfamiliar address turns the page red and disables the pay button until you have checked. The record is written only after you actually pay — never just from opening a link, or a forged one would teach itself as trusted.
Safety numbers
“Confirm the address out of band” is useless advice when the address is 40 hexadecimal characters. In practice people check the first four and the last four — which is precisely the check a vanity-address generator beats.
So every recipient address also appears as a 20-digit safety number you can read down a phone line, in any language. The length is deliberate: a short fingerprint can be brute-forced until it collides.
What the app refuses to do
- Substitute a different token when the one you chose is not on that chain
- Build a link with an invalid or zero recipient address
- Round an amount it cannot represent exactly
- Show a green check for a sender it cannot genuinely confirm
- Put your bank details into a shareable link
Sanctioned addresses are refused
Before payment unlocks, the recipient address is checked against the OFAC sanctions (SDN) list using Chainalysis's free on-chain oracle — a public smart contract anyone can read. No account, no API key, no sign-up: the check runs through your own wallet or a public Ethereum node.
A listed address disables payment and says why. If the check cannot complete, the page says that instead of pretending it ran — and it never locks you out of an address that screens clean.
Test networks are kept apart
Sepolia and other test chains sit in their own group in every network picker, labelled not real money. An invoice issued on a testnet can never be paid, and in a flat list that reads like just another option.
How encrypted invoices work
Encryption runs in both directions of a relationship: your client generates a key and proves it is theirs, and then you encrypt to it.
If you are being invoiced
- Open Generate Key and create an X25519 keypair. It is made in your browser and never uploaded.
- Export it with a passphrase. The plain-text option exists, but a passphrase-wrapped file is useless to anyone who finds it.
- Press Sign Public Key to bind it to your Ethereum address, then Copy signed bundle.
- Send that bundle to whoever invoices you.
If you are sending the invoice
- Paste their bundle into the recipient key field, or check it on Verify Key.
- The app recovers the signature and confirms the key really belongs to that address, rather than trusting a bare key someone pasted.
- Build the invoice and choose Create Encrypted Pay Link.
- Only their private key opens it. Lose that key and the invoice is unrecoverable, by design.
Privacy and custody
- No accounts, no sign-up, no invoice database
- Payments go wallet to wallet; funds never pass through us
- Private keys stay in your wallet, or are generated locally and never uploaded
- Invoice data rides in the URL fragment, which browsers do not send to servers
- Bank details stay in the PDF and are never embedded in a link
- Sanctions screening shares only the recipient address — with the Chainalysis oracle via your wallet or a public Ethereum node — never amounts, names, or the invoice itself
Under the hood
- Vite multi-page build, Tailwind CSS, vanilla ES modules
- jsPDF for export, fetched only when you generate a PDF
- libsodium for X25519 encryption and Argon2id key wrapping
- EIP-712 signatures; EIP-681 wallet deep links and QR codes
- WalletConnect for mobile wallets; recipients screened against the OFAC SDN list before payment is enabled
- All third-party code is self-hosted — nothing loads from a CDN
- Strict Content Security Policy, with no inline scripts anywhere
From Telegram
Everything above assumes a browser. @StableInvoice_Bot does the common jobs from a chat, which is usually where the client already is.
Setting it up
/start— then/helpfor the full list/setwallet 0x…— the address you get paid at, stored once/setbillfromand/setbillto— company and client details for invoice PDFs/getwallet,/resetwallet— read it back, or delete it
Getting paid
/paymentlink charge 10 USDT on Polygon for 3 beers— plain English; the amount, token and network are read out of the sentence/invoice— the same, plus a PDF/payother— a transfer link for paying someone else/verify <tx> <chain>and/checkpayment— confirm a payment landed- You are told when you get paid. Every link made in the bot is watched, and the bot messages you when the payment arrives.
/watchinglists them;/stopwatchingcancels - Made the invoice on the website instead? Press Notify me on Telegram next to the link and the same thing happens
What it stores, and how
- Your wallet address and billing details, so you do not retype them
- Encrypted at rest with AES-256-GCM, bound to your Telegram id so one record cannot be replayed as another
- To tell you when a link is paid, the bot keeps the amount, token, network and your address for it — nothing about your client — encrypted, and deletes it once the link is paid, expires or you cancel
- The website button sends nothing by itself: those details reach the bot only when you press Start in Telegram
/resetwalletdeletes the stored address
Three honest limits
- Bot links are unsigned. They carry no signature, so a forwarded link can have its recipient address changed. For a stranger, make the link on the website and use Create Signed Link.
- Encryption is browser-only. Encrypted links need a key that never leaves your device, so the bot cannot make them. It will tell you so rather than pretend.
- Notifications match the exact amount. A transfer carries no invoice number, so the amount is all that ties a payment to an invoice. A part-payment or a different amount is not announced, two invoices for the same amount to the same wallet cannot be told apart, and Rootstock is not watched yet.
For AI agents
Everything above assumes a person. An autonomous agent can do the same jobs through tools — issue an invoice, decide whether one is safe to pay, and confirm it was paid — with nobody in the loop.
What an agent can do
create_payment_link— build a link, and get the EIP‑712 data for the agent’s wallet to signattach_signature— check that signature and return the signed linkread_payment_link— decode a link, verify it, screen the recipient, and answerpayablewith the exact transfer to sendverify_payment— confirm on-chain that a transaction paid an invoicevalidate_addressandlist_supported_assets— catch a mistyped address or a token that is not on that network
How to connect
- MCP:
https://www.stableinvoice.xyz/mcp— for Claude, IDEs, and LangChain or CrewAI through their MCP adapters - HTTP:
POST /api/v1/<tool>with the tool’s arguments as JSON - x402: an invoice in USDC or EURC on Base, Polygon, Arbitrum or Avalanche also has an x402 address, so any x402-capable agent can pay it with no gas. The money goes from the payer straight to your wallet
- No account, no API key, free
- Specs: manifest, tool definitions, OpenAPI, agent guide
What the hosted service sees and keeps
Elsewhere on this site an invoice never reaches our server. To read or verify a link for an agent, the hosted tools have to be given it — that is the service. What happens to it:
- Processed in memory for that one request, then gone
- Nothing stored, and nothing from the request logged
- No session and no cookie
- The only thing kept is a rate-limit counter under a scrambled form of the caller’s network address, deleted after two days
- Two lookups go to outside services, because they are the check: the recipient address to the sanctions oracle, and a transaction hash to a public blockchain node
Four honest limits
- A signature is not an identity. It proves a link was not altered — a forger signs their own forgery correctly. Tell the agent which signer to expect (
expectedSigner), from somewhere other than the link. - The hosted tools never pay. They hold no key. Your agent’s own wallet signs and sends. A version you run yourself can pay, under a whitelist and spending limits you set in a file — never in a prompt — and it is not published yet.
- Screening blocks when it cannot check. A person sees a warning and decides; an agent has nobody watching, so an unreachable sanctions check stops the payment unless you opt out.
- Not yet: signatures from smart-contract wallets, and reading encrypted links.
Business accounts
An optional yearly plan that keeps your invoices — built so that "keeps" never has to mean "reads".
How the vault works
- You sign in with a free wallet signature — no email, no password
- Includes the Treasury dashboard: your stablecoin balances across every supported network
- A second signature derives your encryption key, on your device
- Invoices are encrypted in the browser (AES‑256‑GCM) before upload
- The same wallet reopens them on any device
- Deleting an item is final: no readable copy ever existed anywhere
What our server can and cannot see
- Can: your wallet address, item sizes, timestamps, plan status
- Cannot: names, amounts, clients, line items, bank details — any invoice content
- Quotas are enforced by counting bytes, never by reading them
- If your plan lapses, saving stops — reading and exporting never do
Get in touch
Questions, bug reports, or something that looks wrong on a payment page — we would rather hear about it.
Or message @StableInvoice_Bot on Telegram.
StableInvoice is powered by Bull Project.