Saltar al contenido principal

SDKs

Veridia publica cuatro SDKs. Tres son clientes de servidor/API (JavaScript, Python, PHP). Uno es una UI de captura para móvil (Flutter).

Los cuatro están en 0.1.0. La superficie de la API es estable, pero tomá la versión por lo que dice que es: pre-1.0.

Los cuatro

SDKPaqueteRegistryRequiereQué es
JavaScript / TypeScript@veridia/sdknpmNode 18.17+ (o un navegador)Cliente de API + verificación de webhooks
PythonveridiaPyPIPython 3.11+Cliente de API (sync + async) + verificación de webhooks
PHPveridia/veridia-phpComposerPHP 8.2+Cliente de API + verificación de webhooks
Flutterveridia_sdkgit privadoDart 3.10.3+ / Flutter 3.38.4+UI de captura por cámara, como un solo widget

El nombre del paquete de JavaScript es @veridia/sdk. No @veridia/sdk-js.

No existe un SDK de React Native

Nunca existió. Si encontraste una referencia a @veridia/react-native o una entrada "React Native" en una versión vieja de este sidebar, apuntaba a un paquete que no existe en ningún registry.

Para React Native hoy, tus opciones son la API HTTP directa más tus propias pantallas de captura, o un WebView que hospede el widget web.

¿Cuál necesito?

El paso de captura y el paso de resultado son trabajos distintos, y necesitan claves distintas.

Capturar imágenes — acceso a la cámara, chequeos de calidad, subir bytes. Esto corre donde está el usuario: el widget web en un navegador, o el SDK de Flutter en una app. Los dos usan una clave publicable.

Leer el resultado — esto corre en tu servidor, con una clave secreta. Cualquiera de los tres SDKs de servidor lo hace, y también un simple request HTTP.

Los tres SDKs de servidor también pueden correr init y submit, que es lo que querés si capturás las imágenes con tu propio código y solo necesitás un cliente tipado para la API.

Tipos de clave, y cuál SDK puede leer un veredicto

PrefijoTipoVa eninit + submitLeer veredictos
qv_pub_, qv_pubt_publicablenavegador, app móvilno
qv_sec_, qv_sect_secretasolo tu servidor

Las variantes con t son modo test. El prefijo de test es qv_pubt_ / qv_sect_ — no qv_pub_test_.

GET /v1/verify/{id} rechaza una clave publicable con 401 secret_key_required. Eso es deliberado: una clave publicable vive en el código fuente de la página, donde cualquiera puede leerla, y el resultado de una verificación lleva los campos de identidad extraídos. Una clave publicable que pudiera leer resultados publicaría el resultado KYC de cada uno de tus clientes a cada visitante.

Por eso el SDK de Flutter acepta únicamente una publishableKey y no puede obtener un veredicto. Meter una clave secreta dentro del binario de una app no es un atajo válido — un APK se desempaqueta en minutos, y la clave que sale de ahí lee los veredictos de todos los clientes de tu tenant, no solo el del que tiene el teléfono en la mano.

SDKPuede capturar imágenesPuede init / submitPuede leer un veredicto
JavaScriptnosí, con secretKey
Pythonnosí, con una clave qv_sec_*
PHPnosí, con una clave qv_sec_*
Flutterno, por diseño

El flujo que envuelve cada SDK

init → PUT de cada imagen → submit → webhook (o polling)
  1. POST /v1/verify/init devuelve un slot de subida por imagen (docFront, docBack, selfie), más un expiresAt en segundos unix.
  2. PUT de los bytes a la URL de cada slot. Mandá los headers del slot tal cual — ver abajo.
  3. POST /v1/verify/submit con las keys de la respuesta de init. keys es obligatorio.
  4. El pipeline tarda unos 15 segundos. El resultado llega por webhook, o hacés polling a GET /v1/verify/{id} con una clave secreta.

Cada SDK expone un helper que junta las keys por vos — keysFrom (JS), keys_from (Python), VerifySubmitKeys::fromInit (PHP) — porque olvidarlas es la forma más común de sacarle un 400 a submit.

