Face Comparison
The Face Comparison API compares two face images and returns whether they belong to the same person, along with a similarity score. Typical use: compare a live selfie against the face cropped from an ID document.
It is a standalone service — it does not require a KYC submission or any customer onboarding state.
Try it in the playground →Overview
Use this endpoint when you want to confirm that the person presenting an ID is the same person captured in a liveness photo, without going through Azakaw's onboarding UI.
For each request the API will:
- Take two images uploaded by the caller.
- Run face matching via the Azakaw Face Comparison service.
- Return a boolean match decision plus similarity and quality scores.
Data handling
- Both uploaded images are processed in memory and not persisted.
- Only the comparison result (match boolean, scores, status) is persisted as part of an audit log entry.
- Nothing is uploaded to blob storage.
Authentication
All requests to this API require authentication using a bearer token in the Authorization header:
Authorization: Bearer your-token-here
For how to obtain a token, see the Authentication documentation. This endpoint requires an application token (issued by AppSessionManager — GetAppToken or the standalone-session flow), not an interactive user/portal session. Application tokens automatically include the services: External claim the gateway enforces — here External is just the platform's marker for an app-integration token; it has nothing to do with your API's end users. A token without that claim is rejected with 403.
Compare Two Faces
POST {base_url}/ExtFaceComparison/Compare
Request
The request must be sent as multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
LivenessFace | File | Yes | Selfie or liveness photo of the person. JPG, PNG, BMP, or TIFF. |
FaceFromDocument | File | Yes | Face cropped from an ID document (passport, ID card, etc.). Same supported formats as LivenessFace. |
Both files must be non-empty. The order does not matter — the comparison is symmetric.
Example
curl --location '{base_url}/ExtFaceComparison/Compare' \
--header 'Authorization: Bearer your-token-here' \
--form 'LivenessFace=@"/path/to/selfie.jpg"' \
--form 'FaceFromDocument=@"/path/to/id-face.jpg"'
Response
{
"version": null,
"statusCode": 200,
"messages": [
"Processed successfully"
],
"result": {
"isFaceMatch": true,
"matchingSimilarity": 0.9605157375335693,
"status": "Success"
}
}
Response Fields
The result object:
| Field | Type | Description |
|---|---|---|
isFaceMatch | boolean | The match decision: true when matchingSimilarity exceeds Azakaw's configured threshold. |
matchingSimilarity | decimal | Similarity in [0, 1] — 1.0 = identical, higher = more alike. This is the value the isFaceMatch decision is based on. |
status | string | Service status code. Success indicates a successful comparison. See Status values below for all values. |
If an input image contains more than one face, the comparison uses the highest-similarity pair.
Status values
status is a stable, provider-neutral code. Possible values:
| Code | Meaning |
|---|---|
Success | Comparison succeeded; isFaceMatch is meaningful. |
EmptyImage | One of the inputs was empty. The endpoint normally returns 400 before reaching this state — only seen if a malformed multipart slips through. |
NoFaceDetected | No face was detected in one of the inputs. isFaceMatch will be false. Re-capture with the face clearly visible. |
LandmarksNotDetected | A face was detected but key landmarks were not. Usually a quality issue (blur, partial occlusion). |
InvalidImage | The image could not be decoded. Verify the file is a JPG / PNG / BMP / TIFF. |
LowQuality | The images were judged too low quality to compare reliably. Re-capture under better lighting. |
Error | Any other processing error. |
A status other than Success does not always mean failure — always check isFaceMatch together with status.
Rate Limit
This endpoint is rate-limited at 5 requests per second. Excess requests return HTTP 429 Too Many Requests.
Error Handling
| Status | Meaning |
|---|---|
200 | Request processed. Inspect result.status and result.isFaceMatch. |
400 | Validation failure — e.g. LivenessFace or FaceFromDocument missing or empty. |
401 | Missing or invalid Bearer token. |
403 | Token does not carry the required services: External claim. |
413 | Uploaded file exceeds the configured size limit. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
Error responses follow the standard envelope:
{
"version": null,
"statusCode": 400,
"messages": [
"LivenessFace is empty."
],
"result": null
}
Best Practices
- Capture quality. Both faces should be well-lit, face-front, and unobstructed. Sunglasses, masks, and extreme angles reduce match confidence.
- Liveness first. This endpoint compares two static images — it does not perform liveness detection. Pair it with your liveness capture flow so the
LivenessFaceyou send is a fresh capture, not a still image. - Threshold interpretation.
isFaceMatchismatchingSimilaritycompared against a threshold configured on the Azakaw side. For a stricter / looser policy, ignoreisFaceMatchand apply your own threshold tomatchingSimilaritydirectly. - Status alongside match. Treat any
statusother thanSuccessas a signal to surface a friendly error to the user (typically a re-capture prompt) rather than relying solely onisFaceMatch = false. - Privacy. No images are stored. Only the comparison outcome is persisted for audit.