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

# Verificación de identidad en iframe: KYC web integrado

> Integra KYC, KYB, AML y liveness de Didit en tu web vía iframe: UniLink sin código o API. Desde $0.33 por KYC completo, $10 gratis/mes, sin contratos.



Prompt de integración con iframe
        Copiar el prompt al portapapeles



      
      

\<pre>

\`Embed Didit identity verification into my web page using an iframe.

\## Two Options

\### Option A: UniLink (no backend — fastest setup)
Copy your UniLink URL from Didit Console > Workflows > Copy Link.
It looks like: https://verify.didit.me/u/<BASE64_WORKFLOW_ID>
Embed it directly:

\<iframe
src="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64"
style="width: 100%; height: 700px; border: none; border-radius: 12px;"
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
/>

No backend needed. Results appear in your Didit Console dashboard.

\### Option B: API session (full control)
1\. Backend creates session: POST /v3/session/ → response includes "url"
2\. Frontend embeds that "url" as the iframe src
3\. Listen for postMessage events from the iframe (event.origin === 'https://verify.didit.me', or your white-label domain)
4\. Backend receives the full, signed decision via webhook (status.updated)

\## postMessage contract (key events — full table below)
Every message is an object: { type: "didit:<event>", data: { ... }, timestamp: <ms epoch> }
Completion event: type === "didit:completed", data: { sessionId, status }
Other events: didit:ready { sessionId }, didit:started, didit:step_started { step },
didit:step_completed { step, nextStep }, didit:step_changed { step, previousStep },
didit:status_updated { status }, didit:error { error, step }, didit:cancelled, didit:close_request,
didit:layout { contentHeight, colorScheme: "light" | "dark", dir: "ltr" | "rtl" }
The payload is NESTED under event.data.data (event.data is the envelope).
For your own iframe, add sdk_presentation=embedded with the URL API to receive didit:layout.

\## Iframe size (redesigned flow)
\- Window 1024px and wider: 960px by 660px (at most 90% of the window)
\- Window 541px to 1023px: 500px wide, height = didit:layout contentHeight (700px until the first message, at most 90% of the window height)
\- Window 540px and below: full screen

\## Frontend Code (Option B — React)
function VerificationIframe({ verificationUrl }) {
useEffect(() => {
function handleMessage(event) {
  if (event.origin !== 'https://verify.didit.me') return; // use your white-label domain if configured
  const { type, data } = event.data || {};
  if (type === 'didit:completed') {
    // data.sessionId, data.status: "Approved" | "Declined" | "In Review" // open string — other session statuses possible in edge flows
    // Trust the webhook on your backend for the canonical decision.
  }
}
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);

return (
\<iframe
  src={verificationUrl}
  style={{ width: '100%', height: '700px', border: 'none', borderRadius: '12px' }}
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
/>
);
}

\## Required client-side permissions
If you front your site with a reverse proxy (nginx, Cloudflare, etc.) make sure it does not
strip the Permissions-Policy / Feature-Policy headers — camera and microphone access must be
allowed for your origin or the iframe will be unable to start the camera.

\## Required iframe Permissions
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
camera: document and face capture. microphone: optional audio during video capture.
geolocation: the location step. clipboard-write: the copy buttons.
digital-credentials-get: sharing a digital ID from a wallet such as Google Wallet.

\## Backend: Create Session
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "vendor_data": userId }
201 response fields (all 10, per OpenAPI):
\{ "session_id", "session_number", "session_token", "url", "vendor_data", "metadata",
"status", "workflow_id", "workflow_version", "callback" }
Use response.url as the iframe src — never build the URL from session_token by hand.

\## Rate Limits
600 session-create requests per minute per API key (falls back to bearer token, then client IP), plus a shared 300 write-requests/minute budget across all endpoints. HTTP 429 with Retry-After when exceeded.

\## Environment Variables
\- DIDIT_API_KEY (backend only)
\- DIDIT_WORKFLOW_ID (backend only)

\## Docs
\- Iframe guide: https://docs.didit.me/integration/web-sdks/incontext-iframe
\- Create Session: https://docs.didit.me/sessions-api/create-session
\- Webhooks: https://docs.didit.me/integration/webhooks`

\</pre>



      
      

Pegar en

