PrivyPrivy
Sign in
  • Documentation
Back to Documentation
Digital ID
Get Started
Changelog
Concepts
Guides
    Web IntegrationNative IntegrationCamera and PermissionsPrivy ButtonData DeliveryVerify the JWTEncrypted Identity DataServer CallbackSecurityProduction Readiness
API Reference
powered by Zudoku
Sign in
Guides

Web Integration

Load the session URL in an iframe and receive widget events with window.postMessage.

Load the iframe

Set the iframe src to the session_url from the create-session response. Permit camera access:

Code
<iframe src="{{session_url}}" allow="camera" style="width: 100%; height: 100%; border: 0" ></iframe>

The merchant origin must be in the Privy allowlist.

Receive widget events

The widget sends events with the privy: prefix. The user journey shows the step that sends each event.

EventPayloadCondition
privy:ready{ session_id, state }The widget completed startup. state identifies the current widget step.
privy:success{ session_id, exchange_code, token?, sections? }Verification and consent succeeded.
privy:cancel{ reason }The user canceled or rejected the consent request.
privy:error{ code }The session is blocked, expired, or not permitted for the embedder. The session also expires when the consent confirmation window ends.

Treat the privy:cancel reason value as opaque.

Validate event.origin before you read the payload. This example uses the sandbox widget origin:

Code
window.addEventListener("message", (event) => { if (event.origin !== "https://stg-digitalid.privy.id") return; const { type, payload } = event.data || {}; switch (type) { case "privy:ready": break; case "privy:success": sendExchangeCodeToBackend(payload.exchange_code); break; case "privy:cancel": break; case "privy:error": break; } });

Privy sends data and tokens only to a verified embedder. An unknown host receives { type } without a payload.

Widget events are front-channel notifications for the user interface. They do not query the backend session status.

Shared-data preview

The optional sections field contains populated fields that the user agreed to share:

Code
{ "sections": [ { "section": "my_contact_data", "label": "My Contact Data", "fields": [ { "key": "email", "label": "Email", "value": "user@example.com", "is_verified": true } ] } ] }

Use sections only for a user-interface preview. Get the authoritative data from the exchange endpoint or the server-to-server callback.

Callback

Privy also sends the verified result to the configured merchant callback_url. See Server Callback.

Last modified on October 23, 2026
Session LifecycleNative Integration
On this page
  • Load the iframe
  • Receive widget events
  • Shared-data preview
  • Callback
Javascript
JSON