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