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.
Embed the Didit verification flow directly within your application using an iframe. This provides a seamless experience without redirecting users away from your site.
Overview
Feature UniLink (No Backend) API Session (With Backend) Setup Time < 1 minute 5-10 minutes Backend Required ❌ No ✅ Yes Custom vendor_data ❌ No ✅ Yes Custom metadata ❌ No ✅ Yes Per-session Callback ❌ No ✅ Yes Session Tracking ❌ No ✅ Yes
UniLink Iframe (No Backend Required)
The fastest way to get started – just copy and paste your UniLink URL.
What You Need
A Didit workflow (created in the Didit Console )
Your UniLink URL (click Copy Link on your workflow)
Implementation
< iframe
src = "https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64"
style = "width: 100%; height: 700px; border: none;"
allow = "camera; microphone; fullscreen; autoplay; encrypted-media"
></ iframe >
⚠️ Required : The allow attribute is mandatory for camera access during liveness detection.
Key Benefits
Less than 1 minute setup — No backend, no API keys
Zero configuration — Callback URL set in workflow settings
Ideal for MVPs — Get started immediately
API Session Iframe (With Backend)
For advanced integrations that need per-session customization.
When to Use
Pass custom vendor_data or metadata per session
Set different callback URLs per session
Track sessions server-side before verification starts
Associate sessions with your user IDs
Implementation
Step 1: Create a session (backend)
// 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_ACCESS_TOKEN ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
workflow_id: process . env . DIDIT_WORKFLOW_ID ,
vendor_data: userId ,
callback: 'https://yourapp.com/verification-callback' ,
metadata: JSON . stringify ({
source: 'web-app' ,
timestamp: Date . now ()
})
})
});
const { session_id , verification_url } = await response . json ();
res . json ({ sessionId: session_id , verificationUrl: verification_url });
});
Step 2: Embed in iframe (frontend)
< iframe
id = "didit-verification"
src = "" <!-- Set dynamically from API response -- >
style="width: 100%; height: 650px; border: none;"
allow="camera; microphone; fullscreen; autoplay; encrypted-media"
> </ 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 >
Modal Implementation
For a polished modal experience that overlays your page:
HTML/CSS/JS
<! 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 ( 4 px );
}
.didit-modal-container {
position : absolute ;
top : 50 % ;
left : 50 % ;
transform : translate ( -50 % , -50 % );
width : 90 % ;
max-width : 480 px ;
height : 85 vh ;
max-height : 750 px ;
background : white ;
border-radius : 16 px ;
overflow : hidden ;
box-shadow : 0 25 px 50 px -12 px rgba ( 0 , 0 , 0 , 0.25 );
}
.didit-modal-close {
position : absolute ;
top : 12 px ;
right : 12 px ;
z-index : 10 ;
width : 32 px ;
height : 32 px ;
border : none ;
background : rgba ( 0 , 0 , 0 , 0.1 );
border-radius : 50 % ;
cursor : pointer ;
font-size : 18 px ;
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; fullscreen; autoplay; encrypted-media"
></ 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 >
React Component
A reusable React component for modal-based verification:
import { useState , useEffect } from 'react' ;
interface DiditInContextProps {
verificationUrl ?: string ;
workflowId ?: string ;
isOpen : boolean ;
onClose : () => void ;
onComplete ?: ( sessionId : string , status : string ) => void ;
}
export function DiditInContext ({
verificationUrl ,
workflowId ,
isOpen ,
onClose ,
onComplete
} : DiditInContextProps ) {
const [ iframeSrc , setIframeSrc ] = useState < string >( '' );
useEffect (() => {
if ( isOpen ) {
if ( verificationUrl ) {
setIframeSrc ( verificationUrl );
} else if ( workflowId ) {
// Use UniLink format
setIframeSrc ( `https://verify.didit.me/u/ ${ btoa ( workflowId ) } ` );
}
document . body . style . overflow = 'hidden' ;
} else {
setIframeSrc ( '' );
document . body . style . overflow = '' ;
}
}, [ isOpen , verificationUrl , workflowId ]);
// Listen for postMessage from iframe
useEffect (() => {
const handleMessage = ( event : MessageEvent ) => {
if ( event . origin !== 'https://verify.didit.me' ) return ;
if ( event . data ?. type === 'verification_complete' && onComplete ) {
onComplete ( event . data . sessionId , event . 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; fullscreen; autoplay; encrypted-media"
title = "Didit Verification"
/>
</ div >
</ div >
);
}
Usage
import { useState } from 'react' ;
import { DiditInContext } from './DiditInContext' ;
function App () {
const [ isVerificationOpen , setIsVerificationOpen ] = useState ( false );
return (
<>
< button onClick = { () => setIsVerificationOpen ( true ) } >
Verify Identity
</ button >
< DiditInContext
workflowId = "your-workflow-id"
isOpen = { isVerificationOpen }
onClose = { () => setIsVerificationOpen ( false ) }
onComplete = { ( sessionId , status ) => {
console . log ( `Verification ${ status } : ${ sessionId } ` );
if ( status === 'Approved' ) {
// Navigate to success page
}
} }
/>
</>
);
}
Vue Component
< 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; fullscreen; autoplay; encrypted-media"
/ >
</ div >
</ div >
</ Teleport >
</ template >
< script setup lang = "ts" >
import { computed , watch , onMounted , onUnmounted } from 'vue' ;
const props = defineProps <{
isOpen : boolean ;
verificationUrl ?: string ;
workflowId ?: string ;
}>();
const emit = defineEmits <{
close : [];
complete : [ sessionId : string , status : string ];
}>();
const iframeSrc = computed (() => {
if ( ! props . isOpen ) return '' ;
if ( props . verificationUrl ) return props . verificationUrl ;
if ( props . workflowId ) return `https://verify.didit.me/u/ ${ btoa ( props . workflowId ) } ` ;
return '' ;
});
// Handle escape key
const handleEscape = ( e : KeyboardEvent ) => {
if ( e . key === 'Escape' && props . isOpen ) emit ( 'close' );
};
// Handle postMessage
const handleMessage = ( event : MessageEvent ) => {
if ( event . origin !== 'https://verify.didit.me' ) return ;
if ( event . data ?. type === 'verification_complete' ) {
emit ( 'complete' , event . data . sessionId , event . 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 >
Configuration
Required Permissions
Always include these permissions for camera and media access:
allow="camera; microphone; fullscreen; autoplay; encrypted-media"
Permission Purpose cameraDocument scanning and face capture microphoneVideo recording for liveness detection fullscreenOptimal capture experience autoplayImmediate camera activation encrypted-mediaSecure media handling
Responsive Design
.didit-container {
position : relative ;
width : 100 % ;
max-width : 500 px ;
margin : 0 auto ;
}
.didit-iframe {
width : 100 % ;
height : 80 vh ;
min-height : 600 px ;
max-height : 800 px ;
border : none ;
border-radius : 12 px ;
}
/* Mobile adjustments */
@media ( max-width : 640 px ) {
.didit-iframe {
height : 100 vh ;
min-height : unset ;
max-height : unset ;
border-radius : 0 ;
}
}
Content Security Policy (CSP)
If you use CSP, add Didit to your frame-src directive:
Content-Security-Policy: frame-src https://verify.didit.me;
Cross-Device Verification
The InContext iframe automatically supports cross-device verification:
User starts verification on desktop
If camera is unavailable, a QR code is shown
User scans QR code on mobile
User completes verification on mobile
Desktop iframe automatically updates with result
This happens automatically – no additional configuration needed.
Troubleshooting
Camera Not Working
Ensure allow="camera; microphone" is set on the iframe
Check that your site is served over HTTPS
Verify the user has granted camera permissions to your domain
Try the Redirect method if iframe camera access fails
Iframe Not Loading
Check for Content Security Policy (CSP) issues
Add https://verify.didit.me to your frame-src directive
Check browser console for errors
postMessage Not Received
Verify you’re listening for the correct origin (https://verify.didit.me)
Check that the event listener is added before opening the iframe
Ensure the callback URL in your workflow matches
Example Repository
GitHub Repository View source code and examples on GitHub