Stablecoin Checkout docs
v1.0.0
Live demoOperator console demo Get help
● Set up · Your merchants

Merchants
portal, API and webhooks.

What your merchants get: a portal to take payments without code, an API to create invoices from their own shop, and signed webhooks that tell their backend when an order is paid.

01Which portal

AppStatus in 1.0.0
apps/portal (merchant portal)The full portal described on this page. Runs on the public demo at /portal/ (built with VITE_BASE=/portal/). Not verified The shipped Caddyfile and pnpm run build:web do not build or route it yet; to serve it in production you add it yourself (build @mikodes-checkout/portal and serve apps/portal/dist under /portal/ on the admin domain).
apps/admin (interim merchant portal)What the shipped Caddyfile serves on the admin domain. Merchants sign in with their API key (an operator key is refused and never stored).

02The merchant portal

ScreenWhat the merchant does
HomeReceived today, fees, fee credit, live payments and quick actions.
Payments, RefundsEvery payment with on-chain evidence and timeline; refunds signed in the merchant's own wallet (Solana wallet adapter or an EIP-1193 wallet on Base), or sent to the customer as a claim link.
Payment linksReusable links with QR code, an embed.js website button, stats and payments.
InvoicesCustomer invoices with a live paper preview: send, void, PDF.
SubscriptionsRecurring billing: pause, resume, cancel, history.
Point of saleKeypad, QR and live status for in-person sales; a cashier role lands here.
Fee creditBalance, fee and tiers, top-ups and automatic top-up.
Webhooks, DevelopersEndpoint, test event, deliveries with payload and retry; API key and webhook secret (shown once), copy-paste code in cURL, Node.js and PHP.
Team, Security, Notifications, ReferralInvites and roles; two-factor (TOTP), recovery codes, sessions, password; Telegram and e-mail notifications; the merchant's referral link.

The portal is in English and Slovak, light and dark.

Merchant portal payment links
Payment links (test merchant, devnet).
Point of sale on a phone
Point of sale
Console merchant page: settled volume for the last 30 days, payment count, conversion, the fee for this merchant, payout setup and webhook URL
One merchant in the console: their settled volume, the fee that applies to them, payout and webhook setup. Figures are from a local test merchant.

03Create an invoice from a shop

The merchant's backend calls the API with its key (sk_live_…, kept in its own environment as MERCHANT_API_KEY). Amounts are decimal strings, never floats.

curl -s -X POST https://pay.example.com/v1/invoices \
  -H "Authorization: Bearer $MERCHANT_API_KEY" -H 'content-type: application/json' \
  -d '{"amount":"25.00","asset":"USDC","chain":"solana-mainnet","orderId":"1042","redirectUrl":"https://shop.example/thanks"}'

The response is the invoice with its id and checkoutUrl (<PUBLIC_CHECKOUT_URL>/pay/<id>). Send the customer there. Optional fields: orderId, description, redirectUrl, expiresInSec. Other merchant routes: GET /v1/invoices/:id, GET /v1/invoices, GET /v1/webhook-deliveries. Full reference: docs/CONTRACT.md and docs/CONTRACT-ADMIN.md in the package.

Developers page with API key, webhook secret and code samples
Developers page: copy-paste code for cURL, Node.js and PHP.

04Invoice statuses

StatusMeaning
pendingWaiting for payment.
confirmingA transaction was seen; waiting for finality. A seen transaction keeps the invoice confirming past its expiry.
paidSettled. Wallet pay needs both legs (merchant amount and fee).
underpaid, overpaidThe amount differs. Decided only on finality; go to review, never paid out automatically.
expiredNothing was seen before the expiry. Expired invoices are watched 24 hours more, so a late payment is still recorded.
flaggedThe payer matched the sanctions list. Terminal; no fee credit is debited (what to do).

05Signed webhooks

For each status change the server sends POST to the merchant's webhook URL with events invoice.confirming, invoice.paid, invoice.underpaid, invoice.overpaid, invoice.expired, invoice.flagged (and webhook.test from the test button). Header:

Mikodes-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
  • Verify the signature over the raw body with the merchant's webhook secret, and compare in constant time.
  • Deduplicate on event.id (also in the header Mikodes-Event-Id). Replays are safe.
  • Retries at 10 s, 30 s, 1 min, 5 min, 15 min, 1 h and 3 h; after 8 attempts the delivery is a dead letter (both configurable in the console). Every attempt is stored.
  • Deliveries to private, loopback, link-local and metadata addresses are refused (SSRF protection).

06What the customer sees

The checkout shows the exact amount, a countdown, a QR code, wallet pay (Phantom, Solflare and other Solana wallets; MetaMask, Rabby, Coinbase Wallet on Base), exchange pay with per-exchange guidance for Binance, OKX and Bybit, live confirmation, and a public status page with on-chain evidence. English and Slovak, light and dark. Underpaid and overpaid invoices go to review.

Checkout on desktop with wallet pay
Checkout, wallet pay (devnet demo store).