Integration walkthrough
Wire up a hosted checkout end to end. Your server holds the API key and creates payment requests; the browser only ever sees a one-time address and amount.
Checkout flow#
The pieces and how they talk to each other:
Customer Your server Dynamic-wallet API
| | |
| start checkout | |
|-------------------->| POST /v1/BTC/payment-request|
| |----------------------------->|
| | address + amount |
| |<-----------------------------|
| address + QR | |
|<--------------------| |
| pays on-chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~> (blockchain)
| | GET /payments (poll) |
| |----------------------------->|
| | status: paid |
| "confirmed" |<-----------------------------|
|<--------------------| |The API key never leaves your server. The browser talks only to your server, which proxies the two calls it needs.
Server: create the payment#
When the customer starts checkout, mint a unique external_id (prefixed with your account prefix) and create the request. Return only the address and amount to the browser.
// POST /api/create-payment
const external_id = `${PREFIX}-${orderId}-${crypto.randomUUID().slice(0, 8)}`;
const res = await fetch(`${API_BASE}/v1/${currency}/payment-request`, {
method: "POST",
headers: {
"x-api-key": process.env.API_KEY, // stays server-side
"Content-Type": "application/json",
},
body: JSON.stringify({ external_id, amount }),
});
const { data } = await res.json();
// -> { address, amount, currency, external_id }
return { external_id, address: data.address, amount: data.amount };Client: show the pay screen#
Render the returned address, the exact amount, and a QR code the customer can scan from a wallet app. Add a countdown so the checkout expires cleanly.
const { address, amount, external_id } = await startCheckout(currency);
showAddress(address);
showAmount(amount, currency);
showQr(`${currency.toLowerCase()}:${address}?amount=${amount}`);
startCountdown(15 * 60); // 15 min
pollStatus(external_id);Confirm the payment#
Poll your own status endpoint every few seconds; it checks GET /payments for a matching external_id with a paid status, then flips the checkout to a success screen.
// GET /api/status?external_id=...
const res = await fetch(`${API_BASE}/payments`, {
headers: { "x-api-key": process.env.API_KEY },
});
const { data } = await res.json();
const match = data.find((p) => p.external_id === external_id);
return { status: match?.status ?? "pending", txid: match?.txid };async function pollStatus(external_id) {
const t = setInterval(async () => {
const { status } = await fetch(
`/api/status?external_id=${external_id}`
).then((r) => r.json());
if (status === "paid") {
clearInterval(t);
showSuccess();
}
}, 4000);
}