Integra el flujo de verificación de Didit directamente en tu aplicación mediante un iframe. Así ofreces una experiencia fluida sin redirigir a los usuarios fuera de tu sitio.## Visión general| Función | UniLink (sin backend) | Sesión de API (con backend) |
| - | - | - |
| Tiempo de configuración | \< 1 minuto | 5-10 minutos |
| Requiere backend | ❌ No | ✅ Sí |
| `vendor_data` personalizado | ❌ No | ✅ Sí |
| `metadata` personalizado | ❌ No | ✅ Sí |
| Callback por sesión | ❌ No | ✅ Sí |
| Seguimiento de sesiones | ❌ No | ✅ Sí |***## Iframe con UniLink (sin backend)La forma más rápida de empezar: solo copia y pega tu URL de UniLink.### Qué necesitas1) Un flujo de verificación (workflow) de Didit (creado en la [Didit Console](https://business.didit.me))
2) Tu URL de UniLink (haz clic en **Copy Link** en tu flujo)### Implementación```html theme={null}
<iframe 
  src="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64"
  style="width: 100%; height: 700px; border: none;" 
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>
```> ⚠️ **Obligatorio**: el atributo `allow` es imprescindible para acceder a la cámara durante la detección de vida.### Ventajas principales- **Configuración en menos de 1 minuto**: sin backend y sin claves de API
- **Cero configuración**: la URL de callback se define en la configuración del flujo
- **Ideal para MVP**: empieza de inmediato***## Iframe con sesión por API (con backend)Para integraciones avanzadas que necesitan personalización por sesión.### Cuándo usarlo- Enviar `vendor_data` o `metadata` personalizados por sesión
- Definir URL de callback distintas por sesión
- Hacer seguimiento de las sesiones desde el servidor antes de que empiece la verificación
- Asociar las sesiones con los ID de tus usuarios### Implementación**Paso 1: Crear una sesión (backend)**La respuesta de creación de sesión incluye un campo llamado **`url`**: úsalo como `src` del iframe.```javascript theme={null}
// Node.js / Express
app.post('/api/create-verification', async (req, res) => {
  const { userId } = req.body;

  const response = await fetch('https://verification.didit.me/v3/session/', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.DIDIT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: userId,
      callback: 'https://yourapp.com/verification-callback',
      metadata: { source: 'web-app', timestamp: Date.now() },
    }),
  });

  if (!response.ok) {
    return res.status(response.status).send(await response.text());
  }

  // 201 per OpenAPI: { session_id, session_number, session_token, url, vendor_data,
  //                    metadata, status, workflow_id, workflow_version, callback }
  const session = await response.json();
  res.json({ sessionId: session.session_id, verificationUrl: session.url });
});
```**Paso 2: Insertar en un iframe (frontend)**```html theme={null}
<iframe 
  id="didit-verification"
  src="" <!-- Set dynamically from API response -->
  style="width: 100%; height: 650px; border: none;" 
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>

<script>
  async function startVerification() {
    const response = await fetch('/api/create-verification', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: 'user-123' })
    });
    
    const { verificationUrl } = await response.json();
    document.getElementById('didit-verification').src = verificationUrl;
  }
