Checkout
Use hosted Checkout for stablecoin payments: create a session on your backend, then redirect the payer to the payment page.
Checkout is for flows where you want less frontend integration work: your backend creates a Checkout Session, then redirects the payer to the StableOps-hosted payment page. The hosted page shows chain, asset, receiving address, and order status. Your integration only needs to create sessions and handle webhooks; you do not have to build the payment UI yourself.
How to use it
- Create a Checkout Session on your backend: call
stableops.checkoutSessions.createwith your API key, merchant order ID, amount, accepted assets, display title, success URL, cancel URL, and optional WalletConnect project ID. - Redirect the payer to Checkout: after creation, issue a 303 redirect to
checkout.url, or return the URL to your frontend and callwindow.location.assign(checkout.url). - Let the payer complete the transfer: the hosted page shows the chain, asset, exact amount, and receiving address, and tracks status live. The payer can pay via browser wallet, mobile wallet, or manual transfer (see Supported payment methods below). Scanners match the deposit either way.
- Complete business logic from webhooks: receive and verify
payment.confirmed/payment.finalizedwebhook events, then provision service, post ledger entries, or update your order. Do not rely onsuccessUrlalone; it is a browser return path, not final payment proof.
You can control the hosted Checkout language by adding lang to the URL, for example ?client_secret=...&lang=es. Supported values are en, zh, zh-Hant, es, pt-BR, vi, id, and ja. If lang is omitted, Checkout matches the payer's browser language when possible and falls back to English.
Supported payment methods
Checkout supports the following three payment methods; users can choose freely based on their environment.
Browser wallet (desktop)
The page auto-detects injected wallet providers and connects on selection. The user confirms the transaction in their wallet to send.
- EVM chains: MetaMask, Rabby, or any wallet injecting
window.ethereum. 12 chains supported. - Solana: Phantom or any wallet injecting
window.phantom.solana. Mainnet + devnet. - TRON: TronLink or any wallet injecting
window.tronLink.tronWeb. Mainnet + Nile.
Mobile wallet (WalletConnect)
Requires walletConnectProjectId when creating the session. Checkout shows a wallet list; the payer picks one and connects via WalletConnect QR code or deep link to sign the transaction. Supports EVM, Solana, and TRON chains — for TRON, the wallet signs the transfer over WalletConnect and Checkout broadcasts it on-chain.
Compatible wallets: MetaMask, Trust Wallet, Coinbase Wallet, OKX, Binance Wallet, TokenPocket, TronLink, Rainbow, Zerion, Ledger Live, and any WalletConnect-compatible wallet. Checkout filters the list by the order's chain families; TRON orders show the TRON-capable wallets: Trust Wallet, TokenPocket, TronLink.
Solana and TRON wallet payments need an RPC node to build and broadcast the transfer, and Checkout handles this for you: mainnet orders are forwarded through StableOps' backend RPC proxy, while testnet orders (Solana Devnet, TRON Nile) connect directly to public RPC nodes — free but occasionally rate-limited; if a testnet payment fails to build, wait a moment and retry.
Manual transfer
Always available. The payer copies the receiving address from the page and sends from any wallet or exchange. Scanners match the deposit by address.
Create a session on the backend
import { StableOps } from '@stableops/api-sdk'
const stableops = new StableOps({
apiKey: process.env.STABLEOPS_API_KEY!,
})
const merchantOrderId = 'order_123'
const checkout = await stableops.checkoutSessions.create(
{
merchantOrderId,
amount: '49.00',
amountMode: 'auto',
acceptedAssets: [{ chain: 'base-sepolia', asset: 'USDC' }],
expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(),
title: 'StableOps Starter Plan',
successUrl: `https://stableops.dev?result=success&orderId=${merchantOrderId}`,
cancelUrl: `https://stableops.dev?result=canceled&orderId=${merchantOrderId}`,
walletConnectProjectId: process.env.WALLETCONNECT_PROJECT_ID,
},
{ idempotencyKey: 'order_123' },
)
return Response.redirect(checkout.url!, 303)Parameter guidance
merchantOrderId: use your internal order ID, and reuse it as the idempotency key to avoid duplicate sessions.amountMode: 'auto': lets StableOps adjust the amount slightly to reduce collisions on shared receiving addresses.acceptedAssets: start with testnet assets, then switch to the production chains you actually support.successUrl/cancelUrl: browser return paths only. Treat webhooks as the source of truth for payment state.walletConnectProjectId: optional. Register a free project ID in Reown Cloud. When present, Checkout shows a mobile wallet entry; EVM, Solana, and TRON chains all connect via WalletConnect QR code or deep link to sign the transaction:- EVM and Solana chains: MetaMask, Trust Wallet, Coinbase, OKX, Binance Wallet, Rainbow, Zerion, Ledger Live, and generic WalletConnect.
- TRON chains: Trust Wallet, TokenPocket, TronLink. The wallet signs the transfer over WalletConnect and Checkout broadcasts it on-chain.
- When omitted, no mobile wallet entries are shown (EVM / Solana / TRON alike); payers can still use an injected browser wallet or manual transfer.
metadata: include plan, user ID, or internal labels. The public Checkout page does not expose order metadata.
Online testing
The panel below uses your sandbox API key directly in the browser to create a Checkout Session, then redirects to the public Checkout page. You can customize merchant order ID, amount, title, description, return URLs, and order metadata to see how merchant parameters appear in the payment flow.
Use a sandbox key. It stays in your browser and is sent directly to the API. In production, call the API from your backend, not the browser.
When on, a deterministic burner sandbox address is imported for this order before the session is created. Useful when your org has no addresses yet. Turn it off to use only the addresses you manage yourself.
Security notes
- This panel is for sandbox testing only. In production, create Checkout Sessions on your backend and never expose a live API key in the browser.
- The
clientSecretopens the public payment page and should only be sent to the current payer. - The Checkout page reads only the public session. It does not require Clerk sign-in and does not expose order metadata.
Handle the webhook
Checkout settles through the same payment orders as the SDK flow, so payment state always arrives over webhooks — never trust the successUrl redirect alone.
- Webhooks — event types, payload shape, and delivery/retry behavior.
- Verify webhook signatures — validate
X-Product-Signaturebefore parsing the body. - Webhook troubleshooting — debugging missed or failing deliveries.
How is this guide?
Last updated