Flow & Check List

How a verification session runs, end to end

This page walks through every step from the moment an end user enters the flow to the moment a signed webhook reaches your system — the checks that run at each step, and the exact numbers behind each decision.

Every weight, threshold and limit below is a value actually enforced in the platform. Per-tenant configuration can only tighten them, never loosen them.

8
Flow steps — from session creation to webhook delivery
18
Distinct document checks — 15 scored + 3 hard rules
5
Document profiles — each with its own weight set
3
Liveness layers — active, passive ML, heuristic

Step by step

Session flow

The photo and NFC paths are identical through step 3, diverge at step 4, and converge again at step 5.

Who performs each stepYour systemEnd userIDV platform
  1. Your system

    Session creation

    Your backend opens a verification session. The tenant API key is used only in this call and never reaches the browser. The returned session_id is the only user identifier exposed externally.

    POST /v1/sessions · X-Api-Key · state: created

    Checks that run at this step

    • Velocity limit: at most 5 sessions per applicant per 24 hours
    • Velocity limit: at most 20 sessions per IP per 24 hours
    • Tenant balance check on production sessions
    • Reusable KYC: an approved verification newer than 180 days with no AML alert skips re-verification
  2. End user

    Opening the flow

    The user opens the WebSDK (iframe) or a mobile SDK. Instead of an API key, the SDK works with a short-lived JWT scoped to that session, valid for 15 minutes by default. Tenant theme and language (TR/EN) are applied at this step.

    GET /v1/sessions/{id}/config · short-lived JWT (15 min) · CORS allowlist

    Checks that run at this step

    • Session validity window: 60 minutes (it moves to expired past that)
    • Per-tenant CORS allowlist — the SDK only loads from declared origins
    • Active modules (document / liveness) are read from the session config
  3. End user

    Document selection and capture

    The user picks a document type and captures it with the camera. Card edges are detected and cropped automatically; overly blurry or dark frames are flagged on-device and re-captured before ever reaching the server. On the NFC path the MRZ is scanned first — the key that unlocks the chip is derived from it.

    POST /v1/sessions/{id}/access-keys · POST /{id}/documents/images

    Checks that run at this step

    • Supported types: Turkish ID card, passport, driving licence, residence permit, Ghana Card
    • The back side is mandatory where the profile requires it (TD1 MRZ sits on the back)
    • On-device quality gates: sharpness, brightness, framing
  4. IDV platformPhoto path

    Document analysis

    The session moves to document_processing and a background worker analyzes the images: PP-OCR field reading, MRZ decoding via a separate path calibrated for OCR-B, ICAO 9303 check digit validation, and tamper detection via ELA and texture analysis. Each check produces a 0–100 score, reduced to a single document score by the profile weights.

    state: document_processing → liveness_pending | review | rejected

    Checks that run at this step

    • 15 scored checks (with per-profile weights in the table below)
    • 3 unweighted hard rules: file integrity, document expiry, specimen detection
    • Cross-field consistency between front and back (MRZ ↔ printed fields)
  5. IDV platformNFC path

    Chip reading and passive authentication

    On eMRTD-compliant documents the chip is accessed over a BAC-established encrypted channel (Secure Messaging); data groups DG1 (MRZ), DG11 and DG12 are read. ICAO 9303 Passive Authentication proves two things: the hashes in the SOD show the data is unaltered, and the Document Signer certificate shows the data was genuinely written by the issuing state.

    POST /{id}/documents/nfc · state: nfc_processing → liveness_pending | review

    Checks that run at this step

    • SOD hash integrity — verified separately for each data group
    • Document Signer certificate signature, validated against the CSCA trust chain
    • Chip values are compared to the declared document number / date of birth / expiry — a mismatch goes to manual review (the chip is authoritative)
  6. IDV platform

    AML / sanctions screening

    The name extracted from the document is screened against open sanctions lists synced daily. Names are normalized (accents and Turkish characters folded), records with a fuzzy match score of 90% or above become candidates, and candidates whose birth year conflicts are eliminated.

    rapidfuzz token_sort_ratio ≥ 90% · match → state: review

    Checks that run at this step

    • OFAC SDN (U.S. Treasury), UN Consolidated and EU FSF lists
    • False-positive elimination via birth-year conflict checks
    • A match never auto-rejects — the decision is left to a human
  7. End user

    Liveness detection and face matching

    The server generates a random sequence of 3–4 challenges (at least one blink and one head movement are guaranteed) alongside a single-use identifier. The user submits one frame per challenge plus a selfie; the server verifies each frame independently against its challenge type, then biometrically compares the selfie to the document photo.

    POST /{id}/liveness/start → /{id}/liveness/submit · challenge TTL 300 s

    Checks that run at this step

    • Every active challenge must pass — no tolerance
    • Frame-to-frame consistency: same person, and no static replay
    • Passive anti-spoofing (MiniFASNet ensemble) + heuristic LBP/FFT/YCrCb signals
    • ArcFace embedding comparison between document photo and selfie
    • Each approved face is written to pgvector; the same face under a different identity raises a duplicate signal
  8. IDV platform

    Decision and delivery

    The outcome of every layer is reduced to a single terminal state. Whatever the decision, each state transition is written to a timestamped event log. The result is delivered to your system via an HMAC-SHA256 signed webhook, and can always be read back from the result endpoint.

    webhook · X-Idv-Signature: hmac-sha256=… · GET /{id}/result

    Checks that run at this step

    • Terminal states: approved, review, rejected, expired
    • A rejected session grants the user 3 retry attempts
    • Failed webhook deliveries are retried; delivery records are retained
    • Personal data is deleted automatically 90 days after the terminal state