</script>
```***## Escuchar eventos (postMessage)La página de verificación envía eventos a la ventana que la contiene. Todos los mensajes tienen esta estructura:```typescript theme={null}
{
  type: 'didit:<event>',   // e.g. 'didit:completed'
  data: { /* payload */ }, // event-specific; may be undefined
  timestamp: 1718000000000 // ms epoch
}
```El payload está **anidado**: lee `event.data.data.sessionId`, no `event.data.sessionId`:```javascript theme={null}
window.addEventListener('message', (event) => {
  // Use your white-label domain here if you have one configured
  if (event.origin !== 'https://verify.didit.me') return;

  const { type, data } = event.data || {};

  if (type === 'didit:ready') {
    console.log('Session ID:', data.sessionId); // available as soon as the page loads
  }
  if (type === 'didit:completed') {
    console.log('Done:', data.sessionId, data.status); // e.g. "Approved" | "Declined" | "In Review"
    // UI hint only — the canonical decision arrives on your backend via webhook
  }
});
```Eventos principales: `didit:ready` (`{ sessionId }`), `didit:started`, `didit:step_started` / `didit:step_completed` / `didit:step_changed` (`{ step, ... }`), `didit:status_updated` (`{ status }`), `didit:completed` (`{ sessionId, status }`), `didit:cancelled`, `didit:error` (`{ error, step? }`), `didit:close_request` y `didit:layout` (`{ contentHeight, colorScheme, dir }`, consulta [más abajo](#dimensionar-el-iframe-con-diditlayout)). La [referencia de eventos del SDK de JavaScript](https://docs.didit.me/es/integration/web-sdks/javascript-sdk.md#referencia-de-eventos) enumera los eventos de verificación disponibles como callbacks tipados. A partir de la versión 0.5.0, el SDK gestiona los mensajes de layout internamente en lugar de reenviarlos a `onEvent`.### Dimensionar el iframe con `didit:layout`La página de verificación te indica cuánto espacio necesita mediante un mensaje `didit:layout`. Envía uno al cargarse y otro cada vez que cambian la altura de su contenido, el tema o la dirección del texto:```typescript theme={null}
{
  type: 'didit:layout',
  data: {
    contentHeight: 612,    // CSS px
    colorScheme: 'light',  // 'light' | 'dark'
    dir: 'ltr'             // 'ltr' | 'rtl'
  },
  timestamp: 1718000000000
}
```| Campo | Tipo | Descripción |
| - | - | - |
| `contentHeight` | `number` | La altura natural del contenido de la página en píxeles CSS, incluida la barra superior |
| `colorScheme` | `'light' \| 'dark'` | El tema con el que se muestra la página. Con colores de marca blanca, lo determina tu color de fondo, no la configuración del dispositivo |
| `dir` | `'ltr' \| 'rtl'` | La dirección del texto en el idioma de la página |> [!NOTE]
>
> Para recibir `didit:layout` en tu propio iframe, añade `sdk_presentation=embedded` a su URL de verificación. A partir de la versión 0.5.0, el [SDK de JavaScript](https://docs.didit.me/es/integration/web-sdks/javascript-sdk.md) configura la presentación por ti. Sin un parámetro de presentación, la página usa su layout independiente y no envía mensajes de layout.Este host sigue los [tamaños recomendados](#tamaño-del-iframe): una tarjeta fija a partir de 1024px de ancho, pantalla completa a 540px o menos y, entre ambos, un iframe de 500px de ancho que adopta la altura que indica la página:```html theme={null}
<iframe
  id="didit-verification"
  class="didit-iframe"
  title="Didit verification"
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>

<style>
  /* 541px to 1023px wide: 500px wide and as tall as the content */
  .didit-iframe {
    display: block;
    width: 500px;
    max-width: 100%;
    height: var(--didit-content-height, 700px); /* 700px until the first didit:layout */
    max-height: 90vh;
    max-height: 90dvh;
    margin: 0 auto;
    border: none;
    border-radius: 16px;
  }

  /* 1024px and wider: the computer card */
  @media (min-width: 1024px) {
    .didit-iframe {
      width: 960px;
      max-width: 90vw;
      height: 660px;
    }
  }

  /* 540px and below: full screen */
  @media (max-width: 540px) {
    .didit-iframe {
      position: fixed;
      inset: 0;
      width: 100%;
      height: 100vh;
      height: 100dvh;
      max-height: none;
      border-radius: 0;
    }
  }
</style>

<script>
  const DIDIT_ORIGIN = 'https://verify.didit.me'; // or your white-label domain
  const iframe = document.getElementById('didit-verification');

  // verificationUrl: the session `url` from your backend, or your UniLink
  const src = new URL(verificationUrl);
  src.searchParams.set('sdk_presentation', 'embedded');
  window.addEventListener('message', (event) => {
    if (event.origin !== DIDIT_ORIGIN || event.source !== iframe.contentWindow) return;
    const { type, data } = event.data || {};
    if (type !== 'didit:layout') return;
    const height = data?.contentHeight;
    if (typeof height !== 'number' || !Number.isFinite(height) || height <= 0) return;

    // Only the 541px to 1023px size reads it; the other two sizes are fixed
    iframe.style.setProperty('--didit-content-height', `${height}px`);
  });
  iframe.src = src.toString();
