Real-time biometric verification to ensure physical presence and prevent spoofing attacks including photos, videos, masks, and deepfakes.
Overview
Liveness detection validates that a user is physically present during verification, providing robust anti-spoofing protection. Combine with face matching to compare the live selfie against a reference image from an ID document.
Base Path: /v1/liveness
Key Features
Real-time verification with results in under 3 seconds
High accuracy with 99.5%+ confidence scores
Anti-spoofing detection for photos, videos, masks, and deepfakes
Face matching with 90%+ similarity threshold
Session-based flow with secure one-time tokens
Quality metrics for brightness, sharpness, and pose validation
How It Works
Create Session - Generate a unique session ID
Perform Check - User completes liveness verification in your UI
Get Results - Retrieve verification results and face image
Face Match (Optional) - Compare live selfie with ID photo
API Endpoints
Create Liveness Session
Generate a new face liveness verification session.
Endpoint: POST /v1/liveness/session
Request:
curl -X POST https://api.botskyc.com/v1/liveness/session \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"settings": {"auditImagesLimit": 4}}'
Request Body:
{
"settings" : {
"auditImagesLimit" : 4
}
}
Response:
{
"sessionId" : "abc123-def456-ghi789" ,
"status" : "CREATED" ,
"createdAt" : "2025-11-24T12:30:00Z" ,
"expiryDate" : "2025-11-24T12:40:00Z"
}
Session Expiry: 10 minutes (default)
Get Session Results
Retrieve liveness verification results for a completed session.
Endpoint: GET /v1/liveness/session/{sessionId}/results
Request:
curl https://api.botskyc.com/v1/liveness/session/abc123-def456-ghi789/results \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"sessionId" : "abc123-def456-ghi789" ,
"status" : "SUCCEEDED" ,
"confidence" : 99.5 ,
"isLive" : true ,
"referenceImage" : "base64-encoded-image..." ,
"auditImages" : [ "base64-image-1..." , "base64-image-2..." ],
"timestamp" : "2025-11-24T12:32:00Z" ,
"message" : "Liveness verified with 99.50% confidence"
}
Response Fields:
sessionId - Unique session identifier
status - SUCCEEDED, FAILED, IN_PROGRESS, EXPIRED
confidence - Confidence score (0-100)
isLive - Boolean indicating liveness check passed
referenceImage - Base64-encoded face image
auditImages - Additional verification images
timestamp - Result generation time
Verify Liveness
Verify liveness with additional validation checks.
Endpoint: POST /v1/liveness/verify/{sessionId}
Request:
curl -X POST https://api.botskyc.com/v1/liveness/verify/abc123-def456-ghi789 \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"sessionId" : "abc123-def456-ghi789" ,
"confidence" : 99.5 ,
"isLive" : true ,
"validationsPassed" : [ "face_detected" , "quality_check" , "anti_spoofing" ]
}
Compare Faces
Compare a live selfie with an ID document photo to verify they match.
Endpoint: POST /v1/liveness/compare-faces
Request:
curl -X POST https://api.botskyc.com/v1/liveness/compare-faces \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceImage": "data:image/jpeg;base64,/9j/4AAQ...",
"targetImage": "data:image/jpeg;base64,/9j/4AAQ..."
}'
Request Body:
{
"sourceImage" : "base64-encoded-id-photo..." ,
"targetImage" : "base64-encoded-selfie..."
}
Response:
{
"similarity" : 95.3 ,
"isMatch" : true ,
"confidence" : 95.3 ,
"threshold" : 90.0
}
Response Fields:
similarity - Similarity score (0-100)
isMatch - True if similarity exceeds threshold
confidence - Confidence in the match
threshold - Minimum similarity required (default: 90.0)
Verify with Document
Combine liveness verification with document face matching in one step.
Endpoint: POST /v1/liveness/verify-with-document/{sessionId}
Request:
curl -X POST https://api.botskyc.com/v1/liveness/verify-with-document/abc123-def456-ghi789 \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "[email protected] "
Response:
{
"sessionId" : "abc123-def456-ghi789" ,
"livenessVerified" : true ,
"livenessConfidence" : 99.5 ,
"faceMatch" : {
"isMatch" : true ,
"similarity" : 95.3 ,
"confidence" : 95.3
},
"overallSuccess" : true
}
Frontend Integration
React Example with AWS Amplify UI
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness' ;
import { useState, useEffect } from 'react' ;
function LivenessCheck () {
const [ sessionId , setSessionId ] = useState ( null );
const [ loading , setLoading ] = useState ( false );
// Step 1: Create session
useEffect (() => {
async function createSession () {
const response = await fetch ( 'https://api.botskyc.com/v1/liveness/session' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ process . env . REACT_APP_API_KEY }` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ settings: { auditImagesLimit: 4 } })
});
const data = await response. json ();
setSessionId (data.sessionId);
}
createSession ();
}, []);
// Step 2: Handle liveness check completion
const handleAnalysisComplete = async () => {
setLoading ( true );
try {
const response = await fetch (
`https://api.botskyc.com/v1/liveness/session/${ sessionId }/results` ,
{
headers: {
'Authorization' : `Bearer ${ process . env . REACT_APP_API_KEY }`
}
}
);
const results = await response. json ();
if (results.isLive) {
console. log ( 'Liveness verified!' , results.confidence);
// Proceed with next step
} else {
console. error ( 'Liveness check failed' );
}
} catch (error) {
console. error ( 'Error fetching results:' , error);
} finally {
setLoading ( false );
}
};
if ( ! sessionId) {
return < div >Creating session...</ div >;
}
return (
< div >
< h2 >Face Verification</ h2 >
< FaceLivenessDetector
sessionId = {sessionId}
onAnalysisComplete = {handleAnalysisComplete}
region = "eu-west-1"
/>
{loading && < div >Verifying...</ div >}
</ div >
);
}
export default LivenessCheck;
TypeScript Service
// services/liveness.ts
export interface LivenessSession {
sessionId : string ;
status : string ;
createdAt : string ;
expiryDate : string ;
}
export interface LivenessResult {
sessionId : string ;
status : string ;
confidence : number ;
isLive : boolean ;
referenceImage : string ;
timestamp : string ;
}
export interface FaceMatchResult {
similarity : number ;
isMatch : boolean ;
confidence : number ;
threshold : number ;
}
const API_BASE = 'https://api.botskyc.com/v1/liveness' ;
const API_KEY = process.env. BOTSKYC_API_KEY ! ;
export async function createLivenessSession () : Promise < LivenessSession > {
const response = await fetch ( `${ API_BASE }/session` , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY }` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ settings: { auditImagesLimit: 4 } })
});
if ( ! response.ok) {
throw new Error ( `Failed to create session: ${ response . status }` );
}
return response. json ();
}
export async function getLivenessResults ( sessionId : string ) : Promise < LivenessResult > {
const response = await fetch ( `${ API_BASE }/session/${ sessionId }/results` , {
headers: {
'Authorization' : `Bearer ${ API_KEY }`
}
});
if ( ! response.ok) {
throw new Error ( `Failed to get results: ${ response . status }` );
}
return response. json ();
}
export async function compareFaces (
sourceImage : string ,
targetImage : string
) : Promise < FaceMatchResult > {
const response = await fetch ( `${ API_BASE }/compare-faces` , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY }` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ sourceImage, targetImage })
});
if ( ! response.ok) {
throw new Error ( `Face comparison failed: ${ response . status }` );
}
return response. json ();
}
Complete Workflow Example
async function performCompleteKYC ( idFrontFile , idBackFile ) {
// Step 1: Scan ID document
const scanFormData = new FormData ();
scanFormData. append ( 'documents' , idFrontFile);
scanFormData. append ( 'documents' , idBackFile);
const scanResponse = await fetch ( 'https://api.botskyc.com/v1/identity/scan' , {
method: 'POST' ,
headers: { 'Authorization' : `Bearer ${ API_KEY }` },
body: scanFormData
});
const { extractedData } = await scanResponse. json ();
const idPhoto = extractedData.photo; // Base64 image
// Step 2: Create liveness session
const sessionResponse = await fetch ( 'https://api.botskyc.com/v1/liveness/session' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY }` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ settings: { auditImagesLimit: 4 } })
});
const { sessionId } = await sessionResponse. json ();
// Step 3: User completes liveness check in UI
// (FaceLivenessDetector component handles this)
// Step 4: Get liveness results
const resultsResponse = await fetch (
`https://api.botskyc.com/v1/liveness/session/${ sessionId }/results` ,
{ headers: { 'Authorization' : `Bearer ${ API_KEY }` } }
);
const { isLive , referenceImage } = await resultsResponse. json ();
if ( ! isLive) {
throw new Error ( 'Liveness check failed' );
}
// Step 5: Compare faces
const matchResponse = await fetch ( 'https://api.botskyc.com/v1/liveness/compare-faces' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY }` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
sourceImage: idPhoto,
targetImage: referenceImage
})
});
const { isMatch , similarity } = await matchResponse. json ();
if ( ! isMatch) {
throw new Error ( 'Face does not match ID photo' );
}
// All checks passed
return {
verified: true ,
personalInfo: extractedData,
livenessConfidence: 99.5 ,
faceMatchSimilarity: similarity
};
}
Best Practices
Security
Validate sessions server-side
Enforce one-time use of session IDs
Use HTTPS for all requests
Implement rate limiting
Do not persist biometric data longer than necessary
User Experience
Provide clear instructions for users
Ensure good lighting conditions
Handle session expiration gracefully (10 min default)
Show confidence scores to users when appropriate
Allow retries on low confidence
Performance
Set reasonable timeouts
Retry only on transient errors
Optimize image sizes before upload
Use audit images for debugging
Error Codes
Code Status Message Resolution 1006 500 Liveness session creation failed Retry or check configuration 1007 400 Liveness session expired Create a new session 1008 404 Liveness session not found Verify session ID is correct 1009 422 Liveness confidence too low Improve lighting/conditions 1010 500 Face matching failed Check image quality 1011 422 Face similarity too low Verify same person in both images 5001 503 Liveness service error Service temporarily unavailable
Error Response Example:
{
"errorCode" : 1009 ,
"message" : "Liveness confidence 85.00% is below required threshold 90.00%" ,
"status" : 422 ,
"timestamp" : "2025-11-24T12:35:00Z" ,
"details" : {
"confidence" : 85.0 ,
"threshold" : 90.0 ,
"reason" : "Poor lighting conditions"
}
}
Troubleshooting
Session Not Found (404)
Problem: Session ID returns 404
Solution: Session may have expired (10 minutes). Create a new session.
Low Confidence Score
Problem: Confidence below 90%
Solution:
Improve lighting conditions
Ensure face is unobstructed
Remove glasses or hats if possible
Position face in center of frame
Face Match Failed
Problem: Similarity score below threshold
Solution:
Verify same person in both images
Check image quality and resolution
Ensure face is clearly visible in both images
Try different lighting conditions
Service Unavailable (503)
Problem: 503 error from liveness service
Solution:
Check service status
Verify API connectivity
Contact support if issue persists
Pricing
Service Price per Request Liveness Session BWP 2-4 Face Comparison BWP 1-2
Volume discounts available. Contact [email protected] .
Support
Related Documentation:
Last modified on November 30, 2025