On this page

Liveness & PAD policy

This page is for a backend engineer or a risk owner who reads the results of a hosted identity verification and wants to know why checks.liveness and checks.selfie read review, what each reason code means, and which decisions your system should leave to a reviewer. It explains what the results mean and what to do with them. Model and vendor names and the internal score limits are not published.

Key points

  1. PAD is advisoryNoxtica reports the PAD result and never lets it decide. Every PAD result reads review, whatever its score.
  2. Liveness and selfie read at best reviewpass is not reachable for checks.liveness or checks.selfie while PAD is advisory. This is policy, not a capture problem.
  3. Two layers keep a verification in reviewThe check cap, and the hosted outcome: unverified with provider_manual_review until a reviewer decides. A validated PAD would remove the first layer, not the second.
  4. Decide on the reviewer, not on a checkTake the outcome from the reviewer decision. Do not auto-approve on any check, and do not ask for a new capture because of pad_unvalidated_model.
How this page is organisedBar length shows each section’s share of the text. Select a section to jump to it.

What it is

Availability: Controlled availability. Identity verification is provisioned per tenant by your account team. This page describes what the hosted verification reports for the liveness step and for the selfie; it applies to every hosted verification.

In short

  • Presentation-attack detection (PAD) is advisory. Noxtica reports its result and never lets it decide. Every PAD result reads review, whatever its score.
  • checks.liveness and checks.selfie read at best review. pass is not reachable for either while PAD is advisory. scorecard.overall is therefore at best review as well.
  • review from pad_unvalidated_model is policy, not a capture problem. The person did nothing wrong, and a retake reads the same.
  • The PAD score is information. It is not a live or spoof verdict.
  • Two independent layers keep a verification in review: the check cap above, and the hosted outcome: the automated run of a hosted verification ends unverified with provider_manual_review, and a reviewer’s decision is what moves it on.
  • Nothing here is a tenant setting. Every limit and both layers are the same for every customer.

What PAD is

Presentation-attack detection tries to tell a live face in front of a camera from a presentation of a face: a printed photo, a photo or video replayed on a screen, a mask. In hosted verification it looks at frames of the liveness challenge, and separately at the selfie.

PAD is not the same as the gesture checks. The gesture checks (turn_left, turn_right, turn_up, turn_down, blink) show that the person moved as asked. PAD looks at the pixels of a frame and produces a live score.

Why PAD is advisory

A PAD score is worth acting on once the point at which a frame counts as live or as an attack has been measured on the population it will judge: genuine people on real devices in real light, and real attacks of each kind. That qualification has not been done on Noxtica’s own capture population. Until it is, a high score is not evidence that the person is live and a low score is not evidence of an attack, so the result is reported and never used to decide.

Promoting PAD to a decision needs a new qualification and a documented contract change. When that happens it is published in the API reference and its change log, and this page changes with it. No version is promised here.

What advisory means for each check

SurfaceWhat you read while PAD is advisory
checks.liveness (identity read)review, fail or null. Never pass. fail when a gesture confidently failed. null when no automated result was recorded.
checks.selfie (identity read)At best review. It reads fail only when a hard selfie-quality check fails.
session.scorecard.livenessreview or fail (or pending / skipped). Gesture checks can read pass, the pad check and the overall active_liveness check do not.
session.scorecard.selfieAt best review, with presentation_attack_detection_inconclusive and pad_unvalidated_model when the quality checks all pass.
session.stages.active_livenessreview or fail. score is null.
session.scorecard.overallAt best review.
numeric scores on the pad (liveness) and live_score_band / pad_class_score (selfie) checksInformation for a reviewer and for your own analysis. Not a verdict. Do not set your own live or spoof cut-off on them.

The two review layers

LayerWhat it isWhat lifts it
1. Check capchecks.liveness and checks.selfie cannot read pass while PAD is advisory.A PAD whose operating point is qualified and that Noxtica then lets decide.
2. Hosted outcomeThe automated run of every hosted verification ends verification.status: "unverified" (verification.source: "pipeline") with reasonCodes: ["provider_manual_review"] and the session waits in review_pending. A reviewer’s approve makes verification.status verified (verification.source: "review"); an override is recorded in review and does not upgrade the status. Either one sends kyc.review.decided.A reviewer decision. It is a separate policy from PAD.

