Verification Flow
Step-by-step guide to the user verification experience
Verification Flow
This guide explains what happens during a verification session from the user's perspective and how the system processes each step.
Overview
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ Create │────▶│ User │────▶│ Liveness │────▶│ Complete/ │
│ Session │ │ Visits │ │ Check │ │ KYC │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘Step 1: Session Creation
Your application creates a session via the API:
const { data: session } = await createSession({
age_target: 18,
redirect_url: 'https://your-app.com/verified',
webhook_url: 'https://your-app.com/webhooks/bouncer'
});
// Redirect user to verification (response is wrapped in data)
window.location.href = session.verify_url;System Actions:
- Session record created with status
CREATED - Unique session ID (UUID) generated
- Short code generated for mobile-friendly URLs
- Expiration timer starts
Step 2: User Visits Verification Page
When the user opens the verification URL:
Cookie bypass (when Force Verification is off): If the user has a valid verification cookie for the required age and the session does not have Force Verification enabled, they can be treated as already verified and the session completes without showing the verification flow. When Force Verification is on (per device or per API), the cookie is ignored and the user always goes through the full flow.
User Experience:
- Sees the organization's branding (logo, colors)
- Views instructions for the verification process
- Sees the target age requirement
System Actions:
- Status changes to
PENDING visited_attimestamp recorded- Mobile device detection
- Verification SDK initialized
QR Code Flow (Desktop)
If the user visits from a desktop:
- QR code is displayed
- User scans with mobile device
- Verification continues on mobile
- Desktop page auto-updates when complete
Step 3: Liveness Check
The 3D liveness check verifies the user is a real, present person.
User Experience:
- Camera permission requested
- User centers face in the frame
- Guided through head movements
- ~3-5 seconds to complete
System Actions:
- Status changes to
VERIFICATION_STARTED biometry_started_attimestamp recorded- Liveness verification performed
- Age estimation performed
Liveness Requirements
| Check | Purpose |
|---|---|
| 3D Depth Analysis | Prevents photos/videos |
| Movement Tracking | Confirms live presence |
| Texture Analysis | Detects masks/screens |
| Eye Tracking | Ensures user attention |
Step 4: Age Evaluation
After the liveness check, the system evaluates the user's age.
Age Estimation Groups
| Group | Age Range |
|---|---|
| 0-2 | Infant |
| 3-7 | Young child |
| 8-12 | Child |
| 13-17 | Teen |
| 18-24 | Young adult |
| 25-34 | Adult |
| 35-54 | Middle-aged |
| 55+ | Senior |
Decision Logic
IF estimated_age >= target_age AND NOT force_kyc THEN
→ Complete with SUCCESS
ELSE
→ Proceed to KYCStep 5: KYC (If Required)
KYC is triggered when:
- Age estimation is below target
force_kycis enabled on the session
User Experience:
- Instructions to prepare ID document
- Capture front of ID
- Capture back of ID (if applicable)
- Wait for processing
System Actions:
- Status changes to
VERIFICATION_KYC kyc_started_attimestamp recorded- Document OCR extraction
- Birth date parsing
- Face-to-document matching
- Spoof detection
Supported Documents
- Driver's licenses
- National ID cards
- Passports
- Residence permits
KYC Checks
| Check | Description |
|---|---|
| Face Match | Compare live face to ID photo |
| Document Authenticity | Detect fake/altered documents |
| OCR Extraction | Extract name, DOB, document number |
| Spoof Detection | Detect photos of IDs, screens |
Step 6: Completion
Success
User Experience:
- Success message displayed
- Automatically redirected to
redirect_url
System Actions:
- Status changes to
COMPLETED successset totruecompleted_attimestamp recorded- Webhook sent (if configured)
Failure
User Experience:
- Failure reason displayed
- Option to retry (if attempts remain)
- Redirected to
redirect_url
System Actions:
- Status changes to
COMPLETED successset tofalse- Failure reason stored in metadata
- Webhook sent (if configured)
Retry Handling
Users can retry verification if:
- Liveness check fails (camera issues, etc.)
- KYC document capture fails
The retry_count is incremented with each attempt.
Configure maximum retry attempts in your device or organization settings.
Duration Metrics
The system tracks several duration metrics:
| Metric | Description |
|---|---|
| Biometry Duration | Time spent on liveness check |
| KYC Duration | Time spent on ID scanning |
| Total Duration | Total time from visit to completion |
Access these via the admin dashboard for analytics.
Error States
Session Expired
If the user takes too long:
expires_attimestamp passed- User sees expiration message
- New session required
Technical Errors
- Camera permission denied
- Network connectivity issues
- SDK initialization failures
Integration Example
Complete flow handling:
// 1. Create session on your server
app.post('/start-verification', async (req, res) => {
const { data: session } = await bouncer.createSession({
age_target: 18,
redirect_url: `${process.env.APP_URL}/verification-callback`,
webhook_url: `${process.env.APP_URL}/webhooks/bouncer`,
metadata: [`user_id:${req.user.id}`]
});
// Store session ID for later lookup
await db.verifications.create({
userId: req.user.id,
bouncerSessionId: session.id,
status: 'pending'
});
res.redirect(session.verify_url);
});
// 2. Handle callback
app.get('/verification-callback', async (req, res) => {
// User has returned - check status via webhook or polling
res.render('verification-processing');
});
// 3. Handle webhook
app.post('/webhooks/bouncer', async (req, res) => {
const { session_id, success, status } = req.body;
const verification = await db.verifications.findByBouncerSession(session_id);
await db.verifications.update(verification.id, {
status: success ? 'verified' : 'failed',
completedAt: new Date()
});
// Notify user, unlock content, etc.
res.status(200).send('OK');
});