Face Matching API
Advanced biometric identification with 1:1 verification and 1:n search capabilities.
Base URL
https://api.zaits.net/v1/face-matchingAuthentication
All requests require your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYTenant Isolation
Multi-Tenant Security: All face embeddings are automatically isolated per Zaits customer. Your data is completely separate from other customers - searches and matches only occur within your own data.
Your API key identifies you as the tenant (owner)
subject_id identifies users in YOUR application (not Zaits users)
Data isolation is enforced at the database level for maximum security
How It Works
Zaits Customer A (API Key: acme_key_123)
├─ Subject: "EMP-001" → John Smith
├─ Subject: "EMP-002" → Jane Doe
└─ Subject: "EMP-003" → Bob Johnson
Zaits Customer B (API Key: beta_key_456)
├─ Subject: "CUST-A" → Alice Williams
├─ Subject: "CUST-B" → Charlie Brown
└─ Subject: "CUST-C" → Diana Prince
❌ Customer A can NEVER access Customer B's data
✅ Each customer has their own isolated face databaseEnroll Face
Register a face in the database for future 1:n identification.
Endpoint
POST /v1/face-matching/enrollParameters
image
file
✅
Face image to enroll
subject_id
string
✅
Your app's user identifier (employee ID, customer ID, etc.)
quality_score
number
❌
Image quality score (0-1)
liveness_score
number
❌
Liveness detection score (0-1)
enrollment_source
string
❌
Source of enrollment (e.g., "registration", "manual")
metadata
object
❌
Custom metadata (employee info, department, etc.)
Request Examples
curl -X POST https://api.zaits.net/v1/face-matching/enroll \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "subject_id=EMP-001" \
-F "image=@employee_photo.jpg" \
-F "quality_score=0.95" \
-F "liveness_score=0.88" \
-F "enrollment_source=hr_registration" \
-F 'metadata={"name":"John Smith","department":"Engineering","badge":"B-8472"}'const formData = new FormData();
formData.append('subject_id', 'EMP-001'); // Your employee ID
formData.append('image', employeePhoto);
formData.append('quality_score', '0.95');
formData.append('liveness_score', '0.88');
formData.append('enrollment_source', 'hr_registration');
formData.append('metadata', JSON.stringify({
name: 'John Smith',
department: 'Engineering',
badge: 'B-8472',
hire_date: '2024-01-15'
}));
const response = await fetch('https://api.zaits.net/v1/face-matching/enroll', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
body: formData
});
const result = await response.json();import requests
files = {'image': open('employee_photo.jpg', 'rb')}
data = {
'subject_id': 'EMP-001', # Your employee ID
'quality_score': 0.95,
'liveness_score': 0.88,
'enrollment_source': 'hr_registration',
'metadata': '{"name":"John Smith","department":"Engineering","badge":"B-8472"}'
}
response = requests.post(
'https://api.zaits.net/v1/face-matching/enroll',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
files=files,
data=data
)
result = response.json()Response
{
"success": true,
"embeddingId": "550e8400-e29b-41d4-a716-446655440000",
"subjectId": "EMP-001",
"embeddingDimension": 512,
"processing_time": 0.85
}Response Fields:
embeddingId- Unique ID for this face embeddingsubjectId- Your app's user identifier that was enrolledembeddingDimension- Vector dimensions (always 512 for ArcFace)processing_time- Time taken to process in seconds
Search Faces (1:n Matching)
Find matching faces in the enrolled database.
Endpoint
POST /v1/face-matching/searchParameters
image
file
✅
Face image to search for
threshold
number
❌
Similarity threshold (0-1, default: 0.6)
limit
number
❌
Maximum results to return (default: 10)
Request Example
curl -X POST https://api.zaits.net/v1/face-matching/search \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@unknown_face.jpg" \
-F "threshold=0.7" \
-F "limit=5"const formData = new FormData();
formData.append('image', file);
formData.append('threshold', '0.7');
formData.append('limit', '5');
const response = await fetch('https://api.zaits.net/v1/face-matching/search', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
body: formData
});
const result = await response.json();
// Process matches
if (result.matchCount > 0) {
const topMatch = result.matches[0];
console.log(`Match found: ${topMatch.user_name}`);
console.log(`Confidence: ${(topMatch.similarity * 100).toFixed(1)}%`);
console.log(`Email: ${topMatch.user_email}`);
}import requests
files = {'image': open('unknown_face.jpg', 'rb')}
data = {
'threshold': 0.7,
'limit': 5
}
response = requests.post(
'https://api.zaits.net/v1/face-matching/search',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
files=files,
data=data
)
result = response.json()
if result['matchCount'] > 0:
top_match = result['matches'][0]
print(f"Match found: {top_match['user_name']}")
print(f"Confidence: {top_match['similarity'] * 100:.1f}%")Response
{
"success": true,
"matches": [
{
"id": "embedding-id",
"subject_id": "EMP-001",
"similarity": 0.8523,
"quality_score": 0.95,
"liveness_score": 0.88,
"enrollment_source": "registration",
"metadata": {
"name": "John Smith",
"department": "Engineering",
"badge": "B-8472",
"label": "Employee Badge",
"location": "HR Office"
},
"created_at": "2025-01-11T10:00:00Z"
}
],
"matchCount": 1,
"thresholdUsed": 0.7,
"processing_time": 1.23
}Response Fields:
subject_id- Your app's user identifier (e.g., employee ID, customer number)similarity- Match confidence score (0-1), higher is betterquality_score- Original enrollment image quality (0-1)liveness_score- Liveness detection score from enrollment (0-1)enrollment_source- Where this face was enrolled (e.g., "registration", "testing")metadata- Custom data you stored during enrollment (name, department, etc.)created_at- When this face was enrolled
Verify Face (1:1 Matching)
Verify if a face matches a specific subject's enrolled faces.
Endpoint
POST /v1/face-matching/verify/:subjectIdParameters
subjectId
string
✅
Subject ID to verify against (path parameter)
image
file
✅
Face image to verify
threshold
number
❌
Similarity threshold (default: 0.6)
Request Example
curl -X POST https://api.zaits.net/v1/face-matching/verify/EMP-001 \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@verification_selfie.jpg" \
-F "threshold=0.7"const subjectId = 'EMP-001'; // Your app's user identifier
const formData = new FormData();
formData.append('image', file);
formData.append('threshold', '0.7');
const response = await fetch(
`https://api.zaits.net/v1/face-matching/verify/${subjectId}`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
body: formData
}
);
const result = await response.json();
if (result.verified) {
console.log('Access granted!');
} else {
console.log('Access denied');
}import requests
subject_id = 'EMP-001' # Your app's user identifier
files = {'image': open('verification_selfie.jpg', 'rb')}
data = {'threshold': 0.7}
response = requests.post(
f'https://api.zaits.net/v1/face-matching/verify/{subject_id}',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
files=files,
data=data
)
result = response.json()
print(f"Verified: {result['verified']}")
print(f"Similarity: {result['similarity']:.4f}")Response
{
"success": true,
"verified": true,
"similarity": 0.8523,
"threshold": 0.7,
"embeddingId": "embedding-id-used",
"enrollmentSource": "registration",
"processing_time": 0.95
}Get Tenant Embeddings
Retrieve all enrolled face embeddings for your tenant (all subjects enrolled under your API key).
Endpoint
GET /v1/face-matching/embeddingsQuery Parameters
active_only
boolean
❌
Only return active embeddings (default: true)
subject_id
string
❌
Filter embeddings for a specific subject ID
Request Examples
curl -X GET 'https://api.zaits.net/v1/face-matching/embeddings?active_only=true' \
-H "Authorization: Bearer YOUR_API_KEY"curl -X GET 'https://api.zaits.net/v1/face-matching/embeddings?subject_id=EMP-001' \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"embeddings": [
{
"id": "embedding-id",
"subject_id": "EMP-001",
"quality_score": 0.95,
"liveness_score": 0.88,
"enrollment_source": "registration",
"created_at": "2025-01-11T10:00:00Z",
"verification_count": 15,
"last_verified_at": "2025-01-11T14:30:00Z"
}
],
"count": 1
}Response Fields:
subject_id- Your app's user identifier for this embeddingquality_score- Image quality score (0-1)liveness_score- Liveness detection score (0-1)enrollment_source- Source of enrollmentverification_count- Number of successful verificationslast_verified_at- Timestamp of last successful verification
Delete Embeddings
Delete face embeddings for your tenant.
Delete Specific Embedding
DELETE /v1/face-matching/embeddings/:embeddingIdDelete All Embeddings for Tenant
DELETE /v1/face-matching/embeddingsDelete All Embeddings for Specific Subject
DELETE /v1/face-matching/embeddings?subject_id=:subjectIdRequest Examples
curl -X DELETE https://api.zaits.net/v1/face-matching/embeddings/embedding-id \
-H "Authorization: Bearer YOUR_API_KEY"# Delete ALL embeddings for your tenant
curl -X DELETE https://api.zaits.net/v1/face-matching/embeddings \
-H "Authorization: Bearer YOUR_API_KEY"# Delete all embeddings for a specific subject
curl -X DELETE 'https://api.zaits.net/v1/face-matching/embeddings?subject_id=EMP-001' \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"message": "Face embedding deleted successfully"
}Similarity Thresholds
Choose the appropriate threshold based on your security requirements:
0.4 - 0.5
High security (banking, medical)
Very strict
May reject some valid matches
0.6
Recommended
Balanced
Good accuracy/security balance
0.7 - 0.8
Low security (social apps)
Permissive
May allow some false matches
Threshold Recommendations
// Banking/Financial Services
const BANKING_THRESHOLD = 0.4;
// Corporate Access Control
const ACCESS_CONTROL_THRESHOLD = 0.6;
// Social/Consumer Apps
const SOCIAL_THRESHOLD = 0.75;Use Cases
1. Employee Access Control
// Enroll employee during registration
const formData = new FormData();
formData.append('subject_id', 'EMP-12345'); // Employee ID from your system
formData.append('image', employeePhoto);
formData.append('metadata', JSON.stringify({
name: 'John Smith',
department: 'Engineering',
label: 'Employee Badge',
location: 'Building A - Security',
notes: 'Access level: Standard'
}));
const enrollResult = await fetch('https://api.zaits.net/v1/face-matching/enroll', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: formData
});
// Verify at entrance using 1:n search
const searchData = new FormData();
searchData.append('image', cameraImage);
searchData.append('threshold', '0.7');
searchData.append('limit', '1');
const searchResult = await fetch('https://api.zaits.net/v1/face-matching/search', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: searchData
}).then(r => r.json());
if (searchResult.matchCount > 0) {
const employee = searchResult.matches[0];
grantAccess(employee.subject_id); // Use subject_id (EMP-12345)
console.log(`Welcome, ${employee.metadata?.name || employee.subject_id}!`);
}2. Customer Identification
// Enroll customer during first visit
const formData = new FormData();
formData.append('subject_id', 'CUST-789'); // Customer ID from your system
formData.append('image', customerPhoto);
formData.append('metadata', JSON.stringify({
name: 'Jane Doe',
membership: 'Gold',
joined: '2024-01-15'
}));
await fetch('https://api.zaits.net/v1/face-matching/enroll', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: formData
});
// Search for returning customer
const searchData = new FormData();
searchData.append('image', customerPhoto);
searchData.append('threshold', '0.65');
searchData.append('limit', '5');
const result = await fetch('https://api.zaits.net/v1/face-matching/search', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: searchData
}).then(r => r.json());
if (result.matchCount > 0) {
const customer = result.matches[0];
console.log(`Welcome back, ${customer.metadata?.name}!`);
loadLoyaltyInfo(customer.subject_id); // Use subject_id (CUST-789)
}3. Event Check-in (1:1 Verification)
// Enroll ticket holder during purchase
const formData = new FormData();
formData.append('subject_id', 'TICKET-12345'); // Ticket number
formData.append('image', ticketHolderPhoto);
formData.append('metadata', JSON.stringify({
event: 'Concert 2024',
section: 'VIP',
seat: 'A-15'
}));
await fetch('https://api.zaits.net/v1/face-matching/enroll', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: formData
});
// Verify at entrance (1:1 verification)
const verifyData = new FormData();
verifyData.append('image', livePhoto);
verifyData.append('threshold', '0.7');
const verification = await fetch(
'https://api.zaits.net/v1/face-matching/verify/TICKET-12345',
{
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: verifyData
}
).then(r => r.json());
if (verification.verified) {
checkInAttendee('TICKET-12345');
console.log('✅ Entry granted - ticket verified');
} else {
console.log('❌ Entry denied - face does not match ticket holder');
}Best Practices
Image Quality
Resolution: 640x640 or higher
Lighting: Well-lit, even lighting
Angle: Frontal face, minimal rotation
Expression: Neutral expression preferred
Enrollment Strategy
Enroll 2-3 images per user for better accuracy
Use different lighting conditions
Include slight angle variations
Check liveness before enrollment
Security
Always use liveness detection before enrollment
Implement rate limiting on verification endpoints
Log all face matching operations for audit
Use appropriate thresholds for your use case
Performance
Cleanup old embeddings periodically
Keep 3-5 most recent enrollments per user
Use indexed searches for large databases
Cache frequent verification results
Next: OCR API Documentation
Last updated