GET /v1/verify/:id
Obtiene el estado actual de una verificacion. Este es el endpoint al que haces polling despues de /submit para conseguir el veredicto.
GET https://api.xxuxe.online/v1/verify/vf_AG07CDWRRFQV4T05ZXG2
Autenticacion
Bearer token. Usa una secret key aca, no una publishable. La publishable key esta intencionalmente limitada a /init y /submit desde origenes whitelisted — obtener veredictos desde el browser permitiria a cualquiera enumerar data de otros tenants.
Authorization: Bearer qv_sec_TU_SECRET_KEY
Path parameter
| Parametro | Tipo | Descripcion |
|---|---|---|
:id | string | El verificationId devuelto por /init (ej. vf_AG07CDWRRFQV4T05ZXG2) |
Request de ejemplo
curl
curl -X GET https://api.xxuxe.online/v1/verify/vf_AG07CDWRRFQV4T05ZXG2 \
-H "Authorization: Bearer qv_sec_TU_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'] ?? '');
Respuesta
200 OK
Mientras procesa:
{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"status": "processing",
"submittedAt": "2026-05-01T18:39:05Z"
}
Cuando esta completo:
{
"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"
}
Cuando el usuario necesita revision manual:
{
"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"
}
Campos de respuesta
| Campo | Tipo | Siempre presente | Descripcion |
|---|---|---|---|
verificationId | string | Si | El verification ID |
status | string | Si | queued, processing, completed, o failed |
verdict | string | Solo cuando completed | approved, review, o rejected |
confidence | number | Solo cuando completed | Score general ponderado de confianza (0-100) |
scores | object | Solo cuando completed | Breakdown de senales individuales |
scores.ocrConfidence | number | Cuando OCR corrio | Confianza VLM auto-reportada en extraccion de texto (0-100) |
scores.faceMatch | number | Siempre | Similitud biometrica entre selfie y foto del documento (0-100) |
scores.liveness | number | Siempre | Score anti-spoofing — confirma que es una persona viva (0-100) |
scores.docQuality | number | Siempre | Score de calidad de imagen del documento (0-100) |
flags | array | Si | Flags de calidad / riesgo. Vacio [] cuando esta limpio |
flags[].level | string | Si | info, warn, o critical |
flags[].text | string | Si | Codigo machine-readable del flag (ej. heavy_glare, low_face_match) |
submittedAt | string | Si | Timestamp ISO 8601 cuando se llamo a /submit |
completedAt | string | Solo cuando completed o failed | Timestamp ISO 8601 cuando se determino el veredicto |
Maquina de estados
Una verificacion se mueve a traves de estos estados:
queued -> processing -> completed
-> failed
| Status | Que significa | Siguiente |
|---|---|---|
queued | El job esta esperando en la cola del backend ML | Va a moverse a processing en segundos |
processing | El pipeline esta corriendo activamente | Va a moverse a completed o failed |
completed | El veredicto esta listo | Estado terminal — no mas cambios |
failed | El pipeline no pudo completar (raro) | Estado terminal — mira flags para causa |
Veredictos explicados
| Veredicto | Que significa | Que deberias hacer |
|---|---|---|
approved | Alta confianza, todas las senales pasan | Confiar en el usuario, completar onboarding |
review | Senales mixtas, revision manual recomendada | Enviar a tu cola de revision |
rejected | Baja confianza o flag critico | Bloquear, pedir al usuario que reintente, o escalar |
El umbral entre veredictos es configurable por tenant (defaults: <60 rejected, 60-80 review, >=80 approved).
Flags comunes
| Flag | Nivel | Significado |
|---|---|---|
heavy_glare | warn | El documento tiene reflejo brilloso oscureciendo el texto |
low_face_match | warn | La selfie y la foto del documento se ven diferentes |
low_liveness | warn | Score anti-spoofing debajo del umbral |
low_doc_quality | warn | Imagen del documento muy borrosa o de baja resolucion |
expired_document | critical | La fecha de expiracion del documento ya paso |
mrz_mismatch | critical | El checksum MRZ fallo (pasaporte potencialmente alterado) |
name_mismatch | warn | El nombre enviado no hace fuzzy-match con el OCR |
age_under_minimum | critical | Edad calculada debajo del minimo del tenant (default 18) |
Patron de polling
Para polling, usa un bucle de retry acotado con backoff:
async function waitForVerdict(verificationId, timeoutMs = 30000) {
const start = Date.now();
let interval = 500; // arranca en 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); // backoff exponencial, cap 3s
}
throw new Error('La verificacion expiro');
}
Mejor que polling: usa webhooks. Disparan apenas el veredicto esta listo — sin polling, sin eventos perdidos.
Errores
| HTTP | Error code | Cuando |
|---|---|---|
404 | verification_not_found | El ID no existe, o pertenece a otro tenant |
401 | unauthorized / invalid_key | Issue de auth. Mira Autenticacion |
429 | rate_limited | Hit el rate limit de /verify/:id (600 req/min por defecto) |
500 | internal | Issue del backend. Incluye el requestId en tu ticket de soporte |
Catalogo completo: Errores.
Notas
- La pertenencia al tenant esta enforced — solo podes obtener verificaciones creadas con tus propias API keys
- El endpoint es seguro para hacer polling hasta 600 veces por minuto por defecto. Necesitas mas? Contacta soporte
- Una vez que una verificacion esta
completedofailed, la respuesta es inmutable — la podes cachear indefinidamente submittedAtycompletedAtson ISO 8601 en UTC
Que sigue
- Errores — referencia completa de codigos de error
- Webhooks — recibi veredictos pusheados en lugar de hacer polling
- Compliance — retencion de datos y detalles regulatorios