> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.idenfy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Redirect & iFrame

> Redirect users to iDenfy or embed the identity verification flow in your web page via iFrame with customizable query parameter options.

export const IframeSizingDiagram = () => {
  const css = `
    .isd-diag {
      display: flex;
      gap: 20px;
      align-items: stretch;
      flex-wrap: wrap;
      margin: 1.5rem 0;
    }
    .isd-card {
      flex: 1 1 260px;
      display: flex;
      flex-direction: column;
      gap: 10px;
      min-width: 0;
      justify-content: flex-end;
      align-items: stretch;
    }
    .isd-cap {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 4px;
    }
    .isd-cap-tag {
      font-weight: 700;
      font-size: 14px;
      display: flex;
      align-items: center;
      gap: 8px;
      color: #19181d;
    }
    .isd-cap-tag::before {
      content: "";
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: #60a561;
      box-shadow: 0 0 0 3px rgb(96 165 97 / 0.22);
    }
    .isd-card-bad .isd-cap-tag { color: #da4167; }
    .isd-card-bad .isd-cap-tag::before {
      background: #da4167;
      box-shadow: 0 0 0 3px rgb(218 65 103 / 0.22);
    }
    .isd-cap-dim {
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-weight: 600;
      font-size: 12px;
      color: #6f7486;
      letter-spacing: 0.06em;
    }
    .dark .isd-cap-tag { color: #e6e9ef; }
    .dark .isd-card-bad .isd-cap-tag { color: #f17a99; }
    .dark .isd-cap-dim { color: #9ba1b0; }

    /* Partner page wrapper around the iframe (non-iDenfy chrome) */
    .isd-partner {
      background: repeating-linear-gradient(45deg, #f3f4f6 0, #f3f4f6 7px, #fff 7px, #fff 14px);
      border: 1.5px dashed #d8dee9;
      border-radius: 14px;
      padding: 38px 18px 24px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-end;
      position: relative;
      height: 500px;
      box-sizing: border-box;
    }
    .isd-partner-lbl {
      position: absolute;
      top: -11px;
      left: 14px;
      font-weight: 700;
      font-size: 10px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: #6f7486;
      background: #fff;
      padding: 6px 10px;
      border-radius: 5px;
      border: 1.5px dashed #d8dee9;
      white-space: nowrap;
      display: flex;
      align-items: center;
      gap: 6px;
    }
    .isd-partner-lbl::before {
      content: "";
      width: 10px;
      height: 10px;
      border-radius: 3px;
      background: repeating-linear-gradient(45deg, #e6e9ef 0, #e6e9ef 2px, #fff 2px, #fff 4px);
      border: 1px solid #d5d7da;
    }
    .dark .isd-partner {
      background: repeating-linear-gradient(45deg, rgb(255 255 255 / 0.05) 0, rgb(255 255 255 / 0.05) 7px, transparent 7px, transparent 14px);
      border-color: rgb(255 255 255 / 0.18);
    }
    .dark .isd-partner-lbl {
      background: #17171b;
      color: #9ba1b0;
      border-color: rgb(255 255 255 / 0.18);
    }

    /* iDenfy iframe tag on the top edge of the frame */
    .isd-wrap {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    .isd-iframe-tag {
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      font-weight: 700;
      font-size: 10px;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: #fff;
      background: #734bfb;
      padding: 5px 10px;
      border-radius: 5px;
      white-space: nowrap;
      display: flex;
      align-items: center;
      gap: 6px;
      z-index: 5;
      box-shadow: 0 2px 6px rgb(115 75 251 / 0.3);
    }
    .isd-iframe-tag::before {
      content: "i";
      font-weight: 900;
      font-size: 9px;
      width: 11px;
      height: 11px;
      border-radius: 2px;
      background: #fff;
      color: #734bfb;
      display: grid;
      place-items: center;
    }

    /* Browser frame with the mock verification UI */
    .isd-frame {
      background: #fff;
      border: 1.5px solid #734bfb;
      border-radius: 10px;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      box-shadow: 0 4px 16px rgb(115 75 251 / 0.18);
      position: relative;
      width: 268px;
      max-width: 100%;
    }
    .isd-card-bad .isd-frame {
      height: 240px;
      width: 240px;
      border-color: #da4167;
      box-shadow: 0 4px 16px rgb(218 65 103 / 0.18);
    }
    .isd-card-bad .isd-frame::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 54px;
      background: linear-gradient(180deg, transparent, rgb(218 65 103 / 0.1));
      pointer-events: none;
    }
    .isd-winbar {
      height: 24px;
      background: #f3f4f6;
      border-bottom: 1px solid #e6e9ef;
      display: flex;
      align-items: center;
      padding: 0 10px;
      gap: 6px;
      flex-shrink: 0;
    }
    .isd-dot { width: 8px; height: 8px; border-radius: 50%; }
    .isd-dot-r { background: #ff6b7e; }
    .isd-dot-y { background: #ffcc4d; }
    .isd-dot-g { background: #7bcb7d; }

    .isd-doc {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 14px 14px 12px;
      gap: 8px;
      overflow: hidden;
      position: relative;
      background: #fff;
    }
    .isd-card-bad .isd-doc { padding-right: 22px; }
    .isd-logo {
      font-weight: 800;
      font-size: 12px;
      letter-spacing: -0.04em;
      color: #19181d;
    }
    .isd-ui-card {
      width: 100%;
      border: 1px solid #e6e9ef;
      border-radius: 8px;
      padding: 10px 12px;
      display: flex;
      flex-direction: column;
      gap: 7px;
      align-items: center;
      background: #fff;
      flex-shrink: 0;
      box-sizing: border-box;
    }
    .isd-ui-card .isd-ui-title {
      font-weight: 700;
      font-size: 12px;
      line-height: 1.22;
      margin: 0;
      color: #19181d;
      text-align: center;
    }
    .isd-desc {
      font-weight: 500;
      font-size: 9px;
      line-height: 1.3;
      color: #6f7486;
      text-align: center;
      margin: 0;
    }
    .isd-scan {
      width: 100%;
      background: #19181d;
      border-radius: 6px;
      height: 90px;
      position: relative;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .isd-id {
      width: 88%;
      height: 80%;
      background: linear-gradient(135deg, #a98bff 0%, #d8b4fe 50%, #fecdd3 100%);
      border-radius: 4px;
      position: relative;
      overflow: hidden;
    }
    .isd-id::before {
      content: "";
      position: absolute;
      left: 8px;
      top: 9px;
      width: 30px;
      height: 38px;
      background: rgb(255 255 255 / 0.45);
      border-radius: 2px;
    }
    .isd-id::after {
      content: "";
      position: absolute;
      left: 44px;
      top: 12px;
      right: 10px;
      height: 36px;
      background: repeating-linear-gradient(180deg, transparent 0, transparent 4px, rgb(255 255 255 / 0.5) 4px, rgb(255 255 255 / 0.5) 6px);
    }
    .isd-accepted {
      width: 100%;
      background: #f3f4f6;
      border-radius: 7px;
      padding: 7px 10px;
      font-weight: 500;
      font-size: 9px;
      line-height: 1.35;
      color: #6f7486;
      text-align: left;
      flex-shrink: 0;
      box-sizing: border-box;
    }
    .isd-diag .isd-accepted strong,
    .dark .isd-diag .isd-accepted strong { color: #19181d; font-weight: 700; }
    .isd-accepted-link {
      color: #734bfb;
      text-decoration: underline;
      font-weight: 600;
    }
    .isd-timer {
      display: flex;
      align-items: center;
      gap: 5px;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-weight: 600;
      font-size: 10px;
      color: #6f7486;
      flex-shrink: 0;
    }
    .isd-timer::before {
      content: "";
      width: 9px;
      height: 9px;
      border-radius: 50%;
      border: 1.5px solid #6f7486;
      box-sizing: border-box;
    }
    .isd-btn-primary {
      width: 100%;
      height: 28px;
      background: #734bfb;
      color: #fff;
      border-radius: 7px;
      display: grid;
      place-items: center;
      font-weight: 600;
      font-size: 11px;
      flex-shrink: 0;
      box-shadow: 0 4px 10px rgb(115 75 251 / 0.25);
    }
    .isd-btn-secondary {
      width: 100%;
      height: 28px;
      background: #fff;
      border: 1px solid #d8dee9;
      color: #19181d;
      border-radius: 7px;
      display: grid;
      place-items: center;
      font-weight: 600;
      font-size: 11px;
      flex-shrink: 0;
      box-sizing: border-box;
    }
    .isd-scrollbar {
      position: absolute;
      right: 5px;
      top: 30px;
      bottom: 5px;
      width: 7px;
      background: #e6e9ef;
      border-radius: 4px;
      pointer-events: none;
    }
    .isd-scrollbar::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      height: 42%;
      background: #d5d7da;
      border-radius: 4px;
    }
    .isd-callout {
      font-weight: 700;
      font-size: 10px;
      letter-spacing: 0.04em;
      padding: 7px 11px;
      border-radius: 6px;
      white-space: nowrap;
      text-transform: uppercase;
      color: #fff;
      margin-top: 2px;
    }
    .isd-callout-bad {
      align-self: flex-start;
      background: #da4167;
      box-shadow: 0 4px 12px rgb(218 65 103 / 0.25);
    }
    .isd-callout-ok {
      align-self: flex-end;
      background: #60a561;
      box-shadow: 0 4px 12px rgb(63 119 65 / 0.25);
    }
  `;
  const MockUI = () => <div className="isd-doc">
      <span className="isd-logo">iDenfy</span>
      <div className="isd-ui-card">
        <div className="isd-ui-title">Capture the front of the document</div>
        <p className="isd-desc">Position your document within the marked area and capture a clear photo.</p>
        <div className="isd-scan"><div className="isd-id"></div></div>
      </div>
      <div className="isd-accepted">
        Accepted documents for <span className="isd-accepted-link">United Kingdom</span>:{" "}
        <strong>Provisional driver license, driver license, military card, ID card, passport,</strong>{" "}
        residence permit and visa.
      </div>
      <div className="isd-timer">29:32</div>
      <div className="isd-btn-primary">Take a photo</div>
      <div className="isd-btn-secondary">Back</div>
    </div>;
  return <>
      <style>{css}</style>
      <div className="isd-diag" data-mock="ui" data-nosnippet="" role="img" aria-label="Two iframe sizings side by side: a fixed 600 by 600 frame that clips the iDenfy capture screen, and a responsive frame that fits it.">
        <div className="isd-card isd-card-bad">
          <div className="isd-cap">
            <span className="isd-cap-tag">Don't</span>
            <span className="isd-cap-dim">600 × 600</span>
          </div>
          <div className="isd-partner">
            <span className="isd-partner-lbl">Your page</span>
            <div className="isd-wrap">
              <span className="isd-iframe-tag">iDenfy iframe</span>
              <div className="isd-frame">
                <div className="isd-winbar">
                  <span className="isd-dot isd-dot-r"></span>
                  <span className="isd-dot isd-dot-y"></span>
                  <span className="isd-dot isd-dot-g"></span>
                </div>
                <MockUI />
                <div className="isd-scrollbar"></div>
              </div>
            </div>
          </div>
          <span className="isd-callout isd-callout-bad">Buttons below the fold</span>
        </div>

        <div className="isd-card">
          <div className="isd-cap">
            <span className="isd-cap-tag">Do</span>
            <span className="isd-cap-dim">670 × 800</span>
          </div>
          <div className="isd-partner">
            <span className="isd-partner-lbl">Your page</span>
            <div className="isd-wrap">
              <span className="isd-iframe-tag">iDenfy iframe</span>
              <div className="isd-frame">
                <div className="isd-winbar">
                  <span className="isd-dot isd-dot-r"></span>
                  <span className="isd-dot isd-dot-y"></span>
                  <span className="isd-dot isd-dot-g"></span>
                </div>
                <MockUI />
              </div>
            </div>
          </div>
          <span className="isd-callout isd-callout-ok">All actions visible</span>
        </div>
      </div>
    </>;
};

