<iframe> on the PeridotID origin; every
trust-critical action — sign-in, send, top-up, transfer — opens a popup on the
PeridotID origin, so the browser address bar stays visible as the unforgeable
trust signal. Nothing that signs or moves money runs in your DOM.
- The iframe announces itself; the wallet shows a Connect button.
- Clicking it opens the PeridotID login popup (Google or passkey). On
return the component exchanges the one-time
pid_codefor a read-only bearer and hands it to the iframe. - The wallet renders, reading identity / profile / balance / activity with that bearer.
- Any write (send, top-up, transfer, activate, register) opens the PeridotID approval popup on the PeridotID origin; the result flows back into the embedded UI.
Register your app first
Create the app withPOST /v1/apps and add the exact origin of the page
that will host the embed to its allowed origins (see
Sign in with PeridotID). Login codes are only
issued to registered origins — an unregistered page cannot obtain a bearer, so
the embed stays inert there.
Why an iframe (not our React in your tree)
WebAuthn binds passkeys to the PeridotID domain (rpId), and the httpOnly
session cookies (pid_access/pid_refresh) are first-party to our origin. A
frame keeps both invariants: the wallet is same-origin with itself, and every
signing ceremony pops out to a top-level window you can verify by its address
bar. Reads inside the frame use a delegated read-only bearer
(scope: "read", GET-only) — writes always return 403 and must go through the
popup.
Deployment: allow the frame
By default the wallet host sends noframe-ancestors allowance for
third-party sites. To enable embeds, the wallet host’s security headers
(Traefik security-headers@file middleware on app.pid.peridotvault.com) must
set:
Notes
env,baseUrl, andpopupBaseUrlmirror the SDK options; omit them in production and the environment preset applies.onIdentityfires after each successful connect (carriespid,profile,credentials— never the bearer).- The read-only bearer lasts 30 days and is non-refreshable; when it expires the user re-connects (one tap if their PeridotID session is alive).