Skip to main content
POST
/
api
/
kyc
/
validations
Crear Validación KYC
curl --request POST \
  --url http://api.gu1.ai/api/kyc/validations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "entityId": "<string>",
  "integrationCode": "<string>",
  "doubleCheckRenaper": true,
  "omitWarnings": [
    "<string>"
  ]
}
'
{
  "providerSessionUrl": "<string>",
  "status": "<string>"
}

Resumen

Este endpoint crea una nueva sesión de validación KYC para una entidad persona usando un proveedor de integración configurado. Después de crear la validación, recibirás una URL de verificación que puedes compartir con tu cliente para completar la verificación de identidad.

Diagrama de Flujo Completo

Secuencia desde la creación de la entidad hasta la validación KYC (flujo de producción; en sandbox con números de documento de prueba se omite el paso del proveedor y la API devuelve el resultado mock y los webhooks de inmediato—ver Datos mock en sandbox):
1. Entidad y taxId duplicado
  • Crea primero la entidad persona con POST /api/entities (incluye countryCode). Si el taxId ya existe en la organización, la API devuelve 409 y no crea duplicado; usa el ID de la entidad existente.
  • Necesitas un entityId existente para crear una validación KYC.
2. Código de integración
  • global_gueno_validation_kyc es el código estándar para KYC completo y funciona en sandbox sin configuración adicional.
3. URL de verificación
  • En producción, la respuesta incluye providerSessionUrl. Envía esa URL a tu usuario; completan el flujo en la página del proveedor (documento + selfie). La URL es válida hasta expiresAt.
  • En sandbox, si el documento de la entidad está en la lista de prueba, no se usa sesión del proveedor: la API devuelve 201 con estado pending y momentos después actualiza la validación y envía los webhooks (p. ej. kyc.validation_approved o kyc.validation_rejected), sin paso del usuario. Importante: Debes tener configurado un webhook endpoint para recibir las respuestas - ver Datos mock en sandbox.
4. Eventos de webhook
  • Cuando termina la validación, la API envía un webhook a tu URL. El evento es uno de: kyc.validation_approved, kyc.validation_rejected, kyc.validation_abandoned, kyc.validation_expired, kyc.validation_cancelled (no un único evento “completed”). El payload es el objeto de validación completo.
  • También puedes hacer polling a GET /api/kyc/validations/:id para actualizaciones de estado.

Prerrequisitos

Antes de crear una validación KYC:
  1. La entidad persona debe existir: Crea una entidad persona usando la API de Entidades
  2. Integración KYC configurada: Tu organización debe tener un proveedor de integración KYC activado (ej: global_gueno_validation_kyc)
  3. API key válida: Autentica con tu clave API
Sandbox vs Producción: Los entornos sandbox NO requieren configuración de perfil ni preconfiguración. Puedes probar validaciones KYC inmediatamente en sandbox con datos de prueba. Los entornos de producción requieren:
  • Proceso de onboarding de la organización completado
  • Proveedor de integración KYC activado por el equipo de gu1
  • Saldo de crédito suficiente para operaciones KYC
Para comenzar en sandbox, simplemente usa tu clave API de sandbox - no se necesita configuración adicional.

Datos mock (sandbox)

En sandbox, cuando el documento de la entidad persona (taxId) coincide con uno de nuestros valores de prueba, la API devuelve un resultado mock inmediato (p. ej. aprobado, rechazado, cancelado) y envía los webhooks correspondientes, sin ejecutar una verificación real. El formato del documento no importa (p. ej. 99.990.001 y 99990001 funcionan igual). Para ver la lista completa de números de documento de prueba por formato (Argentina DNI/CUIT, Brasil CPF/CNPJ), resultados esperados y ejemplos de respuesta, consulta Datos mock en sandbox.

Comportamientos Importantes

taxId duplicado (POST /entities)

¿Qué sucede si llamas a POST /entities con un taxId que ya existe?La API no crea una segunda entidad. Devuelve 409 Conflict con código de error DUPLICATE_TAX_ID e incluye en los detalles el id, name y type de la entidad existente.Qué hacer:
  1. Opción A – Consultar antes: Usa GET /api/entities?taxId=12345678 (o el endpoint by-tax-id) antes de crear. Si existe la entidad, usa su entityId para KYC.
  2. Opción B – Manejar el 409: Si recibes 409, lee error.details.existingEntityId en la respuesta y usa ese entityId para tu validación KYC.
  3. Reutilizar la misma entidad: Usa una entidad por persona/empresa y crea varias validaciones KYC sobre ese mismo entityId si necesitas re-verificación o nuevos intentos.