Las subidas no van a R2

Las URLs de los slots apuntan a un endpoint de Veridia, no a object storage prefirmado. Se autentican con X-Veridia-Upload-Token, una credencial de vida corta por verificación que viaja dentro de los propios headers del slot. Tu API key no autentica ese endpoint en absoluto.

Dos consecuencias que conviene saber antes de escribir código de subida a mano:

  • Reenviá slot.headers tal cual. Reconstruir los headers vos mismo — o mandar solo Content-Type — descarta el token, y todas las subidas fallan. Los cuatro SDKs lo hacen bien.
  • Poné en la allowlist el host de la API, no un host de storage. Si estás escribiendo un CSP o una regla de firewall de egreso, los bytes van a api.xxuxe.online.

El body tiene que ser un JPEG real (el endpoint chequea el magic number FF D8 FF) y de 8 MB como máximo.

Todavía podés ver "presigned R2 upload" en el README de algún SDK o en un comentario de código. Esa redacción está desactualizada; el código de los cuatro SDKs reenvía los headers del slot y es correcto.

status no es verdict

Dos ejes independientes, y confundirlos es el error más caro que ofrece esta API.

CampoPregunta que respondeValores
status¿Corrió el pipeline?queued processing completed failed
verdict¿Pasó la persona?approved review rejected — ausente hasta que esté completed

completed significa que el pipeline llegó a una conclusión. Una verificación aprobada, una que requiere revisión y una rechazada son todas completed. Ramificar sobre status para admitir a un usuario admite a todos los solicitantes rechazados.

Hacé polling sobre status. Decidí sobre verdict.

Dos trampas relacionadas: un veredicto nulo no es un rechazo (significa que no se llegó a ninguna decisión, sea porque sigue corriendo o porque failed), y review es final — significa que una persona tiene que mirarlo, no que el resultado todavía se está asentando. Hacer polling sobre un review esperando que se resuelva espera para siempre.

metadata no sobrevive

POST /v1/verify/submit acepta un objeto metadata, pero se descarta en el edge: no llega al pipeline y no está presente en el payload del webhook. No lo uses para rutear ni reconciliar nada.

userRef, seteado en init, es el campo que ata un evento de vuelta a un usuario de tu sistema. Se devuelve en el webhook. Si además necesitás correlacionar por el camino del polling, guardá vos mismo el mapeo verificationId → usuario: GET /v1/verify/{id} no devuelve userRef.

Webhooks

Los cuatro SDKs traen verificación de firma HMAC-SHA256. Usala — el resultado de una revisión humana puede llegar mucho después de que submit haya retornado, y el webhook es el único canal que lo lleva.

Hechos que aplican sin importar el lenguaje:

  • El header es Veridia-Signature: t=<unix>,v1=<hex>. No existe X-Veridia-Signature ni un header de timestamp aparte — el timestamp vive dentro del valor de la firma.
  • El MAC cubre los bytes "<t>." + rawBody. Verificá contra el body crudo. Reserializar el JSON cambia el digest y el chequeo falla.
  • El payload es planoverdict, verificationId, userRef en el nivel superior. No hay un envoltorio data.
  • El discriminador es type, no event.
  • Exactamente tres tipos de evento: verification.approved, verification.review_required, verification.rejected. No hay un evento created ni un expired que esperar.
  • La entrega es al menos una vez. Deduplicá por id (evt_<hex>), que es estable entre reintentos.
  • La tolerancia de replay por defecto de 300 segundos es la correcta. No la amplíes — el dispatcher vuelve a firmar en cada intento de reintento, así que incluso el último reintento llega con un t fresco.
  • fieldsExtracted lleva PII de identidad: nombre completo, número de documento, fecha de nacimiento. Por eso el endpoint tiene que ser https, y por eso el payload no debería escribirse tal cual en los logs de la aplicación.

Todo el detalle en la sección de webhooks.

Verificar un webhook es tarea de un servidor. El SDK de Flutter expone un WebhookVerifier, pero una app móvil no es un destino de webhooks — no tiene URL estable y no puede guardar el secreto de firma.

Qué sigue