A validated PAD would remove layer 1 only. Layer 2 stays: no check result, however good, makes a hosted verification verified by itself.

PAD reason codes

CodeMeaningStatus it causesEmitted today
pad_unvalidated_modelThe PAD result is advisory by design.pad check reviewYes, on every PAD result
presentation_attack_detection_inconclusiveScorecard form of the same fact: the PAD analysis as a whole is inconclusive. It appears next to pad_unvalidated_model on scorecard.liveness and scorecard.selfie.step reviewYes
pad_face_not_detectedThe PAD analysis did not find a face on a frame, even though other checks may have. The verification does not end in an error: the other checks continue. In the liveness result it comes with pad_unvalidated_model.reviewYes
pad_unavailablePAD could not run.reviewNo, reserved. A liveness check that cannot run at all shows one of the “could not run” codes below instead.
pad_incompletePAD did not evaluate every challenge.reviewNo, reserved
pad_reviewA PAD score that falls in the middle band once PAD decides.reviewNo, reserved for when PAD decides
pad_rejectedA PAD score that falls in the lowest band once PAD decides.failNo, reserved for when PAD decides

Reserved codes are part of the published vocabulary so that your code can already accept them. Do not branch on them today: they are not produced.

Gesture reason codes

These explain a gesture check that did not pass. The gesture checks are turn_left, turn_right, turn_up, turn_down and blink (the passive variant has one passive_hold check). A check that reads review is written <name>_inconclusive in scorecard reason codes, and a failed one <name>_failed.

CodeMeaningStatus it causes
challenge_direction_inconsistentThe head movement did not match the requested direction. It is present when the gesture failed, or when the gesture reads review and no more specific cause below applies. A review that names its cause (for example client_metrics_unavailable) does not carry it.gesture fail (or review)
landmark_peak_mismatchThe browser’s reported peak frame does not match the server’s measurement. For up and down it is judged just when the head-pose measurement was available.gesture fail (turn left and right, and up and down with a head-pose measurement)
no_face_detected, multiple_facesA frame had no face, or more than one face.gesture fail
face_track_lostThe face was lost between frames.review or fail
client_metrics_unavailable, client_landmark_low_confidenceThe browser did not provide its own measurements, or provided them with low confidence. A blink is judged by the server on its own frames and does not carry them.caps at review
neutral_reference_unavailableNo usable starting pose (fewer than three single-face frames in the blink burst).review, never pass
pose_landmarks_unavailableThe head-pose measurement was unavailable for a frame, so up and down cannot be judged.pitch gesture review
blink_inconsistentThe blink could not be confirmed. When a blink-like cycle existed it comes with one of the three codes below.blink review or fail
blink_closed_plateauA real eye closing and reopening was found, but the closed frame sits next to another almost identical near-closed frame.blink review
blink_scene_changedThe blink was found, but the nose region, which serves as a control for lighting and head movement, changed between the open frame and the reopened frame.blink review
blink_cycle_partialJust part of the evidence for a blink was present, or the cycle was incomplete.blink review
blink_duration_out_of_rangeThe blink cycle lasted outside 50 to 1500 ms.blink review
passive_temporal_evidence_unavailable, passive_temporal_inconsistent, motion_implausible, frame_duplicate_suspectedPassive-hold variant: not enough or implausible motion across the three frames, or repeated frames. passive_temporal_inconsistent is present when the result is fail, or when a review has no more specific cause.review (inconsistent: fail)

The scorecard also carries active_liveness_inconclusive, active_liveness_failed and active_liveness_fail for the overall liveness result.

Codes for a liveness check that could not run

When the liveness check could not run at all, the result is review, never fail, and the stage reason is one of these codes. They say that no gesture was judged, not that the person failed.

CodesMeaning
evidence_missing, evidence_unavailable, evidence_wrong_content_type, invalid_evidence_package, evidence_lookup_failedThe capture package was missing, could not be read, was the wrong kind of file, was not a valid package, or could not be looked up.
transport_error, unexpected_status, malformed_response, malformed_refusal_bodyThe verification service did not answer in time, refused the request, or answered in a form that could not be read.
adapter_not_configured, adapter_config_invalid, not_configured, weights_ungatedThe liveness analysis was not set up for the environment or was not available there.

