> ## 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 h5 {
      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">
        <h5>Capture the front of the document</h5>
        <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">
        <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, it just 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>

<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

- [Face Auth iFrame](/face-authentication/iframe.md)
- [Choosing Your Integration](/guides/choosing-integration.md)
- [KYB iFrame](/kyb/iframe.md)
- [Quickstart](/quickstart.md)
- [SDK Overview](/sdks/overview.md)