After [creating a verification session](/kyc/generate-token), you need to send your user to the iDenfy verification UI. There are two approaches: **embed an iFrame** directly in your page, or **redirect** your user to an iDenfy-hosted page.

***

## iFrame Integration

Embedding the verification flow in an iFrame keeps users on your site and gives you full control over the experience.

### Base URL

```
https://ui.idenfy.com/
```

### Query Parameters

| Parameter | Required | Description |
| - | - | - |
| `authToken` | Yes | The verification token returned by the [session creation endpoint](/kyc/generate-token). |
| `lang` | No | Forces the UI into a specific language (e.g. `en`, `lt`, `de`). If omitted, the user can choose. |

### Sizing Recommendations

On desktop, use the **recommended 670 × 800 px** embed size so all verification steps display without internal scrolling. Cramped heights cause scrolling at the camera step, which is where users drop. This is a guideline, not a hard minimum. On mobile (below the `575px` breakpoint), switch to **100% width and 100% height** so the iFrame fills the viewport. This gives the best experience for camera capture and liveness checks.

<IframeSizingDiagram />

The UI adapts across three layouts, based on the iFrame's width:

| Breakpoint | Layout |
| - | - |
| `≤ 575px` | Full mobile |
| `576px – 991px` | Mixed-card |
| `≥ 992px` | Full desktop |

