Appearance
Embed onboarding
Run Zay's onboarding inside an <iframe> on your own page, instead of redirecting the user away.
We recommend the redirect — see Onboard a user. Embed only if keeping the user on your page matters more than the extra work below. Everything else — the URL, the webhook you wait for, what to do when a user doesn't finish — is the same in both.
Requirements
| Requirement | Description |
|---|---|
| A user | Created with Create user — you need their onboarding_url |
| A webhook endpoint | Registered and receiving events — see Get started, steps 2–3 |
| An HTTPS page | The page that hosts the frame. Camera access only works on a secure origin |
How it works
1. Add the frame
Point the frame at the user's onboarding_url. Identity verification needs the camera and microphone, so delegate both to the frame — without allow, the browser blocks them inside it and the user cannot finish:
html
<iframe
src="https://privy-stag.zay.me/onboarding?merchant_id=YOUR_MERCHANT_ID&user_id=USER_ID"
allow="camera; microphone"
title="Zay onboarding"
style="border: 0; width: 100%; min-height: 720px;"
></iframe>- Give the frame the full width of your content column and at least about 720px of height — the identity-verification step is a full screen of its own.
- Don't add a
sandboxattribute: the onboarding opens its own sign-in and verification frames and needs scripts, forms and popups. callback_urlis ignored inside a frame. Use the message in the next step instead.
2. Listen for the end of the flow
When the user reaches the end of the web flow, the frame posts a message to your page:
json
{
"type": "zay:onboarding",
"status": "card_is_ready",
"step_data": {}
}Listen for it, and check that it comes from Zay's host:
javascript
const ZAY_ORIGIN = "https://privy-stag.zay.me"; // https://privy.zay.me in production
window.addEventListener("message", (event) => {
if (event.origin !== ZAY_ORIGIN) return;
if (event.data?.type !== "zay:onboarding") return;
// The user is done with the frame: close it, or show your next screen.
showOnboardingFinished(event.data.status);
});status says where the user left off — for example card_is_ready, card_issuing_failed, kyc_declined or residence_country_waitlisted — so you can choose what to show. The message is sent once per page load, when there is nothing left for the user to do in the frame: usually after their card is issued and activated, a few minutes after they submit identity verification.
The message does not mean the user can be paid. Don't decide anything from it.
3. Wait until the user can be paid
Exactly as with the redirect: when the user's card is ready to spend, Zay sends user.onboarding_completed to your webhook endpoint, with the wallet_address to pay. See Onboard a user.
Related
- Onboard a user — the recommended redirect flow, and what to do when a user doesn't finish
- How onboarding works — the steps, the events and account states