Prerequisites

  • A hosted verification that has reached the submit step, so that a result exists. Before that, the liveness step reads pending.
  • A server key that can read the session status (GET /v1/kyc/sessions/{sessionId}, see Server API reference: KYC), and, for checks.*, the identity read (GET /v1/kyc/verifications/{verificationId}/identity, permission read:identity_details).
  • A webhook endpoint subscribed to kyc.review.decided (and kyc.session.completed for a hosted session), if you complete your own flow on the reviewer’s decision.

Steps

Decide what your system does with a result

  1. Take the outcome from the reviewer decision. Read verification.status, verification.source and review in the session status, or react to kyc.review.decided. Treat unverified / pipeline with provider_manual_review as “waiting for a person”.
  2. Do not auto-approve on any check. No check result changes verification.status, and no check, pass included, replaces the reviewer decision.
  3. Do not read a gesture pass as proof that the face was live. The gesture checks show that the requested movement happened. They are not a presentation-attack test.
  4. Do not treat review with pad_unvalidated_model as a capture failure. Do not ask the person for a new capture because of it.
  5. Read fail as “a gesture confidently failed”. Use the gesture check and its reason code to see which one. A fail on a person who is clearly genuine is a false reject: report it with the sessionId.
  6. Treat the PAD score as information. Show it to your own reviewers if you like. Do not turn it into a cut-off.
  7. Do not auto-reject on review. review means “no confident answer, a person should look”.

Read per-gesture checks as information

In session.scorecard.liveness.checks, read the five gesture checks first. When every gesture check is pass: true and only active_liveness and pad are pass: false, the person did all five gestures and the review is the PAD policy. When a gesture check is pass: false, its reason codes say why.

  1. Read the outcome

    Read verification and review in the session status, or react to kyc.review.decided.

  2. Read the gesture checks

    turn_left, turn_right, turn_up, turn_down and blink say whether each movement was seen.

  3. Spot the PAD policy

    When just active_liveness and pad read pass false, the review is the advisory PAD policy.

  4. Look up a reason code

    A check that did not pass names its cause in a reason code listed on this page.

  5. Leave the decision to the reviewer

    Do not auto-approve, auto-reject or ask for a retake because of pad_unvalidated_model.

Read a liveness result in five steps

Verify it works

Take a hosted session whose person completed the liveness step and the selfie, and read GET /v1/kyc/sessions/{sessionId}. A result that follows this policy looks like this (the values are an illustration):

WhereValue
session.verificationstatus: "unverified", source: "pipeline"; reasonCodes holds provider_manual_review while the session waits in review_pending
session.scorecard.liveness.statusreview
session.scorecard.liveness.checksturn_left, turn_right, turn_up, turn_down, blink: pass: true. active_liveness, pad: pass: false.
session.scorecard.liveness.reasonCodesactive_liveness_inconclusive, presentation_attack_detection_inconclusive, pad_unvalidated_model
session.scorecard.selfie.statusreview, with presentation_attack_detection_inconclusive and pad_unvalidated_model
checks.liveness, checks.selfie (identity read)review, review
after a reviewer approvessession.verification reads status: "verified", source: "review", session.review.decision is approve, kyc.review.decided is delivered, and provider_manual_review stays in reasonCodes. The check results do not change.

If your system reads this as a problem with the person’s capture, change the rule in your system: this is the expected reading.

Troubleshooting

You seeIt meansWhat to do
checks.liveness: "review", every gesture pass: truePAD policy (layer 1).Nothing. Wait for the reviewer decision.
checks.selfie: "review", quality checks all passPAD policy (layer 1).Nothing. Do not ask for a new selfie.
verification.status: "unverified", provider_manual_review, review: nullLayer 2. A reviewer has not decided yet.Wait for kyc.review.decided.
pad_face_not_detectedThe PAD analysis found no face on a frame. The rest of the verification continued.Nothing in your integration. A reviewer looks at it.
blink_inconclusiveThe blink was not measured or not confirmed.Treat it as “not measured”, not “no blink”. A reviewer looks at it.
turn_*_failedThe head barely moved, the face was very small, or the light was poor.Your policy: the hosted page already has a retake budget for the person.
fail on a genuine personA false reject.Report it with the sessionId.
A stage reason such as evidence_missingThe liveness check could not run.A reviewer looks at it. It is not a failure of the person.