Iframe integration
Embedding the verification UI and handling postMessage events.
The iframe is a self-contained verification UI hosted on the platform
domain. Your frontend embeds it and listens to postMessage events for
real-time updates.
Embedding
The session_id and token come from POST /v1/sessions. Both are required
— the iframe will refuse to initialize without them.
Event envelope
Every postMessage event uses a fixed envelope:
Event types
| Type | When it fires |
|---|---|
kyc.ready | Iframe has initialized and validated the SDK token. |
kyc.status_changed | A step advances (document_upload → liveness, etc.). |
kyc.resize | Iframe content height changed — adjust your host element. |
kyc.completed | Terminal success. The verification is saved. |
kyc.error | Terminal failure with a machine-readable code. |
kyc.canceled | User or parent aborted the flow. |
Always validate event.origin
Only accept messages whose origin matches your configured iframe origin.
Drop everything else.
Parent → iframe commands
You can send commands to the iframe from the parent window:
kyc.configure— set theme (light/dark) and locale.kyc.cancel— cancel the current flow cleanly.
Session resume after a page refresh is automatic — the iframe fetches the current snapshot on initialization and renders the correct screen. There is no explicit resume command.
All commands use the same envelope shape as iframe → parent events.
Image uploads (under the hood)
You don't see this from the parent — it's worth knowing it exists.
Before any document or selfie body is sent to /v1/iframe/upload, the
iframe normalizes the image in the browser:
- EXIF orientation is baked into pixels via
createImageBitmap(file, { imageOrientation: 'from-image' }). Several downstream face providers (AWS Rekognition included) do not auto-rotate based on the EXIF tag, so a portrait iPhone capture would otherwise arrive sideways and fail face detection. - Resized to 2048px on the longest side. Raw mobile captures are often 4032×3024 and >3MB — downscaling shaves bandwidth and keeps face detection focused on the subject rather than searching a 12MP frame.
- Re-encoded as JPEG at quality 0.92. This also strips all EXIF data (no GPS coordinates, device identifiers, or capture timestamps leave the browser).
- Fail-open. If the browser cannot decode the file or the canvas context is unavailable, the original bytes are uploaded as-is so the flow keeps working.
This is invisible to the parent integration and requires no configuration on your end.
Mobile camera handoff
Desktop sessions can hand the applicant off to a mobile device for the
capture steps. The desktop iframe surfaces a QR code linking to a
hosted mobile page; the mobile page consumes a one-time capability
token (hof_...) via POST /v1/hosted/claim and is issued a
short-lived mobile SDK token scoped to the same session_id. The
desktop iframe polls for state and renders progress in real time. No
parent action is needed — the events stream through the existing
postMessage channel as if the desktop did the capture.