Ejemplo – Verificar antes de crear:
// Verificar si la entidad existe
const existing = await fetch('https://api.gu1.ai/api/entities?taxId=12345678', {
  headers: { 'Authorization': 'Bearer TU_API_KEY' }
});
const data = await existing.json();

let entityId;
if (data.data && data.data.length > 0) {
  entityId = data.data[0].id; // Usar entidad existente
} else {
  const createRes = await fetch('https://api.gu1.ai/api/entities', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer TU_API_KEY', 'Content-Type': 'application/json' },
    body: JSON.stringify({ type: 'person', taxId: '12345678', name: 'Juan Pérez', countryCode: 'AR' })
  });
  const created = await createRes.json();
  entityId = created.entity?.id ?? created.data?.id;
}

// Crear validación KYC con el entityId

Múltiples Validaciones KYC por Entidad

Puedes crear múltiples validaciones KYC para la misma entidad:
  • Cada validación obtiene un ID y sesión únicos
  • Solo la validación aprobada más reciente se marca como isCurrent: true
  • Casos de uso: Re-verificación, validaciones expiradas, intentos fallidos

Solicitud

Endpoint

POST https://api.gu1.ai/api/kyc/validations

Headers

{
  "Authorization": "Bearer TU_API_KEY",
  "Content-Type": "application/json"
}

Parámetros de Query (opcionales)

doubleCheckRenaper
boolean
En true, activa el doble chequeo RENAPER para entidades Argentina. En estados terminales la API consulta el registro oficial (datos y, cuando aplica, biometría) y guarda el resultado en metadata. Solo si la verificación OCR KYC devuelve el estado approved un fallo de cruce puede rechazar automáticamente la validación; en in_review o rejected el chequeo es informativo (enforcementApplied: false). Requiere entidad de Argentina y credenciales RENAPER configuradas en la organización.

Parámetros del Body

entityId
string
required
El UUID de la entidad persona a verificarTipo: string (uuid)
integrationCode
string
required
El código del proveedor de integración para validación KYCValor Estándar: global_gueno_validation_kyc (recomendado para la mayoría de casos de uso)Tipo: string (longitud mínima: 1)
¿Qué es integrationCode?El integrationCode identifica qué integración de proveedor KYC usar para la verificación. Piénsalo como seleccionar el servicio de verificación.Códigos de Integración Disponibles:
  • global_gueno_validation_kyc - Recomendado - KYC completo con documento + selfie + coincidencia facial + detección de vida
  • Es posible que se configuren códigos personalizados para tu organización (contacta a soporte)
Cómo encontrar tu código de integración:
  1. Inicia sesión en gu1 Dashboard
  2. Navega a Configuración → Integraciones → Proveedores KYC
  3. Tu código de integración activo estará listado allí
En entornos sandbox, global_gueno_validation_kyc funciona inmediatamente sin configuración.
doubleCheckRenaper
boolean
Igual que el query param. En true activa el doble chequeo RENAPER para Argentina. Puede enviarse en el body o como ?doubleCheckRenaper=true. Si van ambos, prevalece el query.
omitWarnings
string[]
Lista opcional de códigos de advertencia KYC (strings exactos). Se guarda en la validación como metadata.omitWarnings. Cuando termina la sesión, si la validación quedaría en in_review, warnings no está vacío y todos los códigos de warnings están en esta lista, la API pasa el estado a approved y conserva las advertencias para UI y auditoría. Si alguna advertencia no está en omitWarnings, el estado sigue in_review. Si warnings está vacío pero el estado es in_review, no se auto-aprueba. Códigos inválidos o no permitidos en el body devuelven 400. Si aplica la regla, metadata.kycOmitWarningsApplied guarda la marca de tiempo y las advertencias coincidentes.Los códigos no omitibles (p. ej. GUENO_CROSS_ENTITY_DUPLICATED) se rechazan en este campo con 400 y siempre bloquean la auto-aprobación por omit aunque figuren en warnings.Tipo: string[] (cada elemento debe ser un código permitido; se ignoran duplicados)

Respuesta