State machine

Session states

A session can only make defined transitions, each one written to the audit log, with no way back. This structurally blocks replay attempts that resubmit an earlier step.

  1. created

    Created

    Session opened; the user has not entered the flow yet.

  2. document_pending

    Awaiting document

    SDK open, waiting for the document upload.

  3. document_processing

    Document in review

    Image checks and OCR/MRZ decoding are running.

  4. nfc_processing

    Chip in review

    On the NFC path, chip data and passive auth are being processed.

  5. liveness_pending

    Awaiting liveness

    Document passed; waiting for the challenge sequence.

  6. liveness_processing

    Liveness in review

    Active/passive layers and face matching are running.

  7. approved

    Approved

    All checks passed — identity verified.

  8. review

    Manual review

    No automatic decision; awaiting an operator.

  9. rejected

    Rejected

    One or more checks failed conclusively.

  10. expired

    Expired

    The session was not completed within 60 minutes.

Document engine

Check list and weights

Each document type carries its own weight set — the MRZ dominates on a passport, while text readability leads on a driving licence that has no MRZ. The percentages below are the contribution shares when every check runs.

Check list and weights
CheckTR ID CardPassportDriving Lic.Residence P.Ghana Card
MRZ ValidationICAO 9303 machine-readable zone: check digits and field consistency.19.5%27.1%25.3%23.5%
Text ReadabilityHow many document-specific keyword groups OCR can find.8.8%10.4%19.8%12.6%9.8%
Sharpness / FocusBlur measured via Laplacian variance.8.8%10.4%12.3%10.5%9.8%
Tampering (ELA)Error Level Analysis: traces of re-saved or edited regions.7.1%8.3%9.9%8.4%7.8%
Face DetectionPresence and placement of the biometric portrait on the document.7.1%8.3%9.9%8.4%7.8%
Screen/Print DetectionMoiré patterns via FFT periodic peak analysis — a photo of a screen.7.1%8.3%9.9%8.4%7.8%
Document ContourID-1 rectangular edge detection and the 1.586:1 aspect ratio.5.3%6.3%7.4%6.3%5.9%
Brightness & GlareOverly dark, blown-out or flash-glared frames.4.4%5.2%6.2%5.3%4.9%
Local Texture ConsistencyRegional texture deviation — region-level splicing detection.4.4%5.2%6.2%5.3%4.9%
ResolutionA readability floor of at least 600×400 pixels.2.7%3.1%3.7%3.2%2.9%
TR National ID AlgorithmMathematical checksum validation of the Turkish national ID number.8.0%14.8%
Ghana Card PINGHA-XXXXXXXXX-X format plus cross-check against the MRZ.8.8%
Colour SignatureThe turquoise/pink print colour signature of the Turkish ID card.7.1%
Micro PrintPresence of the repeating fine print pattern on the back side.4.4%
Data ConsistencyCross-comparison of MRZ fields against the printed fields on the front.5.3%7.3%6.3%5.9%

