TrustWixDocs
Handle results

Statuses

The lifecycle of a verification, and which states you are allowed to act on

status tells you where a verification is in its life. verdict tells you what was decided. They are separate fields answering separate questions, and reading one for the other is the most common integration bug we see.

The six statuses

StatusTerminalMeaning
pendingnoCreated. The user has not finished submitting.
processingnoSubmissions received, checks are running.
approvedyesEvery required check passed.
rejectedyesAt least one required check failed.
manual_reviewyesA human needs to look at this before it is final.
expiredyesThe user never completed the session in time.

There is no completed status. A finished verification lands on approved, rejected or manual_review, and treating those three as the terminal set is the correct way to write your handler.

Which states you may act on

Do nothing on pending or processing. A verification in those states may already have some checks resolved, but the roll-up is not final and can still change.

approved, rejected and manual_review are the decision points. expired is not a decision, it means the user dropped out, so the right response is usually to invite them to start again rather than to reject them.

switch (verification.status) {
  case "approved":
    return grantAccess(user);
  case "rejected":
    return declineWithReasons(user, verification.reason_codes);
  case "manual_review":
    return holdPendingReview(user);
  case "expired":
    return inviteToRetry(user);
  default:
    return; // pending or processing: not a decision yet
}

manual_review is terminal for you, not for us

manual_review means the automated pipeline has finished and handed the case to a person. It is a terminal status from your integration's point of view, so you act on it, typically by holding the account in a restricted state.

When the review concludes, the verification's verdict is updated and you receive another webhook. That is why your handler must be safe to run more than once for the same verification, and why you should apply the latest state rather than assume the first terminal event you saw is the last word.

Expiry

Every verification carries expires_at. An unfinished session past that point moves to expired and its hosted link and client token stop working. Create a fresh verification for a returning user rather than trying to revive an expired one. The expired record stays in your history.

Per-check statuses

Each check inside a verification has its own status: pending, processing, completed or failed. failed means the check could not be evaluated at all, for example because a capture was unusable, which is different from the check completing with a reject verdict. Both surface reason codes, so your user-facing copy can distinguish "we could not read this" from "this did not pass".

On this page