Respuesta Exitosa (201 Created)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "entityId": "123e4567-e89b-12d3-a456-426614174000",
  "organizationId": "org_abc123",
  "sessionId": "session_xyz789",
  "status": "pending",
  "provider": "kyc_provider",
  "providerSessionUrl": "https://verify.example.com/session_xyz789",
  "isCurrent": true,
  "metadata": {
    "customField": "customValue",
    "doubleChecks": { "renaper": true }
  },
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}
Cuando el doble chequeo RENAPER está activo, en creación se guarda metadata.doubleChecks.renaper: true. Tras aprobación y ejecución del chequeo, se rellena metadata.responseDoubleChecks.renaper (ver Doble chequeo RENAPER).

Campos de Respuesta

providerSessionUrl
string
La URL de verificación para compartir con tu cliente
status
string
Estado actual de la validación. Valores posibles:
  • pending - Validación creada, esperando que el cliente inicie
  • in_progress - Cliente completando la verificación (llenando formulario)
  • in_review - Verificación completada, requiere revisión manual del equipo de compliance
  • approved - Verificación exitosa
  • rejected - Verificación fallida
  • expired - Sesión de verificación expirada (ej. tras 7 días)
  • abandoned - Cliente inició pero no completó
  • cancelled - Validación cancelada manualmente
Tras la aprobación, las claves de medios aparecen dentro de decision. Para descargar archivos (imágenes, video), usá GET /api/kyc/validations/:id/media?key=... con Authorization: Bearer. Detalle completo: Obtener medios de la validación KYC.

Ejemplo de Solicitud

const response = await fetch('https://api.gu1.ai/api/kyc/validations', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer TU_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    entityId: '123e4567-e89b-12d3-a456-426614174000',
    integrationCode: 'global_gueno_validation_kyc'
  })
});

const validation = await response.json();
console.log('URL de verificación:', validation.providerSessionUrl);

Respuestas de Error

Entidad No Encontrada (404)

{
  "error": "ENTITY_NOT_FOUND",
  "message": "Entity not found"
}

Tipo de Entidad Inválido (400)

{
  "error": "INVALID_ENTITY_TYPE",
  "message": "KYC validation is only available for person entities"
}

KYC No Configurado (400)

{
  "error": "KYC_NOT_CONFIGURED",
  "message": "KYC integration is not configured for this organization. Please contact your administrator."
}

Doble chequeo RENAPER (Argentina)

Con doubleCheckRenaper: true y entidad de Argentina, en cada estado terminal (approved, rejected, in_review) la API ejecuta una verificación cruzada contra el registro oficial (RENAPER) cuando hay datos OCR suficientes. El rechazo automático por RENAPER solo aplica si la verificación OCR KYC devolvió el estado approved.

Cómo enviarlo

  • Body: { "entityId": "...", "integrationCode": "...", "doubleCheckRenaper": true }
  • Query: POST /api/kyc/validations?doubleCheckRenaper=true con el mismo body. Si van ambos, prevalece el query.

Dónde se guarda el resultado

En metadata.responseDoubleChecks.renaper. Los códigos de mismatch (p. ej. trámite y vencimiento) se añaden a metadata.warnings sin reemplazar advertencias previas de la verificación OCR KYC. errorCode en el objeto renaper conserva el primer fallo para compatibilidad; la UI puede listar todos los códigos desde comparisonResults y warnings. Campos de metadata.responseDoubleChecks.renaper:
CampoTipoDescripción
verifiedbooleantrue si el chequeo pasó.
matchResultstring"match" | "mismatch" | "error".
verifiedAtstringISO timestamp del chequeo.
personalNumberstringNúmero de trámite desde KYC.
idTramitePrincipalstringNúmero de trámite desde RENAPER.
renaperDataobjectRespuesta cruda de RENAPER (ver forma de renaperData).
comparisonResultsobjectComparación campo a campo entre OCR y registro (cuando aplica).
renaperBiometricobjectResultado biométrico ABIS (validate-dni): matchResult, score, renaperData (respuesta cruda).
errorCodestringPresente si falla; ver códigos abajo.

Forma de renaperData

