Manejando resultados
Una vez que una verificacion corre, tenes tres formas de recibir el veredicto. Cada una encaja en una arquitectura diferente.
Comparacion rapida
| Metodo | Cuando usar | Latencia | Confiabilidad |
|---|---|---|---|
| Eventos del widget | SPAs, feedback UX inmediato | <100ms | Buena |
| Polling | Flujos server-side, sin URL publica de webhook | 2-5s tipico | Buena |
| Webhooks | B2B en produccion, procesamiento async | 1-3s tipico | Mejor |
Para la mayoria de los sistemas en produccion, los webhooks son la opcion recomendada. El polling esta bien para prototipos.
Metodo 1 — Eventos del widget
El widget emite un evento veridia:complete en el browser apenas la API acepta la verificacion. El camino mas simple para SPAs.
Que recibis
{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"userRef": "customer-12345",
"status": "queued" // o "processing" o "completed"
}
El status es el estado inicial. El veredicto todavia no esta aca — necesitas hacer fetch.
Patron
<veridia-widget id="kyc" publishable-key="qv_pub_..."></veridia-widget>
<script>
document.getElementById('kyc').addEventListener('veridia:complete', async (e) => {
const { verificationId } = e.detail;
// Enviar a tu propio backend, que llama a GET /v1/verify/:id con la 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('Veredicto:', result.verdict); // approved / review / rejected
});
</script>
:::warning Nunca llames a /v1/verify/:id desde el browser
La publishable key del browser (qv_pub_*) esta intencionalmente limitada. Para obtener veredictos, usa una request server-side con tu secret key (qv_sec_*). De otro modo, cualquiera podria consultar cualquier verificacion.
:::
Metodo 2 — Polling GET /v1/verify/:id
Si tu backend recibio el verificationId (del evento o via form submission), haz polling al endpoint de status hasta que sea completed.
curl
curl -X GET https://api.xxuxe.online/v1/verify/vf_AG07CDWRRFQV4T05ZXG2 \
-H "Authorization: Bearer qv_sec_TU_SECRET_KEY"
Respuesta cuando esta listo:
{
"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)); // espera 1s
}
throw new Error('La verificacion no completo a tiempo');
}
const result = await pollVerification('vf_AG07CDWRRFQV4T05ZXG2');
console.log('Veredicto:', 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("La verificacion no completo a tiempo")
result = poll_verification("vf_AG07CDWRRFQV4T05ZXG2")
print("Veredicto:", 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("La verificacion no completo a tiempo");
}
$result = pollVerification("vf_AG07CDWRRFQV4T05ZXG2");
echo "Veredicto: " . $result['verdict'] . "\n";
Metodo 3 — Webhooks (recomendado para produccion)
Los webhooks son push: cuando una verificacion completa, Veridia envia un POST HTTP firmado a tu endpoint. Sin polling, sin eventos perdidos, audit trail completo.
Setup
- En tu dashboard, anda a Webhooks
- Configura la webhook URL a tu endpoint (ej.
https://tuapp.com/webhooks/veridia) - Copia el webhook secret — vas a necesitarlo para verificar firmas
- Listo. Cada verificacion completada dispara un POST.
Que recibis
{
"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"
}
El campo event va a ser uno de:
verification.approvedverification.rejectedverification.review_required
La request HTTP incluye un header de firma que tenes que verificar (mira verificacion de firma para el algoritmo exacto).
Por que preferir webhooks
| Aspecto | Polling | Webhooks |
|---|---|---|
| Latencia | Polling 1s = 1s delay promedio | <100ms post completion |
| API calls | Muchas | Solo la entrega |
| Confiabilidad | Tu codigo tiene que correr | Veridia reintenta 5 veces con backoff exponencial |
| Audit trail | Ninguno | Log completo de delivery en el dashboard |
| Cold starts | Despierta serverless en cada poll | Dispara una vez |
Actuando sobre el veredicto
Cualquiera sea el metodo que uses, la accion es la misma:
function onVerdict(result) {
switch (result.verdict) {
case 'approved':
// Marcar usuario como KYC, habilitar acceso completo
enableUserAccount(result.userRef);
break;
case 'review':
// Enviar a cola de revision manual, pausar acciones sensibles
queueForReview(result.verificationId, result.flags);
break;
case 'rejected':
// Bloquear, pedir al usuario que reintente o contacte soporte
blockUserKyc(result.userRef, result.flags);
break;
default:
// Nunca deberia pasar, loguearlo
console.error('Veredicto desconocido:', result.verdict);
}
}
Que sigue
Quickstart completo. Desde aca, dependiendo de que estas construyendo:
- Documentacion del Widget — cada atributo, evento y opcion de estilo
- Referencia API — REST API completa para integraciones server-side
- Webhooks — verificacion de firma, retry behavior, ejemplos
- Compliance — retencion de datos, SEPRELAD, LGPD, GDPR
Necesitas ayuda? Contactar soporte.