Step 2
Embed the widget
The widget is a plain iframe. Fetch a fresh token from your own backend at the moment the customer opens the flow, then set it as the frame's source:
html
<iframe
id="kvarnpay"
title="KvarnPay"
allow="camera; payment"
style="width: min(33rem, 100%); height: 42rem; border: 0"
></iframe>
<button onclick="openKvarnPay()">Buy crypto</button>
<script>
async function openKvarnPay() {
const res = await fetch('/kvarnpay/token', { method: 'POST' });
const { merchantToken } = await res.json();
document.getElementById('kvarnpay').src =
'https://staging.pay.kvarnx.com/#token=' +
encodeURIComponent(merchantToken);
}
</script>Mint the token on demand, not when the page renders. A token lives ten minutes. If you sign one into the HTML of a page a customer leaves open, it will have expired by the time they click Pay, and the widget will fail to open a session.
Why the fragment, and not a query parameter
The token goes after the #. A fragment is never sent to any server — not to ours, not to a CDN in front of it — so the token stays out of every request log on the way. A query parameter would be written to all of them. The widget reads the token as its first act and immediately rewrites its own address without it, so a spent token is not left sitting in the frame's history entry either.
Sizing
width: min(33rem, 100%) and height: 42rem are the dimensions the widget's layout is designed against: wide enough for the card payment and document capture steps, and tall enough that the amount screen fits without scrolling. Narrower or shorter works — the widget is responsive — but it will scroll inside your frame.
Careful
The allow attribute is required, and its contents are not decorative. camera is what the identity check needs to capture the customer's document; payment lets the card step use the browser's built-in payment features. An iframe does not inherit these permissions from your page — without the attribute, those steps simply fail inside your product, and they fail late, after the customer has already committed to an amount.