</script>
```Entre 541px y 1023px, este ejemplo usa una altura inicial de 700px hasta que llega un mensaje de layout, con un máximo del 90% de la altura visible de la ventana. Los tamaños para computadoras y teléfonos se aplican de inmediato. En teléfonos, el iframe cubre la ventana, así que ofrece en tu host una forma de salir de la verificación. Usa `colorScheme` y `dir` para que los controles que dibujes alrededor del iframe coincidan con el tema y la dirección del texto de la página.Si la conexión del usuario se cae, la página muestra una pantalla "No internet connection" que se cierra sola cuando se recupera la conexión. Si el usuario elige **Exit Verification** en ella, la página envía `didit:error` con `error: "network_error"` y después `didit:cancelled`: cierra el iframe al recibir `didit:cancelled`.***## Implementación en modalPara una experiencia pulida con el modal que se superpone a tu página:### HTML/CSS/JS```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <style>
    .didit-modal-overlay {
      display: none;
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.6);
      z-index: 9999;
      backdrop-filter: blur(4px);
    }
    
    .didit-modal-container {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 90%;
      max-width: 480px;
      height: 85vh;
      max-height: 750px;
      background: white;
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    }
    
    .didit-modal-close {
      position: absolute;
      top: 12px;
      right: 12px;
      z-index: 10;
      width: 32px;
      height: 32px;
      border: none;
      background: rgba(0, 0, 0, 0.1);
      border-radius: 50%;
      cursor: pointer;
      font-size: 18px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .didit-modal-close:hover {
      background: rgba(0, 0, 0, 0.2);
    }
    
    .didit-iframe {
      width: 100%;
      height: 100%;
      border: none;
    }
  </style>
</head>
<body>
  <button onclick="openVerification()">Verify Identity</button>

  <div id="didit-modal" class="didit-modal-overlay">
    <div class="didit-modal-container">
      <button class="didit-modal-close" onclick="closeVerification()">✕</button>
      <iframe 
        id="didit-iframe"
        class="didit-iframe"
        allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
      ></iframe>
    </div>
  </div>

  <script>
    const UNILINK_URL = 'https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64';
    
    function openVerification() {
      document.getElementById('didit-iframe').src = UNILINK_URL;
      document.getElementById('didit-modal').style.display = 'block';
      document.body.style.overflow = 'hidden';
    }
    
    function closeVerification() {
      document.getElementById('didit-iframe').src = '';
      document.getElementById('didit-modal').style.display = 'none';
      document.body.style.overflow = '';
    }
    
    // Close on escape key
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') closeVerification();
    });
    
    // Close on overlay click
    document.getElementById('didit-modal').addEventListener('click', (e) => {
      if (e.target.id === 'didit-modal') closeVerification();
    });
  </script>
</body>
</html>
```***## Componente de ReactUn componente de React reutilizable para la verificación en un modal:```tsx theme={null}
import { useState, useEffect } from 'react';

interface DiditInContextProps {
  /**
   * Either the `url` returned by POST /v3/session/ (API session)
   * or your UniLink URL copied from the Console (Workflows → Copy Link).
   * Don't derive the UniLink yourself — the path segment is a 22-character
   * base64url encoding of the workflow UUID's raw bytes, not btoa(workflowId).
   */
  verificationUrl: string;
  isOpen: boolean;
  onClose: () => void;
  onComplete?: (sessionId: string, status: string) => void;
}

export function DiditInContext({ 
  verificationUrl, 
  isOpen, 
  onClose,
  onComplete 
}: DiditInContextProps) {
  const [iframeSrc, setIframeSrc] = useState<string>('');

  useEffect(() => {
    if (isOpen) {
      setIframeSrc(verificationUrl);
      document.body.style.overflow = 'hidden';
    } else {
      setIframeSrc('');
      document.body.style.overflow = '';
    }
  }, [isOpen, verificationUrl]);

  // Listen for postMessage from iframe
  // Messages look like: { type: 'didit:<event>', data: {...}, timestamp }
  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      // Use your white-label domain here if you have one configured
      if (event.origin !== 'https://verify.didit.me') return;

      if (event.data?.type === 'didit:completed' && onComplete) {
        onComplete(event.data.data?.sessionId, event.data.data?.status);
        onClose();
      }
    };

    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [onComplete, onClose]);

  // Handle escape key
  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isOpen) onClose();
    };
    
    document.addEventListener('keydown', handleEscape);
    return () => document.removeEventListener('keydown', handleEscape);
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return (
    <div 
      className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      <div className="relative w-[90%] max-w-[480px] h-[85vh] max-h-[750px] bg-white rounded-2xl overflow-hidden shadow-2xl">
        <button 
          onClick={onClose}
          className="absolute top-3 right-3 z-10 w-8 h-8 rounded-full bg-black/10 hover:bg-black/20 flex items-center justify-center"
          aria-label="Close"
        >
          ✕
        </button>
        <iframe 
          src={iframeSrc}
          className="w-full h-full border-0"
          allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
          title="Didit Verification"
        />
      </div>
    </div>
  );
}
```### Uso```tsx theme={null}
import { useState } from 'react';
import { DiditInContext } from './DiditInContext';

