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 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
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:
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 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');
});