Skip to main content

POST /api/IdVerification/verify

Verify an identity document and match it against a selfie photo using facial recognition.

Endpoint​

POST https://api.matchstra.ca/api/IdVerification/verify

Authentication​

Requires API key in the X-API-Key header.

Request​

Headers​

HeaderValueRequired
X-API-KeyYour API key✅ Yes
Content-Typemultipart/form-data✅ Yes (set automatically by most HTTP clients)

Body Parameters (Form Data)​

ParameterTypeRequiredDescription
IdCardImagefile✅ YesGovernment-issued ID document image (JPEG/PNG, max 10 MB)
SelfieImagefile✅ YesSelfie photo of the person (JPEG/PNG, max 10 MB)

Image Requirements​

ID Card Image:

  • Format: JPEG or PNG
  • Max size: 10 MB
  • Recommended: 1200×800 pixels or higher
  • Must show: All text readable, all corners visible, no glare

Selfie Image:

  • Format: JPEG or PNG
  • Max size: 10 MB
  • Recommended: 800×800 pixels or higher
  • Must show: Face clearly visible, eyes open, no obstructions

Request Example​

curl -X POST https://api.matchstra.ca/api/IdVerification/verify \
-H "X-API-Key: your_api_key_here" \
-F "IdCardImage=@/path/to/drivers-license.jpg" \
-F "SelfieImage=@/path/to/selfie.jpg"
// Browser JavaScript
const formData = new FormData();
formData.append('IdCardImage', idCardFile); // File object from <input type="file">
formData.append('SelfieImage', selfieFile);

const response = await fetch('https://api.matchstra.ca/api/IdVerification/verify', {
method: 'POST',
headers: {
'X-API-Key': 'your_api_key_here'
// Don't set Content-Type - browser will set it with boundary
},
body: formData
});

const data = await response.json();
using System.Net.Http;
using System.Net.Http.Headers;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key_here");

using var formData = new MultipartFormDataContent();

// Add ID card image
var idCardContent = new ByteArrayContent(File.ReadAllBytes("drivers-license.jpg"));
idCardContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
formData.Add(idCardContent, "IdCardImage", "drivers-license.jpg");

// Add selfie image
var selfieContent = new ByteArrayContent(File.ReadAllBytes("selfie.jpg"));
selfieContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
formData.Add(selfieContent, "SelfieImage", "selfie.jpg");

var response = await client.PostAsync(
"https://api.matchstra.ca/api/IdVerification/verify",
formData
);

var result = await response.Content.ReadAsStringAsync();

Response​

Success Response (200 OK)​

Successful Match​

{
"success": true,
"message": "Verification completed successfully",
"data": {
"id": 67890,
"faceMatch": true,
"matchConfidence": 96.8,
"livenessScore": 98.5,
"status": "Verified",
"extractedData": {
"documentType": "Driver License",
"documentNumber": "D1234567",
"fullName": "JANE MARY DOE",
"dateOfBirth": "1990-08-15T00:00:00Z",
"expiryDate": "2028-08-15T00:00:00Z",
"country": "Canada",
"region": "Ontario",
"address": "123 Main St, Toronto, ON M5V 1A1",
"nationality": "Canadian",
"sex": "F"
},
"remainingRequests": 234
},
"errors": null
}

No Match​

{
"success": true,
"message": "Verification completed successfully",
"data": {
"id": 67891,
"faceMatch": false,
"matchConfidence": 42.3,
"livenessScore": 97.2,
"status": "Not Verified",
"extractedData": {
"documentType": "Driver License",
"documentNumber": "D1234567",
"fullName": "JANE MARY DOE",
"dateOfBirth": "1990-08-15T00:00:00Z",
"expiryDate": "2028-08-15T00:00:00Z",
"country": "Canada",
"region": "Ontario",
"address": "123 Main St, Toronto, ON M5V 1A1",
"nationality": "Canadian",
"sex": "F"
},
"remainingRequests": 233
},
"errors": null
}

Response Fields​

FieldTypeDescription
successbooleantrue if request succeeded
messagestringHuman-readable status message
dataobjectVerification result data
data.idintegerUnique verification ID
data.faceMatchbooleantrue if face matches ID document
data.matchConfidencenumberFace match confidence (0-100)
data.livenessScorenumberLiveness detection score (0-100, or null)
data.statusstring"Verified", "Not Verified", or "Manual Review Required"
data.extractedDataobjectData extracted from ID document
data.remainingRequestsintegerRemaining API quota
errorsarrayError messages (null on success)

Extracted Data Fields​