Es el body sin transformar que devuelve el registro vía ms-providers (POST …/provider-records/renaper/data). Gu1 lo reenvía tal cual en metadata.responseDoubleChecks.renaper.renaperData. Los nombres de campo están en snake_case; todos son opcionales según lo que devuelva RENAPER en cada consulta. Ejemplo (doble chequeo exitoso, matchResult: "match"):
{
  "id_tramite_principal": "987654321",
  "id_tramite_tarjeta_reimpresa": "112233445",
  "ejemplar": "A",
  "vencimiento": "2030-05-20",
  "emision": "2015-05-20",
  "apellido": "García",
  "nombres": "Juan",
  "fecha_nacimiento": "1990-01-15",
  "cuil": "20-30123456-9",
  "calle": "Av. Corrientes",
  "numero": "1234",
  "piso": "5",
  "departamento": "B",
  "codigo_postal": "1043",
  "barrio": "San Nicolás",
  "monoblock": "",
  "ciudad": "Ciudad Autónoma de Buenos Aires",
  "municipio": "Comuna 1",
  "provincia": "Buenos Aires",
  "pais": "Argentina",
  "nacionalidad": "Argentina",
  "codigo_fallecido": "",
  "mensaje_fallecido": "",
  "fecha_fallecimiento": "",
  "id_ciudadano": "30123456",
  "codigo": "",
  "mensaje": ""
}
Otros casos habituales:
SituaciónrenaperData típico
Error antes de obtener datos (ej. RENAPER_DNI_MISSING){}
Servicio no disponible (RENAPER_VERIFICATION_UNAVAILABLE){ "error": "…", "code": "SERVICE_UNAVAILABLE" }
Cruce fallido con datos parciales del registroSubconjunto de campos (ej. id_tramite_principal, apellido, nombres, fecha_nacimiento)
En sandbox, los mismos valores mock aparecen en Datos mock de KYC (sandbox).

Forma de comparisonResults

Mapa por campo (dni, tramite, name, ejemplar, dateOfBirth, expirationDate). Cada entrada puede incluir:
CampoTipoDescripción
comparedbooleantrue si se intentó comparar; false si se omitió por datos faltantes.
passedbooleanResultado cuando compared es true.
skipReasonstringocr_missing, renaper_missing o both_missing cuando no se comparó.
ocrValuestringValor extraído del OCR (si aplica).
renaperValuestringValor del registro RENAPER (si aplica).
similarityPercentnumberSolo en name: similitud Levenshtein (0–100).
thresholdnumberSolo en name: umbral aplicado (p. ej. 80).
errorCodestringCódigo de fallo del campo (p. ej. RENAPER_DNI_NOT_MATCH).
Para ejemplar, el valor OCR es extractedData.ejemplar (ver campos de extractedData). La comparación corre cuando existen ambos valores OCR y RENAPER. Ejemplo — extractedData en una validación KYC aprobada (Argentina):
"extractedData": {
  "documentNumber": "38966181",
  "personalNumber": "00460759387",
  "taxNumber": "20389661814",
  "ejemplar": "C",
  "dateOfBirth": "1995-05-22",
  "expirationDate": "2031-10-17",
  "nationality": "ARG"
}

Forma de renaperBiometric

