What is checked, and why
Every uploaded ID side and selfie goes through automatic checks. Each check ends as pass, warning, review flag or retry. This page explains the outcomes so you can explain any decision.
Outcomes of a check
| Outcome | Effect |
|---|---|
| pass | Nothing to report. |
| warning | Small deduction from the side score (−8). Does not force review on its own. |
| review flag | Larger deduction (−25) and the session cannot be auto-approved. A reviewer decides. |
| retry | The image is rejected. The applicant is asked to retake it; nothing is stored as accepted. |
Document image checks
These run on every side and need no OCR.
| Check | What it looks at | Outcome |
|---|---|---|
| File type | Real type from the file's magic bytes, not its extension or declared MIME. PDFs and scans are not accepted, only photos (JPEG, PNG, WebP). | retry |
| Resolution | Shorter side below 480 px is rejected; below 700 px warns. | retry / warning |
| Blur | Variance of the Laplacian on a normalized grayscale copy. Below DOC_BLUR_RETRY: rejected. Between DOC_BLUR_RETRY and DOC_BLUR_REVIEW: warning. | retry / warning |
| Glare | Share of blown-out pixels. Moderate glare warns, strong glare is rejected. | retry / warning |
| Brightness | Mean brightness. Too dark is rejected; dim warns. | retry / warning |
| Card aspect ratio | A card photo should look like a card. A very different ratio suggests an uncropped or wrong picture. | warning |
| Editing-software traces | Metadata naming Photoshop, GIMP, Canva, Snapseed, Pixelmator, Affinity Photo, PicsArt, Lightroom, Photopea, Fotor, Facetune, Remini, Meitu, BeFunky and similar. | review flag |
| Screenshot heuristic | Image dimensions that match common device screen resolutions, suggesting a picture of a screen rather than of a physical card. | review flag |
| Duplicate image | SHA-256 (exact copy) and dHash (near copy after resizing or recompression), compared against earlier images of the same company from sessions that reached a result. The same photo for front and back of one session is rejected. | review flag |
ID data rules
Run on the text read from the card by OCR.
| Check | Rule | Outcome |
|---|---|---|
| Wrong side | Front uploaded where back is expected, or the reverse. | retry |
| OCR confidence | Average confidence too low means the card was not read reliably. | retry / warning |
| ID number | Must be 8 digits. Repeated digits (00000000) and similar fake-looking patterns are flagged. Missing number is rejected. | review flag |
| Names | First and last name present and made of plausible characters. | review flag |
| Birth date / age | Readable, plausible, and the holder is at least 18. | review flag |
| Issue date | Not in the future, not before the holder was 15, and not older than CIN_MAX_AGE_YEARS (default 10). | review flag |
| Field confidence | Low OCR confidence on number, birth date or names. | review flag |
| Back-side data | Some data must be readable on the back (address, issue date, etc.). | retry |
| Same ID already verified | An ID number already verified (FINISHED or APPROVED) for your company is flagged for review. With checkCINUniqueness on, the upload is instead refused with 409 DUPLICATE_CIN_NUMBER. | review flag / 409 |
Selfie checks
The selfie is analysed for quality before it is compared with the card photo. Any failure sends the session to review with the reason listed.
- Exactly one face.
- Detection confidence, sharpness and lighting above minimums.
- Frontal pose (face turned to the camera).
- No sunglasses, eyes open, face not partially covered.
- Face large enough in the frame (not too far).
Face match
The selfie is compared with the face on the card. The similarity must reach FACE_MATCH_THRESHOLD (default 85, out of 100) to count as a MATCH. Below that it is NO_MATCH and always goes to review.
AML
When enabled for the session, the applicant is screened against sanctions and PEP lists. Any potential match sends the session to review. If AML is enabled but has not completed (or failed to run), the session is not auto-approved.
Scores
Side score (0–100)
Each document side starts at 100. Every warning subtracts 8, every review flag subtracts 25. Any retry makes the side rejected. A side gets verdict PASS only if it has no review flag and its score is at least DOC_MIN_SCORE_AUTO (default 80); otherwise REVIEW.
Risk score (0–100)
The risk score starts from 100 − lowest side score, then adds penalties: +40 if the faces do not match (+10 for a match below 92), +15 for a failed selfie quality check, +30 for an AML hit, +30 for a duplicate image or ID. It is capped at 100.
| Risk score | Band |
|---|---|
| below 20 | low |
| 20 to 49 | medium |
| 50 and above | high |
Auto-approval
A session is auto-approved (status FINISHED) only when all of these are true. Anything else goes to manual review with the reasons listed.
- Both front and back have verdict
PASS. - Selfie quality passed.
- Face match is
MATCH. - AML is clear (if enabled).
- No duplicate image, no duplicate ID, no front/back mismatch.
Auto-approval is a recommendation for a clean case. A human can still approve or decline afterwards.
Tunables
| Variable | Default | Effect |
|---|---|---|
FACE_MATCH_THRESHOLD | 85 | Minimum face similarity for MATCH. |
DOC_BLUR_RETRY | 40 | Sharpness below this is rejected. |
DOC_BLUR_REVIEW | 150 | Sharpness below this (but above retry) raises a warning. |
DOC_MIN_SCORE_AUTO | 80 | Minimum side score for a PASS verdict. |
CIN_MAX_AGE_YEARS | 10 | Cards issued longer ago are flagged as possibly expired. |
These are environment variables on the server. Defaults can change between releases; check your deployment.
Limits and calibration
- Calibrate thresholds on your real traffic: review a sample of approvals and rejections, then tune blur, score and face-match values.
- Keep a human reviewer in the loop for anything high-stakes, and add a specialist vendor if your regulator or risk appetite requires it.
- Expect false positives (good photos flagged) until you tune; they cost reviewer time, not security.
To explore what a reviewer sees, use the interactive demo.