function App() {
  const [isVerificationOpen, setIsVerificationOpen] = useState(false);
  
  return (
    <>
      <button onClick={() => setIsVerificationOpen(true)}>
        Verify Identity
      </button>
      
      <DiditInContext
        verificationUrl="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64" // UniLink from Console, or the API session `url`
        isOpen={isVerificationOpen}
        onClose={() => setIsVerificationOpen(false)}
        onComplete={(sessionId, status) => {
          console.log(`Verification ${status}: ${sessionId}`);
          if (status === 'Approved') {
            // Navigate to success page
          }
        }}
      />
    </>
  );
}
```***## Componente de Vue```vue theme={null}
<template>
  <Teleport to="body">
    <div 
      v-if="isOpen"
      class="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center"
      @click.self="$emit('close')"
    >
      <div class="relative w-[90%] max-w-[480px] h-[85vh] max-h-[750px] bg-white rounded-2xl overflow-hidden shadow-2xl">
        <button 
          @click="$emit('close')"
          class="absolute top-3 right-3 z-10 w-8 h-8 rounded-full bg-black/10 hover:bg-black/20 flex items-center justify-center"
        >
          ✕
        </button>
        <iframe 
          :src="iframeSrc"
          class="w-full h-full border-0"
          allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
        />
      </div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { computed, watch, onMounted, onUnmounted } from 'vue';

const props = defineProps<{
  isOpen: boolean;
  // The `url` from POST /v3/session/, or your UniLink URL copied from the
  // Console (Workflows → Copy Link). Don't derive the UniLink with btoa() —
  // its path segment is base64url of the workflow UUID's raw bytes.
  verificationUrl: string;
}>();

const emit = defineEmits<{
  close: [];
  complete: [sessionId: string, status: string];
}>();

const iframeSrc = computed(() => (props.isOpen ? props.verificationUrl : ''));

// Handle escape key
const handleEscape = (e: KeyboardEvent) => {
  if (e.key === 'Escape' && props.isOpen) emit('close');
};

// Handle postMessage — messages look like { type: 'didit:<event>', data: {...}, timestamp }
const handleMessage = (event: MessageEvent) => {
  // Use your white-label domain here if you have one configured
  if (event.origin !== 'https://verify.didit.me') return;
  if (event.data?.type === 'didit:completed') {
    emit('complete', event.data.data?.sessionId, event.data.data?.status);
  }
};

onMounted(() => {
  document.addEventListener('keydown', handleEscape);
  window.addEventListener('message', handleMessage);
});

onUnmounted(() => {
  document.removeEventListener('keydown', handleEscape);
  window.removeEventListener('message', handleMessage);
});