Objeto anidado en metadata.responseDoubleChecks.renaper.renaperBiometric cuando la org tiene credenciales biométricas y la sesión KYC aporta selfie. Gu1 envía una selfie a validate-dni; RENAPER la compara con la foto del DNI en el registro.
CampoTipoDescripción
verifiedbooleantrue si resultado.match del chequeo biométrico ABIS es positivo.
matchResultstring"match" | "mismatch" | "error".
scorenumberPuntuación devuelta por el chequeo biométrico (si aplica).
verifiedAtstringISO timestamp del chequeo biométrico.
renaperDataobjectRespuesta cruda de validate-dni (incluye resultado.match, resultado.score, etc.).
submittedSelfieRefstringReferencia de la selfie enviada: ruta de almacenamiento (kyc/...) o URL (https://...).
submittedSelfieRefKindstringFormato de submittedSelfieRef: s3_key (ruta interna) | url (URL pública).
submittedSelfiePickedFromstringOrigen en decision: liveness_reference_image o face_match_target_image.
errorCodestringSi falla (p. ej. RENAPER_BIOMETRIC_NOT_MATCH).
skipReasonstringSi no se ejecutó (p. ej. selfie no disponible).

Ejemplo completo de responseDoubleChecks.renaper

{
  "verified": true,
  "matchResult": "match",
  "personalNumber": "00123456789",
  "idTramitePrincipal": "987654321",
  "verifiedAt": "2026-06-05T14:30:00.000Z",
  "enforcementApplied": true,
  "renaperData": {
    "id_tramite_principal": "987654321",
    "apellido": "García",
    "nombres": "Juan",
    "fecha_nacimiento": "1990-01-15",
    "ejemplar": "A",
    "vencimiento": "2030-05-20"
  },
  "comparisonResults": {
    "dni": {
      "field": "dni",
      "compared": true,
      "passed": true,
      "ocrValue": "30123456",
      "renaperValue": "30123456"
    },
    "tramite": {
      "field": "tramite",
      "compared": true,
      "passed": true,
      "ocrValue": "00123456789",
      "renaperValue": "987654321"
    },
    "name": {
      "field": "name",
      "compared": true,
      "passed": true,
      "ocrValue": "Juan García",
      "renaperValue": "García Juan",
      "similarityPercent": 92,
      "threshold": 80
    },
    "ejemplar": {
      "field": "ejemplar",
      "compared": true,
      "passed": true,
      "ocrValue": "A",
      "renaperValue": "A"
    },
    "dateOfBirth": {
      "field": "dateOfBirth",
      "compared": true,
      "passed": true,
      "ocrValue": "1990-01-15",
      "renaperValue": "1990-01-15"
    }
  },
  "renaperBiometric": {
    "verified": true,
    "matchResult": "match",
    "score": 0.91,
    "verifiedAt": "2026-06-05T14:30:02.000Z",
    "submittedSelfieRef": "kyc/org-id/entity-id/session-id/selfie.jpg",
    "submittedSelfieRefKind": "s3_key",
    "submittedSelfiePickedFrom": "liveness_reference_image",
    "renaperData": {
      "resultado": {
        "match": true,
        "score": 0.91
      }
    }
  }
}
renaperBiometric y entradas en comparisonResults pueden omitirse según credenciales, datos OCR o disponibilidad de selfie.

Códigos de error (cuando falla RENAPER)

El motivo del rechazo es un código en metadata.warnings y en metadata.responseDoubleChecks.renaper.errorCode. La UI debe traducir estos códigos.
CódigoSignificado
RENAPER_DNI_MISSINGNo se obtuvo número de documento (DNI) en la verificación.
RENAPER_GENDER_MISSINGFalta género (M/F) para llamar a RENAPER.
RENAPER_VERIFICATION_UNAVAILABLENo se pudo completar la verificación cruzada (ej. error de red). Reintentar.
RENAPER_DNI_NOT_MATCHEl número de documento no coincide con el registro oficial.
RENAPER_TRAMITE_DATA_MISSINGFaltan datos para comparar el número de trámite.
RENAPER_TRAMITE_ID_NOT_MATCHEl número de trámite del documento no coincide con el registro (ejemplar anterior, vencido o reemitido; la persona debe verificar de nuevo con DNI vigente).
RENAPER_NAME_NOT_MATCHEl nombre del OCR no alcanza el 80% de similitud con el registro RENAPER.
RENAPER_EJEMPLAR_NOT_MATCHEl ejemplar del DNI no coincide con el registro RENAPER.
RENAPER_DOB_NOT_MATCHLa fecha de nacimiento del OCR no coincide con RENAPER.
RENAPER_EXPIRY_NOT_MATCHLa fecha de vencimiento del OCR no coincide con RENAPER.
RENAPER_BIOMETRIC_NOT_MATCHLa selfie no coincide con la foto del DNI en el registro biométrico.
RENAPER_BIOMETRIC_UNAVAILABLENo se pudo completar el chequeo biométrico (red, credenciales o servicio).

Cuándo RENAPER aplica enforce (rechazo automático)

Estado de la verificación OCR KYC¿RENAPER se ejecuta?¿Puede rechazar por RENAPER?
approved (aprobación directa) — fallo de cruce → rejected
in_reviewNo — informativo; el equipo decide en revisión manual
rejected (rechazo de la verificación OCR o reglas Gu1)Sí (si hay OCR)No — informativo; deja datos en metadata
Aprobación manual desde in_review (POST …/approve)No (reutiliza el chequeo ya guardado)No — decisión humana; no se re-ejecuta el cruce
En todos los casos con consulta activa, datos y biometría (cuando aplica) quedan en metadata.responseDoubleChecks.renaper (comparisonResults, renaperBiometric). En in_review y rejected los códigos RENAPER con mismatch se agregan a warnings junto con las advertencias de la verificación OCR.

Próximos Pasos

Después de crear una validación:
  1. Extrae la URL de verificación de providerSessionUrl
  2. Comparte la URL con tu cliente vía email, SMS o en tu app
  3. Configura endpoint webhook para recibir notificaciones de finalización
  4. Monitorea el estado de validación usando el ID de validación
  5. Tras la aprobación, leé las claves en decision y descargá archivos — ver Obtener medios de la validación KYC

Obtener URL de KYC

Aprende cómo recuperar la URL

Integración Webhook

Configura notificaciones webhook