Skip to main content

The result

onComplete(result) fires once the server has reached its decision. That decision is authoritative.
Only approved should unlock whatever the verification gates. Treat pending and manual_review as “not yet” — resolve them from your backend against the case, not from the browser.

Correlating with your own records

caseId identifies the verification case. Store it against your user so support requests and any later status change can be reconciled.
Confirm the final state from your backend before granting access. A browser callback tells you what the user saw; it is not a substitute for server-side confirmation, and a client can always be tampered with.

Errors

onError({ error, fatal }) and the error event surface failures. Two typed classes are exported for instanceof checks:
The fatal flag is what to branch on: a non-fatal error leaves the widget mounted and usable, while a fatal one means the flow cannot continue and you should present your own fallback.
Do not surface error.body to end users. It is diagnostic detail meant for your logs — show your own message instead, and keep the raw payload server-side.

A note on what you can observe

The SDK reports flow progress so you can build a responsive UI around it. It does not report intermediate assessments, and there is nothing in the browser that predicts the outcome. This is deliberate. Identity decisions are made server-side precisely because the browser is an environment your users control, so any signal exposed there could be manipulated. Build against onComplete and your backend, and the design works in your favor.