// Lock body scroll when open
watch(() => props.isOpen, (isOpen) => {
  document.body.style.overflow = isOpen ? 'hidden' : '';
});
</script>
```***## Configuración### Permisos necesariosUsa esta lista completa de permisos para la captura, la ubicación, la copia y la compatibilidad multimedia:```html theme={null}
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
```| Permiso | Para qué se usa y qué ocurre sin él |
| - | - |
| `camera` | Escaneo de documentos y captura facial. Sin él, la cámara no puede iniciarse y el usuario ve instrucciones para permitir el acceso a la cámara |
| `microphone` | Audio opcional durante la captura en video del documento y del rostro. Sin él, la captura continúa sin audio |
| `geolocation` | El paso de ubicación lee la posición del dispositivo. Sin él, el usuario ve **El acceso a la ubicación está desactivado**, aunque haya permitido la ubicación en el navegador |
| `clipboard-write` | Copiar la referencia de la sesión o el enlace de verificación, también en la pantalla del navegador integrado en una aplicación. Sin él, la acción de copiar puede fallar y el usuario debe copiar manualmente el texto visible o la dirección del navegador |
| `fullscreen` | Permite que los controles multimedia soliciten la pantalla completa. Sin él, esos controles se quedan dentro del iframe |
| `autoplay` | Permite que los videos de instrucciones y las vistas previas de la cámara se reproduzcan automáticamente, según las reglas del navegador. Sin él, la reproducción puede esperar a una acción del usuario |
| `encrypted-media` | Se mantiene por compatibilidad con contenido multimedia protegido. Los pasos de captura actuales no lo requieren; sin él, se bloquearía la reproducción de contenido multimedia protegido |
| `digital-credentials-get` | Compartir una identificación digital desde una wallet como Google Wallet mediante la Digital Credentials API del navegador. Sin él, el navegador rechaza la solicitud a la wallet dentro de tu iframe, por lo que el usuario no puede compartir ahí una identificación desde la wallet |El atributo `allow` delega permisos; no anula la elección del usuario ni un encabezado `Permissions-Policy` más restrictivo en tu página anfitriona.### Tamaño del iframeEl flujo de verificación adapta su diseño al tamaño de su iframe. Dimensiona el iframe según la ventana en la que se muestra:| Ancho de la ventana | Tamaño recomendado del iframe |
| - | - |
| 1024px o más (escritorio) | 960px por 660px, como máximo el 90% del ancho y del alto de la ventana. Mantén este tamaño en todos los pasos |
| De 541px a 1023px | 500px de ancho y tan alto como el contenido: toma como altura el `contentHeight` del [mensaje `didit:layout`](#dimensionar-el-iframe-con-diditlayout), como máximo el 90% del alto de la ventana |
| 540px o menos (teléfono) | Pantalla completa: todo el ancho y todo el alto visible de la ventana, sin esquinas redondeadas |Para el rango intermedio, empieza con 500px por 700px hasta que llegue el primer mensaje `didit:layout`, con el mismo límite de altura. El [ejemplo de `didit:layout`](#dimensionar-el-iframe-con-diditlayout) aplica los tres tamaños, incluidos los de escritorio y teléfono antes de que llegue cualquier mensaje.### Content Security Policy (CSP)Si usas CSP, añade Didit a tu directiva `frame-src`:```
Content-Security-Policy: frame-src https://verify.didit.me;
```***## Verificación entre dispositivosEl iframe InContext admite automáticamente la verificación entre dispositivos:1) El usuario inicia la verificación en un equipo de escritorio
2) Si la cámara no está disponible, se muestra un código QR
3) El usuario escanea el código QR con un dispositivo móvil
4) El usuario completa la verificación en un dispositivo móvil
5) El iframe en el equipo de escritorio se actualiza automáticamente con el resultadoEsto ocurre automáticamente: no se necesita ninguna configuración adicional.***## Solución de problemas### La cámara no funciona1) Asegúrate de que el iframe incluya la [lista de permisos](#permisos-necesarios) completa
2) Comprueba que tu sitio se sirva por HTTPS
3) Verifica que el usuario haya concedido permisos de cámara a tu dominio
4) Prueba el método de [redirección](https://docs.didit.me/es/integration/web-sdks/web-redirect.md) si falla el acceso a la cámara desde el iframe### El iframe no carga1) Revisa si hay problemas con la Content Security Policy (CSP)
2) Añade `https://verify.didit.me` a tu directiva `frame-src`
3) Revisa la consola del navegador en busca de errores### No se recibe el postMessage1) Verifica que estés escuchando el origen correcto (`https://verify.didit.me` o tu dominio de marca blanca)
2) Comprueba que el listener de eventos se añada antes de abrir el iframe
3) Comprueba el nombre y la estructura del evento: los tipos llevan prefijo (`didit:completed`, no `verification_complete`) y el payload está anidado en `event.data.data`***## Repositorio de ejemplo> [card] [Repositorio de GitHub](https://github.com/didit-protocol/iframe-example)
>
> Consulta el código fuente y los ejemplos en GitHub***


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