ONP Embed Integration
This document describes how to embed the Guardline onboarding experience directly within your application using an iframe. The embedded mode allows your users to complete identity verification without leaving your interface.
The embedded mode and the direct link mode share the same backend, decision engine, and verification providers. The only differences are the entry point (iframe src versus full-page navigation) and the presence of a PostMessage channel for real-time communication with the host page. For everything that is not iframe-specific, refer to the ONP API Reference.
This page focuses on what is specific to iframe embedding: iframe attributes and required permissions, the embed mode flag (surface_hint=embed), PostMessage events, browser compatibility, and security concerns specific to a cross-origin iframe context.
Design Principles
Section titled “Design Principles”Four principles guide the embedded integration:
- Transparency for the end user: The onboarding must feel like a native part of the integrator’s application. The user should not perceive that they are interacting with an external system. Visual identity (colors, logos, text overrides) is fully configurable per flow and is managed by the Guardline backend, not by URL parameters or client-side code.
- Security by default: The iframe operates in a cross-origin context, meaning the integrator’s site and the Guardline onboarding run on different domains. All communication between the two uses secure channels: PostMessage with strict origin validation, webhooks with HMAC-SHA256 signatures. Session tokens are ephemeral, cryptographically secure, and bound to a single execution.
- Backend as the source of truth: All persistent information (session state, collected data, verification results, visual configuration) lives in the Guardline backend. The iframe frontend does not maintain state that cannot be reconstructed from the backend. This ensures sessions can be resumed even if the iframe is destroyed and recreated.
- Same infrastructure, two entry points: The embedded mode and the direct link mode share the entire stack. The frontend automatically detects whether it is running inside an iframe and activates the PostMessage channel accordingly. No separate configuration is needed.
Integration Flow
Section titled “Integration Flow”The embedded onboarding involves four participants communicating in sequence: the integrator’s backend, the Guardline API, the integrator’s frontend, and the Guardline iframe.
The process starts when the integrator’s backend creates a session. It calls POST /api/v1/onboarding/sessions with surface_hint: "embed" to enable PII sanitization on the resolver. The API returns the token, execution ID, and the embed_url that the integrator’s frontend uses as the iframe src.
The iframe loads, resolves the token via GET /api/v1/link/{token}, and receives everything it needs to render the onboarding: flow configuration, visual identity, and (sanitized) customer data. The user navigates through steps; each completed step is persisted to the backend. The iframe sends PostMessage events to the host page reporting progress.
When the last step is completed, the backend automatically runs the decision engine. The iframe communicates the conclusion to the host page via PostMessage, and the backend fires a webhook to the integrator’s backend with the result.
Creating a Session for Embed Mode
Section titled “Creating a Session for Embed Mode”Session creation is the same POST /api/v1/onboarding/sessions endpoint used for direct-link mode. See Creating a Session for the full request schema and response contract.
The only embed-specific difference is the surface_hint field on the request:
{ "flow_type": "kyc", "surface_hint": "embed", "primary": { "full_name": "Maria Santos", "tax_id": "12345678900" }}When surface_hint: "embed" is set:
- The session is flagged as embed-mode at creation time.
GET /api/v1/link/{token}returns a sanitized payload that strips PII fields the iframe must not display (CPF, email, phone, birth_date, representative URLs).- The flag is server-internal and is not echoed in any response. Integrators observe its effect through the sanitized shape of the resolver response.
For the full sanitization behavior, see PII Sanitization Behavior on the API reference.
The embed_url field in the session response is the canonical URL to mount in the iframe. It points to the same execution as url (the direct-link entry point). Both URLs resolve through the same GET /api/v1/link/{token} endpoint server-side; the difference is which front-end shell the user lands on.
For authentication (X-API-Key), idempotency (Idempotency-Key), error responses, and the full request/response schema, see the ONP API Reference.
Embedding the Iframe
Section titled “Embedding the Iframe”The integrator’s frontend embeds the onboarding by mounting an iframe element pointing to the embed_url returned by the session creation endpoint.
The embed_url is returned without a query string, and in that form it emits no PostMessage events. The PostMessage bridge stays inert until the iframe is given a valid parent origin, which it reads from an origin query parameter on its own URL. Append ?origin=<your page origin> to the embed_url before mounting it, where the origin is the exact scheme, host and port of the page hosting the iframe (for example https://app.acme.com, or https://app.acme.com:8443 when a non-default port is used). The iframe falls back to the document referrer when the parameter is absent, which is not reliable and is suppressed by common referrer policies. Set the parameter explicitly. The origin must also be present in the allowed origins configured for your instance.
Required Attributes
Section titled “Required Attributes”The iframe requires explicit permission declarations to function correctly. Without these, the browser silently blocks access to the camera and motion sensors, and the onboarding cannot proceed past biometric verification.
| Attribute | Value | Purpose |
|---|---|---|
src | embed_url from the session creation response, with ?origin= appended | Points to the Guardline onboarding for this session. The origin parameter is required: without it the iframe emits no PostMessage events. |
allow | camera; geolocation; accelerometer; gyroscope; magnetometer | Camera is required for document capture and biometric verification. Motion sensors are required on mobile devices for liveness detection. Geolocation lets the terms screen record the acceptance location as consent evidence; the end user may decline the browser prompt without blocking the journey. |
width | 100% | The onboarding layout is responsive and adapts to the container width. |
height | 100% of viewport or fixed value (minimum 600px) | The layout is designed to occupy the full height of its container. |
Attributes to Avoid
Section titled “Attributes to Avoid”The sandbox attribute must not be used. It restricts iframe capabilities (forms, scripts, popups, camera access) in ways that make the onboarding inoperable.
Sizing
Section titled “Sizing”The iframe height should be set by the integrator with a fixed value, typically 100% of the viewport. The onboarding layout is designed to fill the entire container.
Automatic height resizing based on content is available via the height-changed PostMessage event. The iframe reports its content height as it changes, throttled to a minimum interval of 200 ms, so the host page receives at most five height updates per second and should treat each value as the latest known height rather than a continuous stream. The host page can adjust the iframe element accordingly. This approach is optional and works best for layouts where the iframe is not full-viewport.
Example
Section titled “Example”<iframe src="https://acme.onp.prod.guardline.com.br/embed/t/abc123def456?origin=https://app.acme.com" allow="camera; geolocation; accelerometer; gyroscope; magnetometer" width="100%" height="100vh" style="border: none;"></iframe>Token in URL: Leakage Mitigations
Section titled “Token in URL: Leakage Mitigations”The session token is present in the iframe URL path. This is a deliberate trade-off: it allows stateless embedding without requiring the host page to inject credentials via PostMessage before the iframe can initialize. The following mitigations limit the exposure surface:
| Leakage Vector | Mitigation |
|---|---|
| Referer header | The embedded document does not set Referrer-Policy, so the browser default applies. Current browsers default to strict-origin-when-cross-origin, under which outbound requests from the iframe (to verification providers, CDNs) send only the origin (https://acme.onp.prod.guardline.com.br) and never the full path containing the token. A browser configured with a more permissive policy would send more. |
| Browser history | The token URL is loaded inside an iframe, not in the top-level navigation bar. Iframe navigations are not recorded in the browser’s address bar or history. |
| Analytics and third-party scripts | The onboarding frontend does not include generic third-party analytics scripts. Provider SDKs are loaded only for verification purposes, and Guardline does not forward token values as analytics identifiers. |
| Integrator logs | The integrator should treat the embed_url and token fields from the session creation response as sensitive data. Avoid logging these values in plain text. The execution_id is the safe identifier for logging and correlation. |
Visual Configuration
Section titled “Visual Configuration”The visual identity of the onboarding is entirely dynamic and managed by the Guardline backend. No visual parameters are passed via URL, query strings, or client-side code.
When the iframe resolves the session token, the backend returns the complete visual configuration associated with the flow:
| Setting | Description |
|---|---|
| Primary and secondary colors | In dark and light variants, used for buttons, accents, and interactive elements. |
| Logo URLs | Hosted on CDN, in versions for dark and light backgrounds. |
| Theme mode | Dark, light, or automatic (follows the user’s system preference). |
| Button styling | Background, text, and icon colors per theme. |
| Per-step overrides | Individual steps can override base colors and layout settings. |
The frontend applies these settings as CSS custom properties at render time. Changing the visual identity does not require code changes or redeployment: update the settings in the Guardline admin panel or via API, and the next session will reflect the new configuration.
This design ensures visual consistency between the direct link mode and the embedded mode. Both use the same configuration source (the backend), so the integrator does not need to synchronize visual parameters across multiple integration points.
PostMessage Events
Section titled “PostMessage Events”The iframe and the host page communicate exclusively via PostMessage, the browser’s native mechanism for cross-origin window communication. Every message sent by the iframe carries a source identifier that allows the host page to filter relevant messages.
Message Structure
Section titled “Message Structure”All messages follow this format:
{ "source": "<slug>-onboarding", "event": "event-name", "payload": {}}The source field is <slug>-onboarding, where <slug> is the client instance identifier of your Guardline instance. The value is fixed for a given instance but differs between instances, so it is not the same string for every integrator. Confirm the exact value for your instance with the Guardline team during setup, and filter on that value. A listener that filters on a hardcoded generic identifier will drop every event on an instance that sets its own slug.
Events Reference
Section titled “Events Reference”Emitted when the iframe has mounted and is ready to display the first step. On token routes it is emitted twice: once at mount, before the session token is resolved, and again after resolution.
| Payload Field | Type | Description |
|---|---|---|
executionId | UUID | The execution identifier for this onboarding session. Use it to correlate the embedded session with your internal records. Typically absent on the first ready, which fires before the session is resolved, and present on the second. |
The host page can use this event to hide a loading indicator and reveal the iframe. Handle it idempotently: a host page that reveals the iframe on ready will run that logic twice, and a host page that reads executionId on ready must tolerate the field being absent the first time.
step-changed
Section titled “step-changed”Emitted each time the user advances to the next step or navigates back.
| Payload Field | Type | Description |
|---|---|---|
executionId | UUID | The execution identifier. |
stepId | string | The identifier of the current step (e.g., document-front, biometric-iproov). |
stepIndex | integer | Zero-based index of the current step in the flow. |
totalSteps | integer | Total number of steps in the flow. |
The set of step codes is specific to each flow and each country, so the codes above are examples and not a fixed list. Confirm the codes for your flow with the Guardline team before branching on stepId, and do not hardcode a switch against the examples in this document.
The host page can use this event to display an external progress indicator, track analytics, or adjust the surrounding interface.
completed
Section titled “completed”Emitted when the user has submitted all required steps. This event signals that the user’s part of the journey is done, not that a final decision has been made. The decision field provides an immediate indication of the outcome, but the webhook is the authoritative source for the final decision result.
| Payload Field | Type | Description |
|---|---|---|
executionId | UUID | The execution identifier. |
decision | string | Immediate decision indication: approved, rejected, in_review, or unconfirmed. When in_review, the execution has been referred to a human analyst and the final result will arrive exclusively via webhook (onboarding.approved or onboarding.rejected). When unconfirmed, the frontend could not confirm the backend verdict; the journey ended, but the outcome is unknown to the iframe. |
Typical frontend handling by decision value:
decision | Suggested UX |
|---|---|
approved | Close the iframe, display a success confirmation. |
rejected | Close the iframe, display an appropriate message or redirect to a support flow. |
in_review | Close the iframe, inform the user that verification is under review and they will be notified. The integrator’s backend will receive the final result via webhook. |
unconfirmed | Close the iframe, but do not present a final result to the user. The journey ended and the outcome is not confirmed. Treat the webhook as authoritative and inform the user once it arrives. |
blocked
Section titled “blocked”Emitted when the flow is interrupted for security reasons.
| Payload Field | Type | Description |
|---|---|---|
executionId | UUID | The execution identifier. |
reason | string | The reason for the block: fraud_detected, invalid_data, max_attempts_exceeded, identity_mismatch. |
The host page can display a support message or offer alternative channels.
Emitted when a technical error prevents progress.
| Payload Field | Type | Description |
|---|---|---|
code | string | A standardized error code (see PostMessage Error Codes). |
message | string | A human-readable description of the error. |
status | integer | Present only when the error originated from an HTTP response. The HTTP status code of that response. |
This event does not carry an executionId. Correlate it with the execution your backend created for the session, or with the executionId received on the resolved ready event.
height-changed
Section titled “height-changed”Emitted when the iframe’s content height changes, throttled to a minimum interval of 200 ms (at most five updates per second). This is useful for layouts where the iframe is not set to 100% of the viewport.
| Payload Field | Type | Description |
|---|---|---|
height | integer | The content height in pixels. |
The following two events are also emitted by the iframe.
retry: Emitted when the user activates the retry button on the error screen. The host page can use it to clear any surrounding error state it displayed in response to a previous error event, before the iframe attempts the failed operation again.
dismissed: Emitted when the user closes a terminal screen, that is, when the user dismisses the final screen of the journey rather than the host page closing it. This is the signal a host page needs in order to close its own modal or overlay on a user-driven exit. A host that only closes on completed will leave an empty container on screen after the user dismisses the terminal screen.
| Payload Field | Type | Description |
|---|---|---|
state | string | The terminal screen the user dismissed: review, approved, rejected, or unconfirmed. |
Origin Validation
Section titled “Origin Validation”PostMessage is an open channel by nature: any window can send messages to any other. Security depends on rigorous validation on both sides.
On the iframe side, delivery is not broadcast to a list of domains. The iframe resolves exactly one target origin, taken from the origin query parameter on its own URL, or from the document referrer when that parameter is absent. It validates that origin for membership in the allowed list configured for the integrator’s instance, and then posts every message to that single origin. Messages sent with a restricted origin are rejected by the browser if the recipient is on a different domain.
A plain-HTTP origin is rejected unless it is localhost. A staging host served over HTTP therefore receives no messages at all, and does so silently: the iframe renders and the journey works, but no PostMessage event ever reaches the host page. Serve staging hosts over HTTPS, or test against localhost.
On the integrator side, the host page must verify the origin property of every received message against the exact domain of the Guardline instance. Validation by substring or regex is insecure (a domain like guardline.com.br.attacker.com would pass naive validations). Only exact domain equality should be used.
Communication from Host to Iframe
Section titled “Communication from Host to Iframe”In the current version, the host page does not need to send commands to the iframe. The onboarding is autonomous once started: the user navigates through the steps, and the iframe manages all state internally.
Future versions will support commands such as programmatically restarting the flow or terminating the session.
Session Resumption
Section titled “Session Resumption”The onboarding can be interrupted for many reasons: the user closes the browser, loses connectivity, navigates to another page, or the host page destroys and recreates the iframe. In all these cases, the user can resume from where they left off by accessing the same token.
Resumption works because the backend persists the state of each step individually. When the iframe loads with a token, it queries the backend for the execution state. If the execution is in progress, the frontend identifies the first pending step and positions the user there. Step position resumes correctly, but field content does not: in embed mode the backend strips the per-step display data and the prefill fields from the resolver response, so previously entered values are not repopulated in the form.
This approach is critical in the iframe context. The browser’s sessionStorage is isolated by origin in cross-origin iframes. If the host page destroys the iframe and recreates it (for example, because the user navigated away and came back), all sessionStorage is lost. The backend as the source of truth ensures the session survives any iframe destruction scenario.
If the token is expired, the execution is in a terminal state, or the token is invalid, the iframe displays an informative screen appropriate to the scenario and does not attempt to start a new flow.
For the full execution lifecycle and state semantics, see Execution Lifecycle on the API reference.
Session and Webhook Contract
Section titled “Session and Webhook Contract”The contract for everything that is not iframe-specific lives in the ONP API Reference:
- Authentication and idempotency
- Available journeys
- Creating a session
- Linked subjects (for
kyc_minorand futurekybofficer flows) - Notification opt-in
- Resolving the link (the endpoint the iframe calls server-side)
- Resending the representative link
- Execution lifecycle
- Querying an execution
- Webhooks (event taxonomy, payload, authentication modes, retry policy)
- Notification polling
- Error reference (HTTP status codes and domain error codes)
- Endpoint summary
The embed-specific guidance below applies on top of these contracts.
Security
Section titled “Security”Instance Isolation
Section titled “Instance Isolation”The Guardline architecture is single-tenant. Each integrator receives dedicated backend, database, and frontend instances. There is no sharing of data or application code between instances. The underlying infrastructure (Kubernetes cluster, networking, observability) is shared, but logical isolation is enforced at every layer: separate databases, separate application processes, separate storage, and separate credentials. One integrator’s iframe has no access to another integrator’s data, even indirectly.
HTTP Security Headers
Section titled “HTTP Security Headers”The embedded document is a static build served by nginx. The only security header it sets is X-Content-Type-Options: nosniff. It ships with no Content Security Policy frame-ancestors directive, no X-Frame-Options, no Permissions-Policy and no Referrer-Policy. Do not rely on response headers from the embedded document to restrict framing, and do not expect a Permissions-Policy to grant sensor access: camera and motion sensor access inside the iframe is granted by the allow attribute that the integrator sets on the iframe element.
Restricting which pages may frame the onboarding is a setup item rather than a response header. The allowed parent origins are configured per instance by the Guardline team and are enforced by the PostMessage origin check described under Origin Validation: the iframe posts only to an origin that is present in that list. Changes to the list require coordination with the Guardline team.
Cross-Origin Cookies
Section titled “Cross-Origin Cookies”The onboarding journey does not authenticate with cookies. The journey credential is the X-Journey-Token request header, combined with the link token carried in the URL path. No journey cookie is set, so the browser’s third-party cookie policy has no effect on the journey itself, and no custom domain or cookie configuration is required on the integrator’s side for the onboarding to work in a cross-origin iframe.
Third-party cookie restrictions remain relevant to the device profiling vendor, which is a separate concern. See Device Profiling (Nethone) in Appendix A.
Attack Protection
Section titled “Attack Protection”| Attack Vector | Mitigation |
|---|---|
| Clickjacking | The embedded document sets no framing header, so framing is not blocked at the browser level. A page that frames the onboarding without being in the instance’s allowed origins receives no PostMessage events, which prevents a disguised page from driving the host-side flow. |
| Token replay | Tokens are bound to a single execution and time-limited (link validity of 7 days, active session window of 24 hours). A captured token grants access only to the execution it was created for. |
| PostMessage XSS | Origin validation on both sides. The iframe only sends messages to the configured origin; the host page must validate the origin of every received message. |
| Webhook replay | HMAC signature with timestamp over the body, which carries the event’s event_id. The integrator’s endpoint should reject webhooks older than 5 minutes and deduplicate on the event_id from the signed body, not on the header. |
| Token enumeration | Tokens are 32-character hex values from a cryptographically secure source (128 bits of entropy). Brute-force enumeration is computationally infeasible. |
| Man-in-the-middle | HTTPS (TLS 1.2+) is mandatory for all network communication: API calls, iframe loading, and webhook delivery. PostMessage is a browser-internal mechanism between windows in the same user agent and does not traverse the network, so it is not susceptible to network-level interception. |
Browser Compatibility
Section titled “Browser Compatibility”The embedded onboarding is supported on all modern browsers. Camera in cross-origin iframes is supported from Chrome 64+, Firefox 90+, Safari 15+, and Edge 79+. Mobile support includes Chrome (Android) 64+ and Safari (iOS) 15+.
The iframe requires the following allow attributes: camera (required on all platforms), accelerometer, gyroscope, and magnetometer (required on mobile for biometric liveness detection). Without camera, the onboarding cannot proceed past document or biometric steps. Without motion sensors, the biometric provider may function in degraded mode on mobile.
For detailed browser compatibility matrices, legacy device notes (iOS 14), and third-party provider behavior, see Appendix A: Browser Compatibility Details.
PostMessage Error Codes
Section titled “PostMessage Error Codes”The following error codes may be emitted via the PostMessage error event. They represent technical conditions that prevent the onboarding from progressing inside the iframe. For HTTP-level error codes returned by the API, see the Error Reference on the API reference.
| Code | Description | Suggested Action |
|---|---|---|
camera_denied | The user denied camera access when prompted by the browser. | Display a message explaining that camera access is required and instruct the user to grant permission in browser settings. |
camera_not_found | No camera was detected on the device. | Display a message suggesting the user switch to a device with a camera. |
camera_play_failed | The camera stream was acquired but playback in the video element could not start. | Display an error message and let the user retry the step. If it persists, suggest closing other applications or tabs that may be holding the camera. |
device_unsupported | The device or browser does not support a capability required by the current step. | Display a message suggesting the user switch to a supported browser or device. See Appendix A: Browser Compatibility Details. |
permission_not_granted | The iframe does not have the required allow attribute for camera. This is a configuration error on the integrator’s side. | Verify that the iframe element includes allow="camera". |
api_unavailable | The Guardline API is unreachable. | Display a generic error message and suggest retrying. If persistent, contact Guardline support. |
sdk_load_failed | The biometric verification SDK failed to load (network issue or CDN failure). | Display an error message and suggest retrying. The user can attempt the step again. |
load_error | A resource required by the current step failed to load. | Display an error message and allow the user to retry the step. |
token_invalid | The session token is malformed or does not exist. | Display a message informing the user the link is invalid. The integrator should generate a new session. |
token_expired | The session token has expired. | Display a message informing the user the link has expired. The integrator should generate a new session. |
session_completed | The execution associated with this token is already in rejected status. This code is not emitted for other final decisions. | Display a message informing the user the onboarding has already been finalized. |
session_cancelled | The session was cancelled before the journey completed. | Display a message informing the user the session is no longer active. The integrator should generate a new session if the user needs to try again. |
session_blocked | The session was blocked due to security reasons. | Display a message and direct the user to support channels. |
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Solution |
|---|---|---|
| PostMessage events not received | ?origin= missing from the iframe URL, host page filtering on the wrong source value, or allowed origin misconfigured. | Confirm the embed_url carries ?origin= with your exact page origin. Check the event listener filters on your instance’s source value (<slug>-onboarding). Verify allowed origins match the exact origin of your host page (protocol + domain + port). |
| Camera does not work in iframe | Iframe element missing allow="camera". | Add allow="camera" to the iframe. On mobile, also include accelerometer; gyroscope; magnetometer. |
| Biometric fails on mobile | Motion sensor permissions not declared on iframe. | Add accelerometer; gyroscope; magnetometer to the iframe’s allow attribute. |
| Terms acceptance always recorded without location | Iframe element missing allow="geolocation", so the browser denies the request without prompting. | Add geolocation to the iframe’s allow attribute. The journey is never blocked by this: a declined or unavailable location is recorded as such in the consent evidence. |
| User loses progress after navigating away | Host page destroyed and recreated the iframe, losing sessionStorage. | Expected behavior. The backend persists all step data. The session resumes automatically from the last completed step with the same token. |
| Webhooks not arriving | Endpoint unreachable, returning non-2xx, or signature verification rejecting valid payloads. | Check endpoint accessibility via HTTPS. Check logs in the Guardline admin panel. Verify signature is computed over timestamp + "." + body. |
Data Flow and Privacy
Section titled “Data Flow and Privacy”Core onboarding data (name, CPF, contact data, document metadata, and document images) is stored in Guardline systems and encrypted at rest. Biometric captures are processed by iProov and are not retained by Guardline. Device fingerprints are processed by Nethone and are not retained by Guardline. The integrator is the data controller under LGPD, Guardline acts as data processor. Retention periods, legal basis, and DPA terms are defined per contract.
For the complete data residency diagram, retention table, and compliance responsibility matrix, see Appendix B: Data Flow and Compliance Details.
Performance
Section titled “Performance”A typical KYC flow with 6 steps completes in 3-5 minutes of user interaction. Backend operations (token resolution, step submission, decision engine) are sub-second. The biometric verification step (5-15s) is the most variable, depending on network latency to iProov servers and device camera hardware.
These figures are engineering reference, not SLA commitments. Performance SLAs are defined per contract. For detailed P95 metrics with measurement context, see Appendix C: Performance Details.
Integration Checklist
Section titled “Integration Checklist”Use this checklist to validate your iframe integration before going to production.
Backend Integration
Section titled “Backend Integration”- Session creation endpoint includes
surface_hint: "embed"for iframe-rendered sessions. - Webhook endpoint is implemented, accessible via HTTPS, and responds with 2xx.
- Webhook signature verification is implemented using the shared secret.
- Webhook idempotency is implemented using the
event_idfrom the signed body, withexecution_id+event_sequenceas the fallback when the delivery does not carry it; theX-Guardline-Event-IDheader still arrives with the same value, but the signature does not cover it. - Webhook timestamp validation rejects events older than 5 minutes.
- Session status polling is implemented as a fallback for missed webhooks.
- API key is stored securely (environment variable, secret manager), not in source code.
Frontend Integration
Section titled “Frontend Integration”- Iframe
srcis theembed_urlwith?origin=appended, carrying the exact origin of the host page (scheme + host + port). Without it, no PostMessage event is emitted. - Iframe element includes
allow="camera; geolocation; accelerometer; gyroscope; magnetometer". - Iframe does not include the
sandboxattribute. - PostMessage listener filters by the
sourcevalue of your instance (<slug>-onboarding), confirmed with the Guardline team during setup. - PostMessage origin validation checks the exact Guardline domain (no substring or regex matching).
- The
readyevent is handled (hide loading indicator, show iframe). - The
completedevent is handled with branching bydecisionvalue:approved(confirmation),rejected(appropriate message),in_review(inform user of pending review),unconfirmed(no final result shown, wait for the webhook). - The
errorevent is handled (display user-friendly message). - The
blockedevent is handled (display support information).
Testing
Section titled “Testing”- End-to-end onboarding flow works in Chrome, Safari, and Firefox (desktop).
- End-to-end onboarding flow works in Chrome (Android) and Safari (iOS 15+).
- Camera access works inside the iframe on all target browsers.
- Biometric verification completes successfully inside the iframe.
- Session resumption works: destroy the iframe, recreate it with the same token, verify the flow resumes from the correct step.
- Expired token displays the appropriate informative screen.
- Invalid token displays the appropriate informative screen.
- Webhook delivery is confirmed in the Guardline admin panel.
- Webhook signature verification correctly rejects tampered payloads.
Environment
Section titled “Environment”- Allowed origins are configured for your production domain(s) (required for PostMessage origin validation).
- SSL certificates are valid and not expiring soon.
- API key for production environment is provisioned and stored securely.
- Webhook shared secret is stored securely.
For sandbox access and testing support, contact the Guardline technical team.
Appendix A: Browser Compatibility Details
Section titled “Appendix A: Browser Compatibility Details”The browser versions, device statistics, SDK versions, and vendor timeouts in this appendix are reported by the browser vendors, the platform, and the verification providers. The product does not feature-detect or verify any of them at runtime, so treat them as vendor guidance rather than as behavior enforced by the onboarding.
Desktop Browsers
Section titled “Desktop Browsers”| Browser | Minimum Version | Camera in Iframe | Notes |
|---|---|---|---|
| Chrome | 64+ (2018) | Yes | Full support for Permissions Policy and cross-origin iframe camera access. |
| Firefox | 90+ (2021) | Yes | Full support. Enhanced Tracking Protection may affect Nethone device profiling. |
| Safari | 15+ (2021) | Yes | Full support. Intelligent Tracking Prevention may affect Nethone device profiling. |
| Edge | 79+ (2020) | Yes | Chromium-based. Same behavior as Chrome. |
Mobile Browsers
Section titled “Mobile Browsers”| Browser | Minimum Version | Camera in Iframe | Notes |
|---|---|---|---|
| Chrome (Android) | 64+ | Yes | Full support. |
| Safari (iOS) | 15+ | Yes | Full support for camera in cross-origin iframes. |
| Safari (iOS) | 14 and earlier | No | Does not support camera in cross-origin iframes. The biometric provider offers a bridge pattern that opens capture in a new tab and returns the result via PostMessage. These versions represent less than 5% of active iOS devices and are declining. |
| Samsung Internet | 12+ | Yes | Chromium-based. Same behavior as Chrome. |
Iframe Permissions Detail
Section titled “Iframe Permissions Detail”| Permission | Required | Purpose | Impact if Missing |
|---|---|---|---|
camera | Yes | Document capture and biometric verification. | Onboarding cannot proceed past document or biometric steps. The iframe displays an error message. |
accelerometer | Mobile only | Liveness detection on mobile devices. | Biometric provider may function in degraded mode (no motion detection) or fail on some devices. |
gyroscope | Mobile only | Liveness detection on mobile devices. | Same as accelerometer. |
magnetometer | Mobile only | Liveness detection on mobile devices. | Same as accelerometer. |
Biometric Verification (iProov)
Section titled “Biometric Verification (iProov)”The iProov Web SDK (version 5.4.3+) supports operation inside iframes. The SDK communicates with iProov servers using its own tokens obtained from the Guardline backend and does not depend on third-party cookies or shared storage.
On mobile devices, iProov uses motion sensors for liveness detection (verifying the device is being held by a real person). The iframe must declare permissions for accelerometer, gyroscope, and magnetometer. Without these declarations, iProov may function in degraded mode (no motion detection) or fail.
Device Profiling (Nethone)
Section titled “Device Profiling (Nethone)”Nethone collects device information (fingerprint, typing patterns, fraud signals) using a JavaScript agent loaded from an external CDN. This agent operates with third-party cookies for cross-session device tracking.
In a cross-origin iframe context, browsers with restrictive privacy policies may limit Nethone’s functionality:
| Browser | Policy | Impact |
|---|---|---|
| Safari | Intelligent Tracking Prevention (ITP) | Third-party cookies blocked. Device fingerprint reduced to session-only. |
| Firefox | Enhanced Tracking Protection (ETP) | Third-party cookies blocked in strict mode. Similar impact to Safari. |
| Chrome | User-configurable | Third-party cookies allowed by default. Users can disable them. |
The onboarding is designed with graceful degradation for Nethone: if the script fails to load, profiling does not complete within the timeout (5 seconds), or cookies are blocked, the flow continues normally. The risk analysis loses the device intelligence dimension, but all other verifications (biometrics, document verification, bureau validation) function independently.
For scenarios where device profiling is critical, running Nethone in the integrator’s domain (first-party context, no third-party cookie restrictions) and communicating the result to the iframe via PostMessage is a supported alternative. Contact the Guardline team for this configuration.
Appendix B: Data Flow and Compliance Details
Section titled “Appendix B: Data Flow and Compliance Details”Where Data Resides
Section titled “Where Data Resides”Data Retention
Section titled “Data Retention”| Data Type | Storage Location | Retention | Encrypted at Rest |
|---|---|---|---|
| Session token | Guardline database | Until expiration or completion | Yes |
| Personal data (name, CPF, email) | Guardline database | Per data retention policy (configurable) | Yes |
| Document images | Guardline object storage | Per data retention policy (configurable) | Yes |
| Biometric data | Processed by iProov, not stored by Guardline | Not retained | N/A |
| Device fingerprint | Processed by Nethone, not stored by Guardline | Not retained | N/A |
| Decision results | Guardline database | Immutable audit trail | Yes |
| Webhook payloads | Guardline database (delivery log) | 90 days | Yes |
Compliance Responsibility Matrix
Section titled “Compliance Responsibility Matrix”| Area | What Guardline Provides (Technical) | Contractual / Configurable | Integrator Responsibility |
|---|---|---|---|
| LGPD | Data is collected with a specific, documented purpose (identity verification). | Retention duration, legal basis for processing, and DPA (Data Processing Agreement) are defined per contract. Retention of onboarding data is a contractual commitment and is not enforced automatically by the platform. | The integrator is the data controller and must ensure lawful basis for initiating the onboarding (e.g., user consent, contractual necessity). Guardline acts as data processor. |
| Data residency | The platform supports deployment in specific geographic regions or on-premise. | Region selection and on-premise deployment are subject to contractual agreement. | The integrator must define residency requirements based on its own regulatory obligations. |
| Audit trail | All operations are recorded in an immutable audit log, accessible via the admin panel. | Log retention period and export format are configurable per contract. | The integrator is responsible for consuming and archiving audit logs as required by its own compliance policies. |
| Data minimization | Only data necessary for the configured flow steps is collected. | Flow configuration (which steps are active, which fields are required) is defined during setup. | The integrator controls which pre-fill data to send. Sending unnecessary personal data in the request is the integrator’s responsibility. |
| Right to deletion | The platform supports data deletion requests technically. | Deletion procedures and SLAs are defined per contract. | The integrator must forward deletion requests from data subjects to Guardline and confirm completion to the requesting party. |
Appendix C: Performance Details
Section titled “Appendix C: Performance Details”The values below are P95 measurements observed in the Europe region under normal load conditions. Actual performance varies depending on the integrator’s infrastructure, end-user network quality, and device capabilities. These figures are provided as engineering reference, not as SLA commitments. Performance SLAs are defined per contract.
| Metric | P95 | Measurement Context |
|---|---|---|
| Iframe initial load | < 2s | Standard broadband (10 Mbps+). Includes SPA bundle (gzipped), fonts, and token resolution. Cached assets reduce subsequent loads to < 500ms. |
| Token resolution | < 200ms | Backend processing time only (database lookup + flow configuration assembly). Does not include network round-trip from the client. |
| Step submission | < 300ms | Backend processing time only (validation + persistence). |
| Document capture (camera init) | 1-3s | Varies with device camera hardware and browser. First capture on a page load is slower due to camera permission prompt and hardware initialization. |
| Biometric verification | 5-15s | End-to-end including iProov SDK initialization, capture, and server-side processing. Heavily dependent on network latency to iProov servers. |
| Decision engine | < 500ms | Backend processing time only. Operates exclusively on data already collected during the onboarding steps. No external provider calls at this stage. |
| PostMessage delivery | < 1ms | Browser-internal, same-device. Not a network operation. |
| Webhook first delivery attempt | < 5s | Time from decision to HTTP request to the integrator’s endpoint. Does not include the integrator’s processing time. |
Factors that affect end-user experience:
- Network quality: Document upload and biometric verification are the most bandwidth-intensive steps. On connections below 3 Mbps, capture and upload times increase significantly.
- Device camera quality: Lower-quality cameras may require multiple capture attempts for document verification.
- Number of steps in the flow: Each step adds user navigation time. A KYC flow with 6 steps typically completes in 3-5 minutes of user interaction.
- Browser: Modern browsers (Chrome 90+, Safari 16+, Firefox 100+) provide the best performance for camera access and WebGL rendering used by the biometric SDK.
Version 18, updated on