A transfer request is a URL. The wallet builds the transfer. There is no server.
solana:<recipient>?amount=<amount>&label=...&message=...&memo=...&reference=...
Spec: https://docs.solanapay.com/spec
A transaction request is different. That one is solana:https://... and needs a public HTTPS endpoint (GET for label, POST for a base64 transaction). Skip that if you only want SOL or an SPL token to land on an address.
Traps:
0.5, never .5.encodeURIComponent. Spaces become %20, not +.reference pubkey on the URL, then getSignaturesForAddress(reference).A single static HTML file that builds the same string in the browser, no SDK: https://brewpage.app/public/67pLF7de2V/invoice.html
Check the recipient on an explorer before anyone pays. Not a wallet.
If the file is useful: 0.05 SOL for the file (memo solana-pay-invoice-v1) 0.01 SOL tip (memo solana-pay-tip-v1)
solana:5eTkbrezyM3Jfe7pfbXvH76LxRBwUrF1LPGZXfDaWEKA?amount=0.05&label=Static%20Solana%20Pay%20Invoice&message=solana-pay-invoice-v1&memo=solana-pay-invoice-v1
solana:5eTkbrezyM3Jfe7pfbXvH76LxRBwUrF1LPGZXfDaWEKA?amount=0.01&label=Static%20Solana%20Pay%20Invoice%20tip&message=solana-pay-tip-v1&memo=solana-pay-tip-v1
Open in Phantom or Solflare. Confirm the address starts with 5eTkbrezyM3 before you pay.