Skip to main content

First verification

Time to run a real verification with the widget you embedded in the previous step.

What you're about to test

A complete user flow:

  1. User clicks Start
  2. Browser asks for camera permission
  3. User photographs the front of their document
  4. User photographs the back (only if require-doc-back="true")
  5. User takes a selfie
  6. Widget runs quality checks, uploads to Cloudflare R2, calls the API
  7. You receive a veridia:complete event with the verificationId
  8. The verdict (approved / review / rejected) is computed in ~2 seconds

Run it

Open the page where you embedded the widget. Use a real device with a camera — the widget is mobile-first but works on laptops too.

:::tip Local testing If you're testing on localhost, add localhost (or 127.0.0.1) to the allowed origins for your test API key in the dashboard. Without that, the widget will refuse to load. :::

Tips for the document capture

  • Hold the document flat on a contrasting surface (avoid white-on-white)
  • Don't cover any corners with your fingers
  • Avoid direct light reflecting off the document (heavy_glare flag will trigger)
  • Make sure the document is fully in frame
  • Hold the phone steady — blurry shots get rejected by the multi-signal quality check

Tips for the selfie

  • Face the camera directly
  • Good even lighting (no backlight)
  • Remove sunglasses, hats that cover the face
  • Stay still for the capture

Inspect the event payload

Add a console.log listener to see exactly what the widget emits:

<script>
document.querySelector('veridia-widget')
.addEventListener('veridia:complete', (e) => {
console.log('verification complete:', e.detail);
});

document.querySelector('veridia-widget')
.addEventListener('veridia:error', (e) => {
console.error('verification error:', e.detail);
});
</script>

When the user finishes, your console will show something like:

{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"userRef": "customer-12345",
"status": "queued"
}

The verificationId is what you'll use to fetch the final result via GET /v1/verify/:id or what arrives in your webhook.

See it in your dashboard

Go to your Veridia dashboard and open the Review queue. You'll see your verification with:

  • Submitter info (user ref, submitted timestamp)
  • Scores breakdown (overall confidence, OCR, face match, liveness, doc quality)
  • Flags (e.g., heavy_glare, low_face_match)
  • The final verdict

Click into a verification to see the full breakdown and the captured images.

What happens behind the scenes

When the widget calls the API on submit, this pipeline runs:

StepWhereWhat
1BrowserQuality checks (Laplacian, Tenengrad, Brenner)
2BrowserDirect upload to Cloudflare R2 (presigned URL)
3WorkerOCR via Workers AI — extracts name, doc number, dates
4WorkerDispatches to backend with all extracted data
5BackendFace match (insightface buffalo_s)
6BackendLiveness scoring
7BackendComputes weighted confidence score
8BackendDetermines verdict: approved / review / rejected
9BackendPersists to MySQL with audit trail
10BackendFires webhook (if configured)

End-to-end latency: ~2.0 to 2.7 seconds for a typical verification.

What the verdict means

VerdictConfidenceWhat you should do
approvedHigh score, all signals passTrust the user, complete onboarding
reviewMedium score, some flags raisedSend to your manual review queue
rejectedLow score, hard failuresBlock, ask user to retry, or escalate

Common errors at this stage

ErrorLikely causeFix
errorInvalidKeyAPI key is revoked or test key in prodCheck the key in your dashboard
errorRateLimitedToo many requests in a short windowAdd throttling on your end
errorInsufficientCreditsTenant ran out of creditsTop up in dashboard or contact support
errorBlurryImage quality too lowUser retakes (widget handles automatically)
errorNoFaceSelfie face not detectedUser retakes with better framing
errorUploadNetwork failure or R2 unreachableWidget retries automatically

Next step

You have a verification result. Now learn the three ways to consume it.

Step 3: Handling results →