A check that could not run (the MRZ with no back side, for example) never enters the score; the remaining checks are rescaled among themselves. Missing data therefore does not behave like a low score.

Unweighted hard rules

These three checks do not enter the score — they set the outcome directly. Even at a score of 100, a failure here blocks automatic approval.

  • File Integrity

    Corrupt, empty or under-5 KB files — no other check is run.

  • Document Validity

    A check-digit-verified expiry date in the past is a hard reject.

  • Specimen Detection

    Specimen markings and known sample document numbers.

Scoring

How the decision is made

Every check produces a score between 0 and 100. The document score is the weighted average of the checks that ran, and falls into one of three decision bands.

Document score

Σ (check score × weight) ÷ Σ (weight)

Thresholds can be raised per tenant but never lowered — the rule engine clamps every value to the global floor.

  • ≥ 70Automatic passDocument passed; the flow advances to liveness (or straight to approval in document-only mode).
  • 45 – 69Manual reviewA document was detected but could not be fully verified; an operator decides.
  • < 45Automatic rejectThe checks do not support the validity of the document.

Hard rules that override the score

In these cases the decision is as follows regardless of the weighted score.

  • Face but no text → reject

    Catches users who upload a selfie instead of a document. The rule is disabled once the MRZ is verified, so a genuine card is never rejected by mistake.

  • No document evidence → reject

    With no face, no readable text and no MRZ, this is not an identity document; even a review-band score is turned into a reject.

  • Expired document → reject

    A hard reject when the expiry date is verified by its MRZ check digit and lies in the past.

  • Specimen document → reject

    A conclusive specimen marking rejects; a weak or ambiguous marking goes to manual review instead of automatic approval.

  • National ID cross-check failed → review

    Splicing the two sides of different cards is only visible in the cross-comparison; automatic approval is blocked and a human decides.

  • AML match → review

    A sanctions list match never produces an automatic rejection under any circumstances.

  • Duplicate face → review

    If the same face was previously approved under a different identity, the session is routed to a human.

  • Chip/declaration mismatch → review

    Where the NFC chip value differs from the declared one, the chip is treated as authoritative and the session goes to review.

Liveness

Three layers of liveness assurance

The layers complement each other: the active layer proves the user is really there, the passive layer proves what faces the camera is not a screen or a print, and the heuristic layer looks for artifacts the other two miss.

  1. 1

    Active challenges

    The server generates a random sequence (blink, head turn). Each frame is verified independently on the server against its challenge type — the client claiming 'passed' counts for nothing.

    MediaPipeHaar cascadeHead pose

  2. 2

    Passive anti-spoofing

    A MiniFASNet ensemble: two independent models sensitive to print, screen replay and moiré artifacts produce a single genuineness probability.

    MiniFASNetV2MiniFASNetV1SEONNX

  3. 3

    Heuristic signals

    Texture, frequency and colour-space heuristics (LBP / FFT / YCrCb), frame-to-frame consistency and optical-flow motion analysis are weighed as secondary signals.

    LBPFFTOptical flow

Liveness confidence score

(passive score × 0.35 + face match × 0.65) × 100

