Skip to main content

GET /v1/verify/:id

Fetch the current state of a verification. This is the endpoint you poll after /submit to get the verdict.

GET https://api.xxuxe.online/v1/verify/vf_AG07CDWRRFQV4T05ZXG2

Authentication

Bearer token. Use a secret key here, not a publishable one. The publishable key is intentionally limited to /init and /submit from whitelisted origins — fetching verdicts from the browser would let anyone enumerate other tenants' data.

Authorization: Bearer qv_sec_YOUR_SECRET_KEY

Path parameter

ParameterTypeDescription
:idstringThe verificationId returned by /init (e.g., vf_AG07CDWRRFQV4T05ZXG2)

Example request

curl

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

JavaScript / Node.js

const response = await fetch(
`https://api.xxuxe.online/v1/verify/${verificationId}`,
{
headers: {
'Authorization': `Bearer ${process.env.VERIDIA_SECRET_KEY}`,
},
}
);
const data = await response.json();
console.log(data.status, data.verdict);

Python

import os
import requests

response = requests.get(
f"https://api.xxuxe.online/v1/verify/{verification_id}",
headers={"Authorization": f"Bearer {os.environ['VERIDIA_SECRET_KEY']}"},
)
response.raise_for_status()
data = response.json()
print(data["status"], data.get("verdict"))

PHP

<?php
$ch = curl_init("https://api.xxuxe.online/v1/verify/$verificationId");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $_ENV['VERIDIA_SECRET_KEY'],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $data['status'] . " " . ($data['verdict'] ?? '');

Response

200 OK

While processing:

{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"status": "processing",
"submittedAt": "2026-05-01T18:39:05Z"
}

When complete:

{
"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"
}

When the user needs manual review:

{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"status": "completed",
"verdict": "review",
"confidence": 64.5,
"scores": {
"ocrConfidence": 88.0,
"faceMatch": 71.2,
"liveness": 88.0,
"docQuality": 75.0
},
"flags": [
{ "level": "warn", "text": "low_face_match" },
{ "level": "info", "text": "heavy_glare" }
],
"submittedAt": "2026-05-01T18:39:05Z",
"completedAt": "2026-05-01T18:39:08Z"
}

Response fields

FieldTypeAlways presentDescription
verificationIdstringYesThe verification ID
statusstringYesqueued, processing, completed, or failed
verdictstringOnly when completedapproved, review, or rejected
confidencenumberOnly when completedOverall weighted confidence score (0-100)
scoresobjectOnly when completedBreakdown of individual signals
scores.ocrConfidencenumberWhen OCR ranSelf-reported VLM confidence in document text extraction (0-100)
scores.faceMatchnumberAlwaysBiometric similarity between selfie and document photo (0-100)
scores.livenessnumberAlwaysAnti-spoofing score — confirms it's a live person (0-100)
scores.docQualitynumberAlwaysDocument image quality score (0-100)
flagsarrayYesQuality / risk flags. Empty [] when clean
flags[].levelstringYesinfo, warn, or critical
flags[].textstringYesMachine-readable flag code (e.g., heavy_glare, low_face_match)
submittedAtstringYesISO 8601 timestamp when /submit was called
completedAtstringOnly when completed or failedISO 8601 timestamp when verdict was determined

Status state machine

A verification moves through these states:

queued -> processing -> completed
-> failed
StatusWhat it meansNext
queuedJob is waiting in the ML backend queueWill move to processing within seconds
processingPipeline is actively runningWill move to completed or failed
completedVerdict is readyTerminal state — no more changes
failedPipeline could not complete (rare)Terminal state — see flags for cause

Verdicts explained

VerdictWhat it meansWhat you should do
approvedHigh confidence, all signals passTrust the user, complete onboarding
reviewMixed signals, manual check recommendedSend to your review queue
rejectedLow confidence or critical flagBlock, ask user to retry, or escalate

The threshold between verdicts is configurable per tenant (defaults: <60 rejected, 60-80 review, >=80 approved).

Common flags

FlagLevelMeaning
heavy_glarewarnDocument has reflective glare obscuring text
low_face_matchwarnSelfie and document photo look different
low_livenesswarnAnti-spoofing score below threshold
low_doc_qualitywarnDocument image too blurry or low-resolution
expired_documentcriticalDocument expiry date has passed
mrz_mismatchcriticalMRZ checksum failed (potentially tampered passport)
name_mismatchwarnSubmitted name doesn't fuzzy-match OCR'd name
age_under_minimumcriticalCalculated age below tenant's minimum (default 18)

Polling pattern

For polling, use a bounded retry loop with backoff:

async function waitForVerdict(verificationId, timeoutMs = 30000) {
const start = Date.now();
let interval = 500; // start at 500ms

while (Date.now() - start < timeoutMs) {
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, interval));
interval = Math.min(interval * 1.5, 3000); // exponential backoff, cap 3s
}

throw new Error('Verification timed out');
}

Better than polling: use webhooks. They fire as soon as the verdict is ready — no polling, no missed events.

Errors

HTTPError codeWhen
404verification_not_foundThe ID doesn't exist, or belongs to another tenant
401unauthorized / invalid_keyAuth issue. See Authentication
429rate_limitedHit the /verify/:id rate limit (600 req/min by default)
500internalBackend issue. Include the requestId in your support ticket

Full catalog: Errors.

Notes

  • Tenant ownership is enforced — you can only fetch verifications created with your own API keys
  • The endpoint is safe to poll up to 600 times per minute by default. Need more? Contact support
  • Once a verification is completed or failed, the response is immutable — you can cache it indefinitely
  • submittedAt and completedAt are ISO 8601 in UTC

What's next

  • Errors — full error code reference
  • Webhooks — get verdicts pushed instead of polling
  • Compliance — data retention and regulatory details