<Tip>
  Aim for the full desktop (`≥ 992px`) or full mobile (`≤ 575px`) layout. The mixed-card middle works, but it isn't the richest UI.
</Tip>

### Required Attributes

<Warning>
  You **must** add the `allow="camera; fullscreen; clipboard-write"` and `allowfullscreen` attributes to the iFrame element. Camera access is required for document capture, and fullscreen is required for 3D liveness detection. Without them, the camera-based checks will fail.
</Warning>

```html theme={"system"}
<iframe
  allow="camera; fullscreen; clipboard-write"
  allowfullscreen
></iframe>
```

<Note>
  **Embedding something other than `https://ui.idenfy.com`?** If your iFrame `src` is the redirect URL (`https://ivs.idenfy.com/api/v2/redirect?...`) or a custom UI domain, name the final UI origin in the allow list:

  ```html theme={"system"}
  allow="camera https://ui.idenfy.com; fullscreen https://ui.idenfy.com; clipboard-write https://ui.idenfy.com"
  ```

  The default allowlist only covers the iFrame's own `src` origin, so permissions are lost after the cross-origin redirect. With a custom UI domain, use that domain here and in the `message` origin check below.
</Note>

<Note>
  **Camera fallback.** iDenfy can enable a fallback on your account for when the camera still fails inside the iFrame, most often because camera permission was not granted to it. The camera error pop-up then offers **Continue in new tab** alongside **Try again**. The user continues the same verification in a new browser tab, outside the iFrame, from the capture step that failed, without repeating the steps already completed. The fallback works on desktop and mobile web, and it is off by default. [Contact us](https://idenfy-ivs.atlassian.net/servicedesk/customer/portal/1) to enable it. It does not replace the `allow` attributes above.
</Note>

<Warning>
  **Skip the `sandbox` attribute.** Bank verification and Digital ID flows open popups, and sandboxing blocks them. If your security policy requires it, include at least:

  ```html theme={"system"}
  sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
  ```

  `allow-popups` lets the popup open; `allow-popups-to-escape-sandbox` keeps the identity provider's login page working.
</Warning>

### Listening for Verification Results

When the verification session ends, the iFrame posts a `message` event to the parent window. You **must** listen for this event to know the outcome.

```javascript theme={"system"}
window.addEventListener("message", function (event) {
  // Verify the origin for security
  if (event.origin !== "https://ui.idenfy.com") return;

  // Native WebViews and some proxies stringify the payload — handle both forms
  let data = event.data;
  if (typeof data === "string") {
    try { data = JSON.parse(data); } catch { return; }
  }
  if (!data || typeof data !== "object") return;

  console.log("Status:", data.status);
  console.log("Manual status:", data.manualStatus);
  console.log("Auto suspected:", data.autoSuspected);
  console.log("Manual suspected:", data.manualSuspected);
});
```

#### Message Event Fields

| Field | Type | Description |
| - | - | - |
| `status` | string | Automatic review result: `approved`, `failed`, or `unverified`. |
| `manualStatus` | string | Manual (human) review result: `approved`, `failed`, or `waiting`. |
| `autoSuspected` | boolean | `true` if the automatic check flagged the verification as suspicious. |
| `manualSuspected` | boolean | `true` if a human reviewer flagged the verification as suspicious. |

<Note>
  All status values are delivered **lowercase**. `manualStatus` will be `waiting` immediately after the session completes. The final manual review result is delivered asynchronously via [webhook](/kyc/webhooks). Do not treat `waiting`, or an `unverified` `status`, as a final state.
</Note>

<Warning>
  Do **not** set `successUrl`, `errorUrl`, or `unverifiedUrl` when using the iFrame integration. These parameters cause the iFrame to redirect internally, which breaks the embedded flow. Use the `message` event instead to handle outcomes.
</Warning>

### Full HTML Example

```html theme={"system"}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    #idenfy-iframe { border: none; width: 670px; height: 800px; }
    @media (max-width: 575px) {
      #idenfy-iframe { width: 100%; height: 100vh; }
    }
  </style>
</head>
<body>
  <!-- See "Required Attributes" above before changing the allow list or adding a sandbox attribute -->
  <iframe id="idenfy-iframe" allow="camera; fullscreen; clipboard-write" allowfullscreen
    src="https://ui.idenfy.com/?authToken=YOUR_TOKEN"></iframe>
  <script>
    window.addEventListener("message", (e) => {
      if (e.origin !== "https://ui.idenfy.com") return;
      let data = e.data;
      if (typeof data === "string") {
        try { data = JSON.parse(data); } catch { return; }
      }
      if (!data || typeof data !== "object") return;

      if (data.status === "approved") {
        // Automatic check passed — show success state
      } else if (data.status === "failed") {
        // Automatic check failed — show failure state
      } else if (data.status === "unverified") {
        // Could not determine automatically — wait for manual review
      }
      // Always check manualStatus via webhook for the final result
    });
  </script>
</body>
</html>
```

***

## Redirect Integration

If you prefer a simpler integration without iFrame embedding, redirect your user to the iDenfy verification page. Your user leaves your site, completes verification, and returns to your redirect URL.

### Redirect URL

```
https://ivs.idenfy.com/api/v2/redirect?authToken={authToken}
```

Replace `{authToken}` with the token from the [session creation endpoint](/kyc/generate-token).

<Tip>
  When using redirect, you can configure `successUrl`, `errorUrl`, and `unverifiedUrl` during session creation. iDenfy will redirect the user back to the appropriate URL after the session ends.
</Tip>

***

## Why There Is No Web SDK

<Info>
  iDenfy intentionally does not provide a JavaScript Web SDK. The iFrame approach is the recommended integration for web applications.
</Info>

**Benefits of the iFrame-only approach:**

* **Always up to date** -- your integration automatically uses the latest UI, liveness detection, and document recognition without any code changes on your side.
* **Lighter integration** -- no package to install, no bundle size impact, no dependency management.
* **Future-proof** -- new features, supported documents, and UX improvements are available immediately.
* **No version management** -- you never need to track SDK releases or handle breaking changes.

***

## Next Steps

<Columns cols={2}>
  <Card title="Set Up Webhooks" icon="bell" href="/kyc/webhooks">
    Receive real-time verification results on your server.
  </Card>

  <Card title="Mobile SDKs" icon="mobile" href="/sdks/overview">
    Native Android and iOS SDKs for mobile apps.
  </Card>
</Columns>


## Related topics

- [Quickstart](/quickstart.md)
- [Identity Verification API (KYC)](/kyc/overview.md)
- [Standalone Bank Card Verification](/guides/dashboard/bank-card/standalone-bank-card-verification.md)
- [Face Auth iFrame](/face-authentication/iframe.md)
- [KYB iFrame](/kyb/iframe.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.