Biometric Verification
Biometric verification confirms that the person presenting an identity document is the same person pictured on that document. TrustGate provides enterprise-grade face comparison and liveness detection.
How It Works
1. Document photo extracted from ID
↓
2. User captures live selfie
↓
3. Liveness check confirms real person
↓
4. Face comparison between document and selfie
↓
5. Similarity score calculated
↓
6. Pass/fail decision based on threshold
Face Matching
Face matching compares the photo on an identity document with a selfie taken by the user during verification.
Match Confidence Scores
| Score Range | Confidence | Recommendation |
|---|---|---|
| 95-100% | Very High | Auto-pass |
| 85-94% | High | Pass with note |
| 70-84% | Medium | Manual review recommended |
| Below 70% | Low | Likely different person |
Factors Affecting Match Quality
Document Photo Quality:
- Resolution of printed/embedded photo
- Photo age vs. current appearance
- Lighting and print quality
Selfie Quality:
- Camera resolution
- Lighting conditions
- Face position and angle
- Obstructions (glasses, masks, hair)
Liveness Detection
Liveness detection prevents spoofing attacks where someone holds up a photo or video instead of their real face.
Anti-Spoofing Measures
TrustGate detects:
| Attack Type | Detection Method |
|---|---|
| Printed photo | Texture analysis, 3D depth |
| Screen display | Moiré pattern detection, reflection |
| Video replay | Motion analysis, synchronization |
| 3D mask | Skin texture, eye movement |
| Deepfake | Artifact detection, temporal consistency |
Liveness Check Flow
The SDK guides users through the liveness check:
- Face positioning - User centers face in frame
- Action prompts - Turn head, blink, smile (optional)
- Quality check - Verify lighting and focus
- Capture - Multiple frames captured
- Analysis - Server-side liveness verification
API Usage
Start Biometric Verification
curl -X POST https://api.bytrustgate.com/v1/biometrics/verify \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"applicant_id": "550e8400-e29b-41d4-a716-446655440000",
"document_id": "doc_123456",
"verification_type": "face_match_with_liveness"
}'
Response
{
"id": "bio_789012",
"applicant_id": "550e8400-e29b-41d4-a716-446655440000",
"verification_type": "face_match_with_liveness",
"status": "pending",
"session_token": "session_abc123xyz",
"session_url": "https://verify.bytrustgate.com/biometric/session_abc123xyz",
"expires_at": "2025-01-20T11:00:00Z"
}
Upload Selfie (Server-side)
For server-side implementations:
curl -X POST https://api.bytrustgate.com/v1/biometrics/bio_789012/selfie \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "image=@selfie.jpg"
Python Example
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.bytrustgate.com/v1"
# Start biometric verification
verification = requests.post(
f"{BASE_URL}/biometrics/verify",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"applicant_id": applicant_id,
"document_id": document_id,
"verification_type": "face_match_with_liveness",
},
).json()
# Upload selfie
with open("selfie.jpg", "rb") as f:
result = requests.post(
f"{BASE_URL}/biometrics/{verification['id']}/selfie",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": f},
).json()
print(f"Face match: {result['face_match']['similarity']}%")
print(f"Liveness: {result['liveness']['is_live']}")
Verification Results
Successful Verification
{
"id": "bio_789012",
"status": "passed",
"face_match": {
"similarity": 96.5,
"confidence": "very_high",
"document_face_quality": 0.92,
"selfie_face_quality": 0.95
},
"liveness": {
"is_live": true,
"confidence": 0.98,
"checks_performed": [
"texture_analysis",
"depth_estimation",
"motion_detection"
]
},
"completed_at": "2025-01-20T10:35:22Z"
}
Failed Verification
{
"id": "bio_789012",
"status": "failed",
"failure_reason": "face_mismatch",
"face_match": {
"similarity": 45.2,
"confidence": "low",
"document_face_quality": 0.88,
"selfie_face_quality": 0.91
},
"liveness": {
"is_live": true,
"confidence": 0.96
},
"completed_at": "2025-01-20T10:35:22Z"
}
Verification Types
| Type | Description | Use Case |
|---|---|---|
face_match_only | Compare document to selfie | Low-risk, quick verification |
liveness_only | Confirm live person | Re-verification, session check |
face_match_with_liveness | Both checks combined | Standard KYC (recommended) |
SDK Integration
Web SDK
<script src="https://cdn.bytrustgate.com/sdk/v1/biometrics.js"></script>
<script>
const biometrics = new TrustGateBiometrics({
sessionToken: "session_abc123xyz",
containerId: "biometric-container",
onComplete: (result) => {
console.log("Biometric verification complete:", result);
},
onError: (error) => {
console.error("Biometric error:", error);
},
});
biometrics.start();
</script>
Web Integration
Create a verification session and redirect the user to the hosted verification page:
// 1. Create a session (server-side)
const response = await fetch('https://api.bytrustgate.com/api/v1/sessions', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ applicant_id: 'APPLICANT_ID', checks: ['face_match', 'liveness'] })
});
const { token, verification_url } = await response.json();
// 2. Redirect user to hosted verification (or embed in iframe)
window.location.href = verification_url;
Coming soon: A React component SDK (
@trustgate/react-sdk) is under development for inline embedding.
Mobile SDKs
Coming soon: Native iOS (Swift) and Android (Kotlin) SDKs are under development. For now, use the web SDK or call the REST API directly:
# Create a biometric session
curl -X POST https://api.bytrustgate.com/api/v1/biometrics/session \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"applicant_id": "APPLICANT_ID", "type": "face_match"}'
# The session URL can be opened in a mobile webview for biometric capture
Configuration Options
Threshold Settings
Configure pass/fail thresholds in Settings > Workflows:
| Setting | Default | Range | Description |
|---|---|---|---|
face_match_threshold | 85% | 70-99% | Minimum similarity to pass |
liveness_threshold | 0.95 | 0.8-0.99 | Minimum liveness confidence |
max_attempts | 3 | 1-5 | Retry attempts before failure |
Quality Requirements
| Setting | Default | Description |
|---|---|---|
min_face_size | 100px | Minimum face bounding box |
max_face_angle | 25° | Maximum head rotation |
min_eye_distance | 50px | Minimum distance between eyes |
require_eyes_open | true | Both eyes must be visible |
Handling Failures
Common Failure Reasons
| Reason | Description | User Guidance |
|---|---|---|
face_mismatch | Faces don't match | "The photo doesn't match your ID. Please ensure you're using your own document." |
liveness_failed | Liveness check failed | "Please try again in better lighting, looking directly at the camera." |
face_not_detected | No face found in image | "We couldn't detect a face. Please center your face in the frame." |
multiple_faces | More than one face | "Please ensure only your face is visible in the frame." |
poor_quality | Image quality too low | "Please retake the photo in better lighting." |
face_obstructed | Face partially covered | "Please remove glasses, masks, or other obstructions." |
Retry Logic
max_attempts = 3
attempt = 0
while attempt < max_attempts:
result = run_biometric_verification(applicant_id, document_id)
if result["status"] == "passed":
break
elif result["status"] == "failed":
if result["failure_reason"] in ["poor_quality", "face_not_detected"]:
# Retriable errors
attempt += 1
notify_user(get_guidance(result["failure_reason"]))
else:
# Non-retriable errors (face_mismatch)
escalate_to_manual_review(applicant_id)
break
if attempt >= max_attempts:
escalate_to_manual_review(applicant_id)
Privacy & Security
Data Handling
- Biometric data is processed but not permanently stored
- Face embeddings (not images) used for comparison
- All transmission encrypted with TLS 1.3
- Compliant with GDPR, BIPA, and similar regulations
Consent Requirements
Before biometric verification, ensure you have:
- Clear disclosure of biometric data collection
- Explicit consent from the user
- Information about data retention
- Right to withdraw consent
// Record consent before starting biometrics
await recordConsent(applicantId, {
consent_type: "biometric_collection",
consent_text:
"I consent to TrustGate collecting and processing my biometric data (facial image) for identity verification purposes.",
ip_address: clientIp,
});
Next Steps
- Document Verification - Set up document upload first
- Address Verification - Add proof of address
- Verification Statuses - Understand the status lifecycle