Skip to main content
Not every check returns a clean match, and how you treat the other outcomes decides whether your integration is robust or brittle. The key is to separate three things that are easy to lump together: a no-match, a failure, and an error.

The three cases

not_found is a successful check with a real answer, and it is charged. Do not treat it as an error or retry it. Retrying a not_found just runs and bills the same lookup again with the same result.

Responding to each

1

found

Proceed. Read the result object by key for the details you need.
2

not_found

A definitive “no record.” Handle it in your product, ask the user to re-check the number, offer another method, and move on. Do not retry.
3

failed

The provider could not answer, usually a timeout or outage. This is safe to retry once, after a short delay. Do not loop.
4

4xx error

Fix the cause before retrying, since the same request will fail the same way. See below.

Reading why a check failed

A failed verification carries an errorMessage describing why, in plain language: liveness not confirmed, no face detected, the selfie did not match, the document could not be authenticated, and so on. Surface this to your own support view; it is usually enough to tell a genuine user problem from a transient one.

Matching errors to causes

A resilient pattern

1

Persist the reference immediately

Store the reference from the response before anything else. It is your record that the check happened and what it cost.
2

Branch on status, not on presence of result

Switch on status: found, not_found, failed. Do not infer failure from an empty result; a not_found legitimately has an empty result.
3

Retry only failures, only once

Retry failed and 502 a single time. Never retry not_found, 402, 403, or 422, since they will not change without action on your side.
4

Reconcile from the list

If you are unsure whether a check ran, list verifications rather than re-running, so you do not pay for a duplicate. See References and retrieval.