FieldTypeDescription
documentTypestringType of document (e.g., "Driver License", "Passport")
documentNumberstringID/document number
fullNamestringFull name as on document
dateOfBirthstringDate of birth (ISO 8601)
expiryDatestringDocument expiry date (ISO 8601)
countrystringIssuing country
regionstringState/province (if applicable)
addressstringAddress on document (if present)
nationalitystringNationality/citizenship
sexstringGender marker ("M", "F", "X", etc.)
note

Some extracted fields may be null if not present on the document or not readable by OCR.

Error Responses​

400 Bad Request - Missing Files​

{
"success": false,
"message": "Validation failed",
"data": null,
"errors": [
"IdCardImage is required",
"SelfieImage is required"
]
}

Cause: One or both image files missing from request.

400 Bad Request - Invalid Files​

{
"success": false,
"message": "Invalid file upload",
"data": null,
"errors": [
"IdCardImage: File size exceeds 10 MB limit",
"SelfieImage: Invalid image format. Only JPEG and PNG are supported."
]
}

Causes:

  • File size exceeds 10 MB
  • Invalid file format (not JPEG/PNG)
  • Corrupted image file

400 Bad Request - Poor Image Quality​

{
"success": false,
"message": "Image quality insufficient",
"data": null,
"errors": [
"ID document text not readable - please retake with better lighting",
"No face detected in selfie image"
]
}

Causes:

  • Image too blurry or low resolution
  • Poor lighting
  • ID document text not readable
  • No face detected in selfie
  • Multiple faces in selfie

401 Unauthorized​

{
"success": false,
"message": "Unauthorized",
"data": null,
"errors": ["Invalid or missing API key"]
}

Cause: Invalid, missing, or revoked API key.

429 Too Many Requests​

{
"success": false,
"message": "Rate limit exceeded",
"data": null,
"errors": ["Request quota exhausted"]
}

Cause: API quota limit reached.

Interpreting Results​

Match Confidence Scores​

ScoreInterpretationRecommended Action
90-100Very high confidence matchAuto-approve
80-89High confidence matchApprove with standard review
70-79Moderate confidenceManual review recommended
60-69Low confidenceRequest better photos or manual review
0-59Very low confidence / No matchReject or request re-submission

Liveness Scores​

ScoreInterpretationRisk
90-100Very confident it's a live personVery low spoof risk
80-89Likely a live personLow spoof risk
70-79UncertainModerate risk - review
0-69Possible spoof (photo of photo, mask, etc.)High risk - reject

Status Values​

  • "Verified": Face matches and liveness checks passed
  • "Not Verified": Face doesn't match or liveness check failed
  • "Manual Review Required": Edge case requiring human review

Use Cases​

Basic Verification​

async function verifyIdentity(idCardFile, selfieFile) {
const formData = new FormData();
formData.append('IdCardImage', idCardFile);
formData.append('SelfieImage', selfieFile);

const response = await fetch('https://api.matchstra.ca/api/IdVerification/verify', {
method: 'POST',
headers: {
'X-API-Key': process.env.MATCHSTRA_API_KEY
},
body: formData
});

const result = await response.json();

if (result.success && result.data.faceMatch) {
console.log('✅ Identity verified!');
return result.data;
} else {
console.log('❌ Verification failed');
return null;
}
}

Decision Logic​

function makeVerificationDecision(verificationData) {
// Check face match
if (!verificationData.faceMatch) {
return { approved: false, reason: 'Face does not match ID' };
}

// Check match confidence
if (verificationData.matchConfidence < 75) {
return { approved: false, reason: 'Match confidence too low' };
}

// Check liveness
if (verificationData.livenessScore !== null && verificationData.livenessScore < 70) {
return { approved: false, reason: 'Possible spoof attempt' };
}

// Check document expiry
const expiryDate = new Date(verificationData.extractedData.expiryDate);
if (expiryDate < new Date()) {
return { approved: false, reason: 'ID document expired' };
}

return { approved: true, reason: 'All checks passed' };
}

// Usage
const verification = await verifyIdentity(idCard, selfie);
const decision = makeVerificationDecision(verification);

if (decision.approved) {
createAccount(verification.extractedData);
} else {
rejectApplication(decision.reason);
}

Notes​

  • Processing time: Average 3-6 seconds
  • Supported documents: Passports, driver's licenses, national ID cards, residence permits
  • Countries: 150+ countries supported
  • Storage: Images are stored securely for 90 days for audit purposes, then deleted
  • Privacy: Complies with GDPR, PIPEDA, and CCPA

See Also​