Skip to main content

Handling results

Once a verification runs, you have three ways to receive the verdict. Each fits a different architecture.

Quick comparison

MethodWhen to useLatencyReliability
Widget eventsSingle-page apps, immediate UX feedback<100msGood
PollingServer-side flows, no public webhook URL2-5s typicalGood
WebhooksProduction B2B, async processing1-3s typicalBest

For most production systems, webhooks are the recommended approach. Polling is fine for prototypes.

Method 1 — Widget events

The widget emits a veridia:complete event in the browser as soon as the API accepts the verification. Easiest path for SPAs.

What you get

{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"userRef": "customer-12345",
"status": "queued" // or "processing" or "completed"
}

The status is the initial state. The verdict isn't here yet — you still need to fetch it.

Pattern

<veridia-widget id="kyc" publishable-key="qv_pub_..."></veridia-widget>

<script>
document.getElementById('kyc').addEventListener('veridia:complete', async (e) => {
const { verificationId } = e.detail;

// Send to your own backend, which calls GET /v1/verify/:id with the SECRET key
const response = await fetch('/api/kyc-completed', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ verificationId }),
});

const result = await response.json();
console.log('Verdict:', result.verdict); // approved / review / rejected
});
</script>

:::warning Never call /v1/verify/:id from the browser The browser-facing publishable key (qv_pub_*) is intentionally limited. To fetch verdicts, use a server-side request with your secret key (qv_sec_*). Otherwise anyone could poll any verification. :::

Method 2 — Polling GET /v1/verify/:id

If your backend received the verificationId (from the event or via a form submission), poll the status endpoint until it's completed.

curl

curl -X GET https://api.xxuxe.online/v1/verify/vf_AG07CDWRRFQV4T05ZXG2 \
-H "Authorization: Bearer qv_sec_YOUR_SECRET_KEY"

Response when ready:

{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"status": "completed",
"verdict": "approved",
"confidence": 87.4,
"scores": {
"ocrConfidence": 78.0,
"faceMatch": 96.2,
"liveness": 91.5,
"docQuality": 85.0
},
"flags": [],
"submittedAt": "2026-05-01T18:39:05Z",
"completedAt": "2026-05-01T18:39:08Z"
}

JavaScript / Node.js

async function pollVerification(verificationId, maxAttempts = 30) {
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://api.xxuxe.online/v1/verify/${verificationId}`,
{
headers: {
'Authorization': `Bearer ${process.env.VERIDIA_SECRET_KEY}`,
},
}
);

const data = await response.json();

if (data.status === 'completed' || data.status === 'failed') {
return data;
}

await new Promise(r => setTimeout(r, 1000)); // wait 1s
}
throw new Error('Verification did not complete in time');
}

const result = await pollVerification('vf_AG07CDWRRFQV4T05ZXG2');
console.log('Verdict:', result.verdict);

Python

import os
import time
import requests

def poll_verification(verification_id, max_attempts=30):
headers = {"Authorization": f"Bearer {os.environ['VERIDIA_SECRET_KEY']}"}

for _ in range(max_attempts):
r = requests.get(
f"https://api.xxuxe.online/v1/verify/{verification_id}",
headers=headers,
timeout=10,
)
r.raise_for_status()
data = r.json()

if data["status"] in ("completed", "failed"):
return data

time.sleep(1)

raise TimeoutError("Verification did not complete in time")

result = poll_verification("vf_AG07CDWRRFQV4T05ZXG2")
print("Verdict:", result["verdict"])

PHP

<?php
function pollVerification(string $verificationId, int $maxAttempts = 30): array {
$secretKey = $_ENV['VERIDIA_SECRET_KEY'];

for ($i = 0; $i < $maxAttempts; $i++) {
$ch = curl_init("https://api.xxuxe.online/v1/verify/$verificationId");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $secretKey",
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);

if (in_array($data['status'], ['completed', 'failed'], true)) {
return $data;
}

sleep(1);
}

throw new RuntimeException("Verification did not complete in time");
}

$result = pollVerification("vf_AG07CDWRRFQV4T05ZXG2");
echo "Verdict: " . $result['verdict'] . "\n";

Webhooks are push-based: when a verification completes, Veridia sends a signed HTTP POST to your endpoint. No polling, no missed events, full audit trail.

Setup

  1. In your dashboard, go to Webhooks
  2. Set the webhook URL to your endpoint (e.g., https://yourapp.com/webhooks/veridia)
  3. Copy the webhook secret — you'll need it to verify signatures
  4. Done. Every completed verification triggers a POST.

What you receive

{
"event": "verification.review_required",
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"tenantId": "tn_default_demo",
"userRef": "customer-12345",
"verdict": "review",
"confidence": 77.85,
"scores": {
"faceMatch": 99.5,
"liveness": 88.0,
"ocrConfidence": 20.0,
"docQuality": 75.7
},
"flags": [
{ "level": "warn", "text": "heavy_glare" }
],
"completedAt": "2026-05-01T18:39:08Z"
}

The event field will be one of:

  • verification.approved
  • verification.rejected
  • verification.review_required

The HTTP request includes a signature header you must verify (see signature verification for the exact algorithm).

Why prefer webhooks

ConcernPollingWebhooks
Latency1s polling = 1s avg delay<100ms after completion
API callsManyJust the one delivery
ReliabilityYour code must runVeridia retries 5 times with exponential backoff
Audit trailNoneFull delivery log in dashboard
Cold startsWakes serverless every pollFires once

Acting on the verdict

Whatever method you use, the action is the same:

function onVerdict(result) {
switch (result.verdict) {
case 'approved':
// Mark user as KYC'd, enable full access
enableUserAccount(result.userRef);
break;

case 'review':
// Send to manual review queue, pause sensitive actions
queueForReview(result.verificationId, result.flags);
break;

case 'rejected':
// Block, ask user to retry or contact support
blockUserKyc(result.userRef, result.flags);
break;

default:
// Should never happen, log it
console.error('Unknown verdict:', result.verdict);
}
}

What's next

Quickstart complete. From here, depending on what you're building:

  • Widget docs — every attribute, event, and styling option
  • API Reference — full REST API for server-side integrations
  • Webhooks — signature verification, retry behavior, examples
  • Compliance — data retention, SEPRELAD, LGPD, GDPR

Need help? Contact support.