generateToken() on your server, and the widget itself through onError.
Errors thrown by kyi()
kyi() throws synchronously, before any iframe is created.
Errors thrown by generateToken()
The promise rejects before anything is signed.
Recommended token endpoint responses
Your endpoint is your API, but these responses keep the browser logic simple. The Claim this profile example uses them.
Send
Cache-Control: no-store on all of them.
Errors from the widget (onError)
When the widget reports a problem, the SDK calls onError with an Error whose message is the payload the widget sent (or Unknown error). The drawer stays open, so the member sees the widget’s own message. Use onError for logging and analytics:
Troubleshooting
The drawer opens but stays empty
The drawer opens but stays empty
Your page’s origin probably isn’t on the allow-list. Open the browser console and look for a frame or CSP error. Scheme, host and port must match exactly:
http://localhost:3000 and http://localhost:5173 are different origins. Ask your Bluprynt representative to add the origin. If your own site sets a Content Security Policy, it must allow frame-src https://app.bluprynt.com.The drawer shows an error instead of the flow
The drawer shows an error instead of the flow
The token was probably rejected: it’s expired, signed with the wrong secret, or has the wrong
iss. Mint a new token for each open, check your server clock, and check the partner ID matches the secret. Decode the token to inspect its claims; see Access tokens.A member sees someone else's organization
A member sees someone else's organization
Two people share one
sub. Use a stable, unique internal ID per member, never a shared service ID or an email that can be reassigned.A member's progress is gone
A member's progress is gone
The
sub changed, for example because you switched from email to database ID. Bluprynt stores progress per sub. Keep it stable for the member’s whole lifetime.onClose fires twice, or a second drawer appears
onClose fires twice, or a second drawer appears
Guard against double clicks and hold the widget in one place, as in the example hook. Clear your reference in
onClose. destroy() doesn’t call onClose.Asset verification is locked
Asset verification is locked
KYB isn’t approved yet. The drawer shows “Locked — complete step 1 above to verify your first asset.” KYB review can take time; the member can close and come back.
The address isn't recognised
The address isn't recognised
“We could not read that address on any chain we support.” Check the address and the supported chains.
Next.js: 'window is not defined'
Next.js: 'window is not defined'
kyi() uses the DOM. Call it only in client code, ideally with await import('@bluprynt/kyi-widget-sdk') inside the click handler.