Skip to content

Onboard a user ​

Send a user to Zay's onboarding, bring them back to your product, and know when you can pay them.

Want onboarding inside your own page instead of a redirect? See Embed onboarding.

Requirements ​

RequirementDescription
A userCreated with Create user — you need their onboarding_url
A webhook endpointRegistered and receiving events — see Get started, steps 2–3
A return pageA URL in your product where the user lands afterwards

How it works ​

  1. Take the user's onboarding_url
  2. Add your callback_url
  3. Redirect the user
  4. Handle the user coming back
  5. Wait until the user can be paid

1. Take the onboarding URL ​

Every User object carries the onboarding URL for that user in onboarding_url. Take it from the Create user response rather than building it yourself:

https://privy-stag.zay.me/onboarding?merchant_id=<merchant_id>&user_id=<user_id>

Onboarding is served from Zay's own host — privy-stag.zay.me on staging, privy.zay.me in production — not from the Merchant API's.

The URL is not a secret. Security rests on the one-time code the user enters during onboarding, not on the URL — a merchant_id / user_id pair alone cannot complete onboarding for someone. The user's phone_number and email are pre-filled, so they don't retype them.

2. Add your callback URL ​

Append callback_url — where Zay sends the user back once they're done — URL-encoded:

https://privy-stag.zay.me/onboarding?merchant_id=<merchant_id>&user_id=<user_id>&callback_url=https%3A%2F%2Fexample.com%2Fzay%2Fdone

https URLs and custom app deep-link schemes (yourapp://…) are accepted. javascript:, data:, vbscript: and file: URLs are ignored.

3. Redirect the user ​

Send the user's browser to the URL — a link, a button, or an HTTP 302 from your server:

html
<a href="https://privy-stag.zay.me/onboarding?merchant_id=…&user_id=…&callback_url=…">
  Set up your Zay wallet
</a>

The user verifies their phone and email, picks their country, and completes identity verification. Allow a few minutes.

4. Handle the user coming back ​

When the user reaches the end of the web flow, Zay sends them to your callback_url with a status query parameter:

https://example.com/zay/done?status=card_is_ready

status says where the user left off, so you can choose what to show them — for example card_is_ready (the card is issued and activated), card_issuing_failed, kyc_declined or residence_country_waitlisted.

Coming back does not mean the user can be paid. The user usually returns once their card is issued and activated, but status is a hint for your screen, not a verdict. Don't decide anything from it. Wait for the webhook in the next step.

5. Wait until the user can be paid ​

Don't poll. When the user's card is ready to spend, Zay sends user.onboarding_completed, carrying the wallet_address to pay. From that moment you can report payouts for them.

json
{
  "type": "user.onboarding_completed",
  "data": {
    "user_id": "2c9596e6-7c48-4fe9-b957-738bd2e04adc",
    "wallet_address": "0x742d35cc6634c0532925a3b844bc9e7595f0beb7"
  }
}

If the user doesn't finish ​

  • They left halfway. Send them to the same onboarding_url again. They sign in with their phone and continue where they stopped.
  • Verification needs another try. You receive nothing: onboarding asks the user to fix what was refused, and they continue from there. If they left, send them to the same onboarding_url again.
  • Verification was declined. You receive user.onboarding_failed with a reason. The user cannot continue; if the reason is region_not_supported, offer them another way to be paid.
  • You never hear back. A user who stops stays in account_state onboarding; read it with Retrieve user.