StackPay is a Bitcoin-native payment gateway on Stacks for sBTC, STX, and USDCx. It combines on-chain invoices and payment routes with a merchant-facing Next.js console, Supabase-backed metadata, hosted checkout pages, receipts, and webhook-driven notifications.
The current working MVP supports:
- merchant profile setup tied to a Stacks wallet
- standard invoices created on-chain, then stored in Supabase after confirmation
MultiPaypayment links for reusable fixed-price or suggested-price checkout- a universal QR route that accepts
sBTC,STX, andUSDCx - hosted payment pages
- processor-based payment confirmation
- receipt PDF generation
- Hiro Chainhook ingestion for
invoice-paid - in-app notifications with toast + sound
- dashboard metrics from real merchant invoice/link data
StackPay currently uses:
apps/web: Next.js 14 app router app, route handlers, merchant console, hosted checkoutSupabase: off-chain source of truth for merchants, invoices, payment links, receipts, notifications, and activitypackages/contracts/stackpay: Clarity contracts and testsStacks wallets: merchant identity and contract signing
There is still an apps/api scaffold in the repo, but the active MVP backend now lives in Next.js route handlers under apps/web/app/api.
apps/web: web app, API routes, hosted payment surfacesapps/api: legacy API scaffold, not the active MVP backendpackages/contracts/stackpay: Clarity contracts and testspackages/domain: shared business metadatapackages/integrations: integration/webhook manifestspackages/sdk: SDK scaffoldingpackages/ui: navigation metadata and shared UI configpackages/config: environment and network helperssupabase: Supabase config and migrationsdocs: MVP notes, Chainhook config, integration docs
- Merchant completes profile setup.
- Merchant creates a standard invoice from
/create-invoice. - Wallet submits
architecture.create-invoice. - Chain result returns the on-chain invoice id.
- Only then does StackPay store the invoice in Supabase.
- Customer pays from the hosted invoice page.
- Payment confirmation creates a receipt and notification.
MultiPay is a reusable public payment route.
- it does not expire like a standard invoice
- it uses one currency
- it supports either:
- one fixed amount
- up to 3 suggested amounts
- each customer payment generates a fresh on-chain invoice under the hood
Merchant management:
- create from
/create-invoice - review all created MultiPay routes at
/payment-links
The universal QR route is a permanent public route for flexible real-world payments.
- customers choose asset
- customers choose amount
- the route remains stable
- managed from
/qr-link
The architecture + processor contracts handle:
- canonical invoice ids
- public link ids
- invoice/payment state
- receipt ids
invoice-paidevents for Chainhooks
Supabase stores:
- merchant profiles
- settlement wallet metadata
- invoices and public links for dashboard/querying
- receipts
- activity events
- notifications
- chainhook delivery state
Current payment notifications work like this:
- Hiro Chainhook watches the deployed StackPay
architecturecontract. - On
invoice-paid, Hiro posts to/api/webhooks/chainhooks. - StackPay confirms the invoice/receipt in Supabase.
- A notification row is inserted.
- The header bell and toast update from
NotificationsButton.tsx.
The sample upload file is:
Email notifications are not implemented yet. The current pipeline is in-app only.
Paid invoices can generate receipt PDFs through:
/api/receipts/[receiptId]/pdf- PDF generator lives in
receipt-pdf.ts
Install dependencies:
npm installRun the web app:
npm run devBuild the app:
npm run buildRun contract tests:
npm run test:contractsCopy envs:
cp apps/web/.env.example apps/web/.env.localStart local Supabase:
npm run supabase:startApply migrations:
npm run supabase:db:resetStop local Supabase:
npm run supabase:stopAuthenticate and link:
npx supabase login
npx supabase link --project-ref YOUR_PROJECT_REFPush migrations:
npm run supabase:db:pushIf you switch from local to remote, make sure your remote DB actually has the current unique constraints used by upsert, especially on:
merchant_profiles.wallet_addressmerchant_wallets.wallet_addressinvoices.onchain_invoice_idnotifications.source_keychainhook_events.delivery_key
Important values:
NEXT_PUBLIC_APP_URLNEXT_PUBLIC_STACKS_NETWORKNEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEYNEXT_PUBLIC_STACKPAY_ARCHITECTURE_CONTRACT_IDNEXT_PUBLIC_STACKPAY_PROCESSOR_CONTRACT_IDSTACKPAY_CHAINHOOK_SECRETSTACKPAY_STACKS_API_URL(optional override)
Merchant pages:
/dashboard/create-invoice/invoices/payment-links/qr-link/profile
Hosted/public pages:
/pay/[invoiceId]/pay/link/[slug]
Core API routes:
GET /api/merchant/profilePOST /api/merchant/profileGET /api/invoicesPOST /api/invoicesPOST /api/invoices/confirmGET /api/payment-linksPOST /api/payment-linksPOST /api/payment-links/[paymentLinkId]/chainGET /api/payment-links/public/[slug]POST /api/payment-links/public/[slug]/invoicesPOST /api/payment-links/public/[slug]/invoices/confirmGET /api/qr-linkPOST /api/qr-linkGET /api/notificationsPATCH /api/notificationsPOST /api/webhooks/chainhooks
- The hosted merchant “open” actions now open in a new tab where appropriate.
- Recent dashboard activity is deduped server-side so a single invoice/link does not spam the feed.
- Notification sound is browser-dependent. Browsers may require prior user interaction before audio can play.
docs/stackpay-mvp-blueprint.mddocs/stackpay-supabase-mvp.mddocs/stackpay-chainhook-invoice-paid.json
This SOP outlines the steps to create and manage invoices using the StackPay Bitcoin payment gateway.
1. Connect Your Wallet 0:42
- Log in to your StackPay dashboard.
- Navigate to the wallet connection section.
- Select your wallet and confirm the connection.
2. Set Up Your Profile 1:03
- Go to the profile settings.
- Enter your business name (e.g., Samuel Ventures).
- Set your display name (e.g., Sammy).
- Provide your invoice email address.
- Save your profile settings.
3. Create an Invoice 1:33
- Click on the 'Create Invoice' button.
- Choose the type of payment (Standard or Multi-Pay).
- For a Standard Invoice:
- Enter the amount (e.g., 1 USDC).
- Specify the customer’s email (e.g., Matt.searchme.com).
- Set an expiration date for the invoice.
- Describe the purpose of the payment (e.g., ebook).
- Click 'Generate Invoice' to create it.
4. Share the Invoice 2:37
- After generating the invoice, you can view it.
- Copy the invoice link to share with the customer.
5. Confirm Payment 3:07
- Once the customer pays, return to your dashboard.
- Check for payment notifications.
- Open the notification to confirm the payment has been received.
6. Download Receipt 3:33
- Navigate to the receipts section.
- Find the relevant receipt for the completed transaction.
- Download or print the receipt as needed.
7. Withdraw Funds 4:08
- Go to the funds withdrawal section.
- Specify the amount you wish to withdraw.
- Confirm the withdrawal request.
8. Access QR Code 4:37
- Locate the universal QR code in your dashboard.
- Click on it to view or share.
- Ensure that all wallet connections are secure to prevent unauthorized access.
- Double-check customer email addresses before sending invoices to avoid payment issues.
- Regularly update your profile information to ensure accurate invoicing.
- Use the Multi-Pay option for recurring customers to simplify payment processes.
- Keep track of invoice expiration dates to manage follow-ups effectively.