Skip to main content

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 AppSessionManagerGetAppToken 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.

FieldTypeRequiredDescription
LivenessFaceFileYesSelfie or liveness photo of the person. JPG, PNG, BMP, or TIFF.
FaceFromDocumentFileYesFace 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:

FieldTypeDescription
isFaceMatchbooleanThe match decision: true when matchingSimilarity exceeds Azakaw's configured threshold.
matchingSimilaritydecimalSimilarity in [0, 1]1.0 = identical, higher = more alike. This is the value the isFaceMatch decision is based on.
statusstringService status code. Success indicates a successful comparison. See Status values below for all values.
note

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:

CodeMeaning
SuccessComparison succeeded; isFaceMatch is meaningful.
EmptyImageOne of the inputs was empty. The endpoint normally returns 400 before reaching this state — only seen if a malformed multipart slips through.
NoFaceDetectedNo face was detected in one of the inputs. isFaceMatch will be false. Re-capture with the face clearly visible.
LandmarksNotDetectedA face was detected but key landmarks were not. Usually a quality issue (blur, partial occlusion).
InvalidImageThe image could not be decoded. Verify the file is a JPG / PNG / BMP / TIFF.
LowQualityThe images were judged too low quality to compare reliably. Re-capture under better lighting.
ErrorAny 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

StatusMeaning
200Request processed. Inspect result.status and result.isFaceMatch.
400Validation failure — e.g. LivenessFace or FaceFromDocument missing or empty.
401Missing or invalid Bearer token.
403Token does not carry the required services: External claim.
413Uploaded file exceeds the configured size limit.
429Rate limit exceeded.
500Unexpected 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 LivenessFace you send is a fresh capture, not a still image.
  • Threshold interpretation. isFaceMatch is matchingSimilarity compared against a threshold configured on the Azakaw side. For a stricter / looser policy, ignore isFaceMatch and apply your own threshold to matchingSimilarity directly.
  • Status alongside match. Treat any status other than Success as a signal to surface a friendly error to the user (typically a re-capture prompt) rather than relying solely on isFaceMatch = false.
  • Privacy. No images are stored. Only the comparison outcome is persisted for audit.