Integration guide
Hosted verification
Let Wristband display the QR code and wallet controls.
Have dashboard access? In Overview, select your check and wallets, then copy the curl, Node, PHP or HTML snippet. The test dashboard requires an issued account.
1. Prepare your checkout
You need a server runtime, a TEST key and an exact registered HTTPS return URL. Keep a server-side attempt record tied to the visitor’s secure checkout cookie: session ID, reference and expiry. Authenticate the visitor’s checkout and protect the start endpoint against CSRF and repeated clicks.
2. Create the check on your server
This is a Node.js excerpt inside your authenticated checkout handler. reference is a new opaque attempt ID. Validate your environment variables at startup.
const api = process.env.WRISTBAND_API_URL;
const secret = process.env.WRISTBAND_SECRET_KEY;
const returnUrl = process.env.WRISTBAND_RETURN_URL;
const response = await fetch(api + '/v1/sessions', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + secret,
'Content-Type': 'application/json',
},
body: JSON.stringify({
scopes: ['age_over_18'], reference,
redirect_uri: returnUrl,
}),
cache: 'no-store',
redirect: 'error',
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) throw new Error('Check unavailable');
const session = await response.json();Validate the returned session ID, reference, expiry and URL. The hosted URL must use your configured API origin and the expected session path. Save the attempt before sending a 303 redirect to session.url. Do not accept a destination from the visitor.
3. Let the hosted page handle the wallet
Desktop visitors scan the QR with their phone. Mobile visitors tap to open a compatible wallet. The hosted page handles the wallet callback and device binding. On a phone the visitor needs to return in the same browser context. Do not copy device keys or callback codes yourself.
4. Read the answer after returning
Look up the attempt using your checkout cookie. Ignore any client claim that the check succeeded. Read the session from your server:
const response = await fetch(
api + '/v1/sessions/' + encodeURIComponent(attempt.sessionId),
{
headers: { Authorization: 'Bearer ' + secret },
cache: 'no-store',
redirect: 'error',
signal: AbortSignal.timeout(10_000),
},
);
if (!response.ok) throw new Error('Result unavailable');
const outcome = await response.json();Apply the status and receipt checks. Pending means wait and read the same session again, with backoff on 429. For this TEST integration show a demo result only. In a live integration, finish the transaction atomically against the saved successful attempt so repeated returns cannot issue two tickets.
5. Test the whole trip
- Desktop Safari: start, scan with an iPhone, confirm and check the desktop result.
- Mobile Safari on iPhone: start, open the wallet, confirm, return and refresh.
- Let a check expire. It must not produce a successful result.
- Try a second browser without the original checkout cookie. It must not inherit the first browser’s approval.
- Double-click start and revisit the return page. Neither should create another ticket.
Prefer a QR inside your own page? Follow the Next.js tutorial.