Static HTML Example
A copy-paste integration for a plain HTML site: no framework, no build step, no backend. You can ship this in 5 minutes.
The simplest possible integration. One script tag, one button, a payment modal your customers can use. Good for landing pages, donation pages, simple Gumroad-style checkout flows, or any static site.
What you'll build
A single page with a styled "Pay with sBTC" button. When clicked, a payment modal opens, the customer connects a wallet and pays, and the payment lands in your dashboard. No JavaScript gymnastics, no backend required.
Prerequisites
- A registered account with a wallet address. If you haven't registered yet, follow the Quickstart.
- Your registered Stacks address (starts with
SP...on mainnet orST...on testnet). - A static HTML file you can edit (or any Carrd / Notion / Webflow / etc. site that allows HTML embeds).
Step 1 — The HTML
Save this as index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pay with sBTC</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
background: #0a0b10;
color: #f5f5f0;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.container { text-align: center; max-width: 480px; padding: 2rem; }
h1 { font-size: 2rem; margin-bottom: 1rem; }
p { color: #8a8a8a; margin-bottom: 2rem; }
</style>
</head>
<body>
<div class="container">
<h1>Support the project</h1>
<p>Chip in 0.001 sBTC to keep the lights on.</p>
<!-- 1. Load the SDK once per page -->
<script src="https://sbtc-pay.com/sbtcpay.js" async></script>
<!-- 2. Drop a Pay button anywhere -->
<div
data-sbtcpay="direct"
data-sbtcpay-merchant="SP1234...REPLACE_WITH_YOUR_ADDRESS"
data-sbtcpay-amount="100000"
data-sbtcpay-memo="Thank you!"
data-sbtcpay-label="Pay 0.001 sBTC"
></div>
</div>
</body>
</html>Step 2 — Customize the data attributes
Replace the values on the <div>:
data-sbtcpay-merchant— your Stacks address. Start withSPfor mainnet,STfor testnet.data-sbtcpay-amount— the amount in sats (1 sBTC = 100,000,000 sats).100000= 0.001 sBTC.data-sbtcpay-memo— short description shown to the customer.data-sbtcpay-label— text on the Pay button. Optional; defaults to "Pay with sBTC".
For the testnet version, swap the script src to https://testnet.sbtc-pay.com/sbtcpay.js — the SDK auto-detects which environment to open the widget on based on the script origin.
Step 3 — Preview locally
Open the file in a browser. You'll see:
- A dark page with a styled "Pay 0.001 sBTC" button
- Click the button — a modal opens with the payment widget
- Click "Connect wallet" — Leather or Xverse prompts
- Approve the payment — the widget shows confirmation with TX hash
- Modal auto-closes a couple seconds later
If the modal doesn't open, check the browser console. The most common issue is a typo in the merchant address (wrong network prefix).
Step 4 — Deploy
Because it's just one HTML file, you can host it anywhere:
- GitHub Pages: push to a repo, enable Pages — free
- Netlify drop: drag the folder onto app.netlify.com/drop — free
- Vercel: deploy as a static project — free
- Cloudflare Pages: same idea — free
- Your own server: just
scpthe file
Going from testnet to mainnet
https://testnet.sbtc-pay.com/sbtcpay.js and a testnet Stacks address. Test the full flow with free testnet tokens from the faucet. Swap to the mainnet script URL only when you've seen a successful testnet payment end-to-end.Accepting multiple amounts
Want preset amount buttons? Each one is just another data-sbtcpay div:
<script src="https://sbtc-pay.com/sbtcpay.js" async></script>
<div data-sbtcpay="direct"
data-sbtcpay-merchant="SP1234..."
data-sbtcpay-amount="50000"
data-sbtcpay-label="0.0005 sBTC"></div>
<div data-sbtcpay="direct"
data-sbtcpay-merchant="SP1234..."
data-sbtcpay-amount="100000"
data-sbtcpay-label="0.001 sBTC"></div>
<div data-sbtcpay="direct"
data-sbtcpay-merchant="SP1234..."
data-sbtcpay-amount="500000"
data-sbtcpay-label="0.005 sBTC"></div>Reacting to a successful payment
The widget shows its own success state inside the modal. For a static site, you usually don't need to do anything further. If you want to fire analytics or redirect on success, listen for the sbtcpay:success window event:
<script src="https://sbtc-pay.com/sbtcpay.js" async></script>
<script>
window.addEventListener('sbtcpay:success', (e) => {
// e.detail = { mode, txId, invoiceId? }
console.log('Paid!', e.detail.txId);
// e.g. redirect to a thank-you page
window.location.href = '/thank-you?tx=' + e.detail.txId;
});
</script>
<div data-sbtcpay="direct"
data-sbtcpay-merchant="SP1234..."
data-sbtcpay-amount="100000"></div>For more advanced backend flows (sending a receipt email, updating a database when a payment lands), see Payment Notifications.
Want an inline iframe instead?
If you'd rather the payment widget render inline on the page (no click trigger, no modal), you can still use the raw iframe URL. See Widget URL Parameters for the iframe format.
What's next?
- Swap the direct payment for an invoice widget if you need a specific order ID
- Add a subscription button for recurring billing
- Build a real backend that reacts to payments via webhooks