A face verification API does one thing: it confirms that a real human face was present in real-time. Not a photo, not a video replay, not a deepfake image — a live face with active liveness detection. This makes it the strongest signal available for "is this person actually human?"
Developers use face verification APIs for three primary use cases: replacing CAPTCHAs at signup, adding identity assurance to high-value actions (large transactions, account recovery, age verification), and meeting regulatory requirements for KYC flows.
This guide walks through TrueLens's face verification API specifically — it's the most developer-friendly option with the simplest integration path. Skip to the API comparison table if you want to evaluate alternatives first.
How a Face Verification API Works
The flow has three parts:
- Client-side challenge: The user's browser or app activates the camera. The liveness SDK prompts a micro-action (blink, turn head, or passive liveness) to confirm it's not a static image.
- Server-side analysis: The captured frame(s) are analyzed by the API — checking for depth cues, reflection patterns, and texture consistency that photos and videos can't replicate.
- Token issuance: On success, the API returns a signed verification token. Your backend verifies the token before completing the action (account creation, login, etc.).
The key insight: the token is the deliverable. You're not storing face data — you're getting a cryptographic receipt that says "a verified human was present at time T." Your database stores the token, not the image.
TrueLens Face Verification API: 4-Step Integration
-
Get your API key
Sign up at /pricing. Free tier includes 50 verifications. Your key is available immediately — no approval process, no KYC for the developer.
-
Embed the verification widget
Add the TrueLens iframe or SDK script to your signup page. The widget handles camera access, liveness challenge, and token generation. Customize with your brand colors via CSS variables.
-
Receive the verification token
On successful liveness check, the widget posts a
truelens:verifiedevent with a signed JWT token to your page. Store it in a hidden field or sessionStorage. -
Verify server-side before account creation
Send the token to your backend. Call the TrueLens verify endpoint. Only create the account if the response is
verified: true.
Code Examples
Client-Side: Embed the Verification Widget
<!-- Add to your signup page -->
<div id="truelens-widget"
data-api-key="tl_live_your_key_here"
data-callback="onVerified">
</div>
<!-- Hidden field to hold the token -->
<input type="hidden" id="verification-token" name="verificationToken">
<script src="https://cdn.truelens.io/v1/widget.js"></script>
<script>
function onVerified(event) {
if (event.status === 'verified') {
document.getElementById('verification-token').value = event.token;
document.getElementById('submit-btn').disabled = false;
}
}
</script>
Server-Side Verification
// Node.js / Express
const TRUELENS_API_KEY = process.env.TRUELENS_API_KEY;
async function verifyLiveness(token) {
const response = await fetch('https://api.truelens.io/v1/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${TRUELENS_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ token })
});
if (!response.ok) throw new Error('Verification service unavailable');
return response.json();
// Returns: { verified: true, liveness_score: 0.98, verification_id: "vrf_..." }
}
app.post('/signup', async (req, res) => {
const { email, password, verificationToken } = req.body;
if (!verificationToken) {
return res.status(400).json({ error: 'Face verification required' });
}
try {
const { verified, liveness_score } = await verifyLiveness(verificationToken);
if (!verified || liveness_score < 0.95) {
return res.status(403).json({ error: 'Verification failed. Please try again.' });
}
// Token is valid — create the account
const user = await createUser({ email, password });
res.json({ success: true, userId: user.id });
} catch (err) {
console.error('Liveness check error:', err);
res.status(500).json({ error: 'Verification service error' });
}
});
import os
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
TRUELENS_API_KEY = os.environ.get('TRUELENS_API_KEY')
def verify_liveness(token: str) -> dict:
response = requests.post(
'https://api.truelens.io/v1/verify',
headers={
'Authorization': f'Bearer {TRUELENS_API_KEY}',
'Content-Type': 'application/json'
},
json={'token': token},
timeout=10
)
response.raise_for_status()
return response.json()
# Returns: {'verified': True, 'liveness_score': 0.98, 'verification_id': 'vrf_...'}
@app.route('/signup', methods=['POST'])
def signup():
data = request.get_json()
token = data.get('verificationToken')
if not token:
return jsonify({'error': 'Face verification required'}), 400
try:
result = verify_liveness(token)
if not result['verified'] or result['liveness_score'] < 0.95:
return jsonify({'error': 'Verification failed. Please try again.'}), 403
# Create user account
user = create_user(data['email'], data['password'])
return jsonify({'success': True, 'userId': user['id']})
except requests.RequestException as e:
return jsonify({'error': 'Verification service error'}), 500
# Test the verify endpoint with cURL
curl -X POST https://api.truelens.io/v1/verify \
-H "Authorization: Bearer tl_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}'
# Successful response:
# {
# "verified": true,
# "liveness_score": 0.98,
# "verification_id": "vrf_01HXYZ...",
# "expires_at": "2026-05-24T05:00:00Z"
# }
# Failed response (photo replay attack):
# {
# "verified": false,
# "liveness_score": 0.31,
# "failure_reason": "spoof_detected"
# }
Face Verification API Response Reference
Every successful verify call returns:
verified— boolean.trueonly if liveness passed and the token is unused + unexpired.liveness_score— float 0–1. Confidence that the subject was a live human. Scores below 0.90 indicate possible spoof attempt. Recommended threshold: 0.95.verification_id— string. Unique ID for this verification event. Store this in your database for audit trail and support queries.expires_at— ISO 8601 timestamp. Tokens are single-use and expire after 10 minutes by default.failure_reason— string, optional. Present on failed verifications:spoof_detected,token_expired,token_used,low_quality.
Face Verification API Comparison (2026)
| API | Liveness Type | Accuracy | GDPR | Pricing | Dev Friendliness |
|---|---|---|---|---|---|
| TrueLens | Active (passive option) | 99.9% | GDPR-ready | From $19/mo | Excellent |
| AWS Rekognition | Passive | 98%+ | Complex | $0.001–0.004/call | Steep learning curve |
| FaceTec | Active (3D liveness) | 99.9% | Yes | Enterprise only | SDK-heavy integration |
| iProov | Active (genuine presence) | 99%+ | UK/EU compliant | Enterprise only | Slow sales process |
| Microsoft Azure Face | Passive | 95–97% | Complex consent | Pay-per-call | Medium complexity |
When to Use a Face Verification API
Face liveness is the right tool when a fake account causes measurable damage. Consider it for:
- SaaS trial abuse: Attackers create hundreds of free trials. Liveness limits each unique human to one trial.
- Marketplace fraud: Fake buyer/seller accounts, fake reviews. One verified face per account breaks the economics of fraud.
- Fintech onboarding: KYC requirements often mandate liveness detection. Face verification APIs are faster and cheaper than manual document review.
- Age-gated content: Regulatory compliance for alcohol, gambling, or adult platforms requiring age verification.
- High-value account recovery: Add liveness to password reset for accounts with sensitive data or payment methods.
Common Integration Mistakes
Three pitfalls that most first integrations hit:
- Trusting the client: The biggest mistake. A sophisticated attacker can modify JavaScript in their browser to always pass client-side checks. The token must be verified server-to-server.
- Not storing the verification_id: You'll need this for support tickets ("I verified but can't sign up"), fraud investigations, and regulatory audits. Always persist it.
- Setting liveness_score threshold too low: The default threshold of 0.95 is correct for most use cases. Dropping to 0.80 to reduce false positives will let through the cheapest spoofing attacks.
Full API documentation, sandbox endpoints, and interactive testing at /docs. For pricing and plan limits, see /pricing.
Also useful: how to stop bot signups without CAPTCHA covers the full layered approach — liveness is the strongest layer, but combining it with rate limiting and email checks covers even more ground.