Skip to main content

Embedding in an iframe

Iframe mode is the recommended way to use Kaunt's embedded UI components inside a logged-in application. Your shell creates a session, hands the JWT to the iframe via postMessage, and the embedded component talks to Kaunt directly. The JWT never appears in the iframe URL, so it can't leak through browser history, screen sharing, or HTTP referer headers.

Creating the session

From your backend (never the browser), call the create-session endpoint with the component, the access mode iframe, the list of origins allowed to embed the iframe, and the component-specific data payload.

POST /v1/tenants/05ed0ffa-1bf5-4bd1-9970-df7a78a948fe/embedded-components/sessions
Authorization: Bearer <your-kaunt-api-key>
Content-Type: application/json

{
"component": "documentai-feedback-agent",
"accessMode": "iframe",
"allowedOrigins": ["https://app.partner.com"],
"data": {
"documentId": "227aebd0-36a4-4d17-b96d-c5b5d071abd4",
"userId": "user-42",
"companyName": "kaunt",
"permissions": {
"canManageRulesAtScope": ["Vendor", "Buyer"],
"canRunPreview": true
}
}
}

The response includes the JWT, the iframe URL, and an expiry timestamp:

{
"sessionId": "fb0ccbbc-62bc-447f-a47e-02b490e25690",
"token": "eyJhbGciOiJIUzI1NiIs…",
"url": "https://components.kaunt.com/documentai-feedback-agent?sessionId=fb0ccbbc-62bc-447f-a47e-02b490e25690&mode=iframe",
"accessMode": "iframe",
"expiresAt": 1717160000
}

allowedOrigins is required in production and is enforced both by the embedded component (when validating the postMessage token) and by Kaunt's Content Security Policy on the components host.

The postMessage handshake

Once the iframe loads the URL, the component does not have the JWT yet — it only knows its session ID. It expects your shell to deliver the JWT via window.postMessage. The handshake is:

  1. The iframe reads the parent's origin from document.referrer and sends { type: "kaunt-ready", sessionId } to that origin.
  2. Your shell responds with { type: "kaunt-token", token } to the iframe's origin.
  3. The component validates the JWT, checks that the parent origin appears in the token's allowedOrigins claim, and boots.

If the iframe doesn't receive a valid token within 5 seconds, it falls into an error state and posts a kaunt-error event with code handshake-timeout.

Minimal embedding example

<iframe
id="kaunt-iframe"
src="https://components.kaunt.com/documentai-feedback-agent?sessionId=fb0ccbbc-62bc-447f-a47e-02b490e25690&mode=iframe"
style="width: 420px; height: 640px; border: 0;"
></iframe>

<script>
const iframe = document.getElementById('kaunt-iframe');
const componentsOrigin = 'https://components.kaunt.com';

// Token comes from your backend — typically returned alongside the iframe URL
// when your application opens the screen that hosts the component.
const token = '<the JWT you got from the create-session call>';

window.addEventListener('message', (event) => {
if (event.origin !== componentsOrigin) return;

if (event.data?.type === 'kaunt-ready') {
iframe.contentWindow.postMessage(
{ type: 'kaunt-token', token },
componentsOrigin
);
}

if (event.data?.type === 'kaunt-error') {
console.warn('Kaunt component error:', event.data.code, event.data.sessionId);
// Decide how to react — see the Error Events guide for the code list.
}
});
</script>

A few things to note:

  • Only deliver the JWT in response to kaunt-ready. Posting it eagerly to a not-yet-loaded iframe is wasteful and easier to get wrong.
  • Always specify the target origin. Passing '*' to postMessage would leak the JWT to any document that happens to load inside the iframe.
  • Always verify event.origin. Drop messages that don't come from the components host. Token theft via forged kaunt-ready messages is the main risk this guards against.
  • The component does not require any specific iframe size. It collapses to a compact layout below ~420 px wide.

Sandbox and permissions

The components host already sets the security headers it needs (CSP, X-Frame-Options is not used so framing works; frame-ancestors is the enforcement mechanism). On your side:

  • If you sandbox the iframe, include at minimum sandbox="allow-scripts allow-same-origin allow-forms". Without allow-scripts the component cannot run; without allow-same-origin it cannot send authenticated requests.

Session lifetime and revocation

Sessions are short-lived (typically one hour) and consumed on first load. The component will continue to function after the URL has been consumed because it holds the JWT in memory; reloading the iframe with the same URL will fail.

If you need to invalidate a session before it expires — for example because the user logged out of your application — call DELETE /v1/tenants/{tenantId}/embedded-components/sessions/{sessionId}. The next request the component makes will receive a 401 and the component will post { type: "kaunt-error", code: "session-revoked" } to your shell.

Pick an iframe size that comfortably fits the component without internal scrolling. As a starting point:

ComponentRecommended minimum size
Document AI Feedback Agent360 × 560 px

Embedded components react to width and switch to a compact layout below ~420 px, so they remain usable in side panels.