Two thirds of the weight sits on the face match: a genuine face that does not belong to the person on the document is not rescued by a high passive score. And the score alone is not enough — every gate beside it must be cleared as well.

Gates that must be cleared

Active challenges
allA single missing or failed frame fails the attempt; the user can retry.
Passive score floor
≥ 0.40Lower bound on the ensemble genuineness probability.
Anti-spoof gate
≥ 0.55Ensemble threshold for a 'genuine face' verdict.
Confidence score
≥ 60Lower bound on the combined liveness confidence (a tenant may raise it).
Challenge TTL
300 sValidity window of the single-use challenge id — it closes the replay window.

Face matching and duplicate detection

The document photo and the selfie are compared through ArcFace embeddings. Every approved face is written to a vector database, which catches the same face enrolling again under a different identity.

  • 0.55

    Match threshold

    Lower bound on cosine similarity between document photo and selfie.

  • 0.60

    Quality gate

    SCRFD detection score — no embedding is produced from blurry or partial faces.

  • 0.75

    Duplicate threshold

    Normalized cosine; above it is a 'same person' suspicion and goes to manual review.

AML

Sanctions list screening

Screening uses publicly available lists only; identity data is never sent to a third-party commercial data vendor. Lists are downloaded by a daily cron and written to a local database.

  • OFAC SDN

    U.S. Department of the Treasury — Specially Designated Nationals list (CSV).

  • UN Consolidated

    United Nations consolidated sanctions list (XML).

  • EU FSF

    European Union Financial Sanctions Files (CSV).

  • PEP (optional)

    An operator-supplied politically exposed persons source — skipped when not configured.

How matching works

  1. 1The name is normalized: accents and Turkish characters are folded, leaving only A–Z and single spaces.
  2. 2Fuzzy matching runs via rapidfuzz token_sort_ratio, so a different word order does not break the match.
  3. 3Records scoring 90% or above are taken as candidates.
  4. 4A candidate whose birth year conflicts with the one read from the document is eliminated (false-positive filter).
  5. 5If any match survives, the session goes to manual review and the match details are written to the record.

A match never produces an automatic rejection. Because sanctions lists can contain people who merely share a name, the final decision always rests with a human.

Abuse protection

Limits and windows

All of these are counted per environment — sandbox testing never consumes a production limit.

5 / 24 h
Sessions / applicant
Daily sessions openable for the same applicant_external_id.
20 / 24 h
Sessions / IP
Daily sessions openable from the same IP address.
3
Retries
Retry attempts granted after a rejection; beyond that the API returns 409.
60 min
Session lifetime
An incomplete session becomes expired after this window.
15 min
SDK token
Lifetime of the short-lived JWT used by the web and mobile SDKs.
180 days
KYC reuse
An approved verification newer than this is not asked for again (absent an AML alert).
90 days
PII retention
How long after the terminal state personal data is automatically deleted.

Delivery

Getting the result into your system

A distinct event is produced for every status change. Webhooks are signed with HMAC-SHA256; undeliverable ones are retried, and every delivery attempt is recorded.

  • document.verifiedThe document (or chip) was verified; the flow moved on to liveness.
  • document.review_requiredThe document could not be auto-verified, or there is an AML match — an operator decides.
  • document.rejectedDocument checks failed conclusively.
  • liveness.failedOne of the liveness layers was not cleared.
  • session.manual_reviewLiveness passed but there is a duplicate-face suspicion.
  • session.approvedAll checks passed — identity verified.

# webhook

X-Idv-Signature: hmac-sha256=9d41…

{ "event_type": "session.approved",

"session_id": "s_7f3a…",

"status": "approved",

"environment": "production" }

Beyond the webhook, the result can always be read via GET /v1/sessions/{id}/result, so a missed webhook never stalls the flow.

Important note

This page describes the platform's current behavior. Thresholds and limits may be configured more strictly in your tenant agreement; loosening them is not possible.