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.

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 details on how to obtain an authentication token, please refer to the Authentication documentation. Tokens issued by AppSessionManager carry a services: External claim that this endpoint requires.

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.9998999834060669,
"matchingScore": 95.0,
"status": "FACER_OK"
}
}

Response Fields

The result object:

FieldTypeDescription
isFaceMatchbooleantrue when the comparison passed the provider's match threshold.
matchingSimilaritydecimalRaw similarity in [0, 1]. 1.0 means identical embeddings.
matchingScoredecimalProvider-specific match score (typically [0, 100]).
statusstringService status code. FACER_OK indicates a successful comparison. See Status values below for common values.

Status values

status is the raw code returned by the Azakaw Face Comparison service. The most common values:

CodeMeaning
FACER_OKComparison succeeded; isFaceMatch is meaningful.
FR_IMAGE_EMPTYOne of the inputs was empty. The endpoint normally returns 400 before reaching this state — only seen if a malformed multipart slips through.
FR_FACE_NOT_DETECTEDNo face was detected in one of the inputs. isFaceMatch will be false. Re-capture with the face clearly visible.
FR_LANDMARKS_NOT_DETECTEDA face was detected but key landmarks were not. Usually a quality issue (blur, partial occlusion).
FR_IMAGE_DECODE_ERRORImage format could not be decoded. Verify the file is a JPG / PNG / BMP / TIFF.
FACER_LOW_QUALITYSource images were judged too low quality to compare reliably. Re-capture under better lighting.

A status other than FACER_OK 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 reflects the provider's threshold. If you need a stricter / looser policy, consume matchingSimilarity directly and apply your own threshold.
  • Status alongside match. Treat any status other than FACER_OK 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.