> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ID Verification (Frente/Reverso del documento)

> Verificar documento de identidad (frente y opcional reverso), extraer MRZ y datos, obtener Aprobado o Rechazado en una sola llamada

## Resumen

ID Verification es un **servicio de verificación de Gu1** que valida un documento de identidad enviando la **imagen del frente** (obligatoria) y opcionalmente la **imagen del reverso** (para documentos de dos caras como DNI). La API devuelve **Aprobado** o **Rechazado**, datos extraídos (nombre, número de documento, fecha de nacimiento, dirección, MRZ, etc.) y advertencias opcionales. No hay sesión alojada: enviás las imágenes y obtenés el resultado en una llamada.

<Note>
  **Cuándo usar cada uno**

  * **KYC por sesión** (`POST /api/kyc/validations`): Flujo completo con URL alojada, selfie en vivo, liveness y captura de documento. Ideal para onboarding y flujos regulados.
  * **Face Match** (`POST /api/kyc/face-match`): Comparar dos imágenes (retrato del documento + selfie) para verificar que son la misma persona; devuelve coincidencia + puntuación.
  * **ID Verification** (`POST /api/kyc/id-verification`): Enviar frente (y opcional reverso) del documento; obtener validación del documento, datos extraídos (MRZ, nombre, dirección, etc.) y Aprobado/Rechazado. Ideal cuando ya tenés las imágenes del documento y solo necesitás extracción + validación.
</Note>

## Prerrequisitos

Antes de usar ID Verification:

1. **Integración ID Verification activada**: Tu organización debe tener la integración KYC ID Verification activada (por ejemplo en Marketplace / Integraciones).
2. **Credenciales configuradas**: La API key de la integración ID Verification debe estar configurada en la configuración KYC de la organización (lo define el administrador de Gu1). Solo se requiere API key (no webhook secret para este endpoint).

<Info>
  ID Verification es un servicio de Gu1. Toda la verificación se realiza en la infraestructura de Gu1.
</Info>

## Solicitud

### Endpoint

```
POST https://api.gu1.ai/api/kyc/id-verification
```

### Content-Type

**Solo se acepta `multipart/form-data`**. Podés enviar imágenes de dos formas (o combinar):

1. **Como archivos**: adjuntar imágenes en los campos del form `documentFront` y (opcional) `documentBack`.
2. **Como base64**: enviar los mismos nombres de campo con la imagen en base64 (con o sin prefijo `data:image/...;base64,`).

**documentFront** es obligatorio: hay que enviar archivo o base64. Si no llega ninguno, la API devuelve **400**. **documentBack** es opcional. Si enviás archivo y base64 para un mismo campo, se usa el archivo.

### Headers

```
Authorization: Bearer TU_API_KEY
Content-Type: multipart/form-data; boundary=----...
```

No definas `Content-Type` a mano al usar FormData; el cliente lo setea con el boundary correcto.

Si tu cuenta usa organización, incluí:

```
X-Organization-Id: TU_ORGANIZATION_ID
```

### Campos del form

<ParamField body="documentFront" type="file | string" required>
  Imagen del frente del documento. Enviar como **archivo** (recomendado) o como **string** (base64, con o sin prefijo `data:image/...;base64,`). Formatos: JPEG, PNG, WebP, TIFF, PDF. Máx. 5MB.
</ParamField>

<ParamField body="documentBack" type="file | string">
  Imagen del reverso (opcional; obligatoria para documentos de dos caras como DNI). Igual que `documentFront`: archivo o base64.
</ParamField>

<ParamField body="entityId" type="string">
  UUID opcional de la entidad persona a asociar con esta verificación. Se usa para auditoría y para listar verificaciones por entidad.
</ParamField>

<ParamField body="vendorData" type="string">
  Referencia opcional (por ejemplo tu ID de usuario) para trazabilidad. Se guarda en el registro de auditoría.
</ParamField>

<ParamField query="doubleCheckRenaper" type="boolean">
  Con `true`, tras **approved** del documento ejecuta chequeo RENAPER de **datos** (DNI + género + trámite desde OCR vs `renaper/data`). Requiere credenciales RENAPER. El query prevalece sobre el body.
</ParamField>

<ParamField body="doubleCheckRenaper" type="boolean">
  Igual que el query param `doubleCheckRenaper`.
</ParamField>

<ParamField body="performDocumentLiveness" type="boolean">
  Si realizar liveness del documento (detectar pantalla/copia). Por defecto `false`. Enviar como string `"true"` o `"false"` en el form.
</ParamField>

<ParamField body="minimumAge" type="number">
  Edad mínima (1–120); por debajo se rechaza. Opcional. Enviar como string en el form.
</ParamField>

<ParamField body="expirationDateNotDetectedAction" type="string">
  `"NO_ACTION"` o `"DECLINE"` si no se detecta fecha de vencimiento. Opcional.
</ParamField>

<ParamField body="invalidMrzAction" type="string">
  `"NO_ACTION"` o `"DECLINE"` si el MRZ es inválido. Opcional.
</ParamField>

<ParamField body="inconsistentDataAction" type="string">
  `"NO_ACTION"` o `"DECLINE"` si los datos visuales no coinciden con el MRZ. Opcional.
</ParamField>

## Respuesta

### Respuesta exitosa (200 OK)

| Campo                   | Tipo                 | Descripción                                                                                                                                                                                                                                |
| ----------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `status`                | string               | `"approved"` \| `"declined"`.                                                                                                                                                                                                              |
| `verificationId`        | string (opcional)    | ID del registro de auditoría en `id_verification_verifications` (soporte y listado).                                                                                                                                                       |
| `requestId`             | string (opcional)    | ID interno de la solicitud (soporte).                                                                                                                                                                                                      |
| `extractedData`         | object (opcional)    | OCR y metadatos de verificación del servicio ID Verification de Gu1, normalizados y persistidos en auditoría. Ver [campos de extractedData](#campos-de-extracteddata) más abajo.                                                           |
| `warnings`              | string\[] (opcional) | Array de **códigos de riesgo** de la verificación (p. ej. `DOCUMENT_EXPIRED`, `POSSIBLE_DUPLICATED_USER`). Usar para mostrar o i18n. Ver [Códigos de riesgo en advertencias](/es/use-cases/kyc/warning-risk-codes) para todos los valores. |
| `debugProviderResponse` | object (opcional)    | **Solo no producción** (API Gu1 con `NODE_ENV=development`). Respuesta completa de verificación sanitizada para depuración (sin imágenes/base64). No usar en integraciones de producción.                                                  |
| `doubleCheckRenaper`    | boolean (opcional)   | `true` si se solicitó doble chequeo RENAPER.                                                                                                                                                                                               |
| `responseDoubleChecks`  | object (opcional)    | Con `doubleCheckRenaper=true`: `renaper` con resultado datos/trámite. Ver [KYC validations RENAPER](/es/use-cases/kyc/create-validation#doble-chequeo-renaper-argentina).                                                                  |

Si falla RENAPER tras aprobación OCR, `status` pasa a `"declined"` y se añaden códigos RENAPER a `warnings`.

### Campos de extractedData

Los siguientes campos se devuelven en `extractedData` y se guardan en `id_verification_verifications.extracted_data` (listado/detalle de auditoría). Los campos vacíos se omiten.

**Identidad y documento (habituales):**

| Campo                                             | Tipo            | Descripción                                                                                                                                                                                                                                      |
| ------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `providerStatus`                                  | string          | Detalle del estado de verificación del documento (p. ej. `Approved`, `Declined`). El `status` de nivel superior es `approved` / `declined`.                                                                                                      |
| `fullName`, `firstName`, `lastName`               | string          | Nombre según OCR.                                                                                                                                                                                                                                |
| `firstSurname`, `secondSurname`                   | string          | Cuando vienen en campos complementarios (p. ej. algunos documentos LATAM).                                                                                                                                                                       |
| `documentNumber`, `personalNumber`                | string          | Número de documento y número personal/nacional si aplica.                                                                                                                                                                                        |
| `documentType`                                    | string          | p. ej. `Driver's License`, DNI.                                                                                                                                                                                                                  |
| `taxNumber`                                       | string          | Identificador fiscal si aplica (p. ej. CUIT/CUIL en Argentina, CPF en Brasil).                                                                                                                                                                   |
| `ejemplar`                                        | string          | Letra de ejemplar del DNI argentino (`A`–`D`), cuando el OCR la devuelve. Se usa en el cruce RENAPER si está activo. Con auto-poblado KYC (o sync de campos vacíos), también se escribe en `entityData.person.ejemplar` si ese campo está vacío. |
| `dateOfBirth`, `age`                              | string / number | Fecha de nacimiento y edad calculada.                                                                                                                                                                                                            |
| `expirationDate`, `dateOfIssue`, `firstIssueDate` | string          | Fechas del documento (ISO `YYYY-MM-DD` cuando aplica).                                                                                                                                                                                           |
| `nationality`, `gender`                           | string          | País y género cuando el OCR los devuelve.                                                                                                                                                                                                        |
| `placeOfBirth`, `maritalStatus`                   | string          | Lugar de nacimiento y estado civil si aplica.                                                                                                                                                                                                    |
| `address`, `formattedAddress`                     | string          | Dirección cuando está presente.                                                                                                                                                                                                                  |
| `issuingState`, `issuingStateName`                | string          | Jurisdicción emisora (p. ej. `BRA`, `Brazil`).                                                                                                                                                                                                   |

**Complementarios (anidados; pueden ir vacíos):**

| Campo                                             | Tipo   | Descripción                                                                                                                                                                     |
| ------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `extraFields`                                     | object | Claves adicionales del documento **no promovidas** a campos de primer nivel (p. ej. categoría de licencia, códigos regionales). Punto de extensión para campos futuros del OCR. |
| `warningMeta`                                     | object | Metadatos de advertencias: `duplicatedSessionId`, `duplicatedSessionNumber`, `duplicatedApiService` con `POSSIBLE_DUPLICATED_USER`.                                             |
| `frontImageQualityScore`, `backImageQualityScore` | object | Puntuaciones de calidad OCR cuando existen.                                                                                                                                     |
| `mrz`                                             | object | Campos MRZ parseados si no están vacíos.                                                                                                                                        |
| `parsedAddress`                                   | object | Dirección estructurada cuando la verificación la devuelve.                                                                                                                      |
| `barcodes`                                        | array  | Lecturas de códigos de barras si aplica.                                                                                                                                        |

<Note>
  **Campos promovidos vs. extensión**

  * Los identificadores frecuentes (`taxNumber`, `firstSurname`, `secondSurname`, `firstIssueDate`, `ejemplar`, etc.) se **elevan** al mismo nivel que `fullName` dentro de `extractedData` cuando el OCR los devuelve.
  * Cualquier otra clave del documento queda en `extractedData.extraFields` (mismo objeto en POST, listado y detalle de auditoría).
</Note>

<Note>
  **No incluido en respuestas API ni JSON de auditoría**

  * URLs temporales de imágenes del flujo de verificación — usar [imágenes almacenadas](/es/use-cases/kyc/id-verification-images) (`document-front-image` / `document-back-image`) de lo que subiste a Gu1.
  * Cuerpo crudo completo de la verificación (no expuesto en APIs de producción).
</Note>

**Ejemplo (aprobado):**

```json theme={null}
{
  "status": "approved",
  "verificationId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "requestId": "req_abc",
  "extractedData": {
    "providerStatus": "Approved",
    "fullName": "Elena Martínez Sánchez",
    "firstName": "Elena",
    "lastName": "Martínez Sánchez",
    "documentNumber": "YZA123456",
    "documentType": "National ID",
    "dateOfBirth": "1985-03-15",
    "expirationDate": "2030-08-21",
    "nationality": "ESP",
    "address": "Calle Mayor 10, 4B, Madrid",
    "issuingState": "ESP",
    "issuingStateName": "Spain",
    "personalNumber": "AAA123456",
    "dateOfIssue": "2020-01-10",
    "gender": "F",
    "parsedAddress": {
      "street": "Calle Mayor",
      "city": "Madrid",
      "country": "ESP",
      "formatted_address": "Calle Mayor 10, 4B, Madrid"
    },
    "frontImageQualityScore": {
      "overall_score": 97.5,
      "focus_score": 100,
      "is_document_fully_visible": true
    },
    "backImageQualityScore": {
      "overall_score": 96.0,
      "focus_score": 99
    }
  },
  "warnings": []
}
```

**Ejemplo (rechazado con advertencias y campos extra LATAM):**

```json theme={null}
{
  "status": "declined",
  "verificationId": "c3d4e5f6-a7b8-9012-cdef-345678901234",
  "requestId": "4e2bf9fb-d75b-4b26-9362-e51436cfe1eb",
  "extractedData": {
    "providerStatus": "Declined",
    "fullName": "Breno Henrique Ferreira Silva",
    "firstName": "Breno Henrique",
    "lastName": "Ferreira Silva",
    "firstSurname": "Ferreira",
    "secondSurname": "Silva",
    "documentNumber": "08585626509",
    "personalNumber": "2156732124SSPBA",
    "documentType": "Driver's License",
    "taxNumber": "10584158599",
    "dateOfBirth": "2004-08-29",
    "age": 21,
    "expirationDate": "2025-03-07",
    "dateOfIssue": "2024-03-08",
    "firstIssueDate": "2024-03-08",
    "nationality": "BRA",
    "gender": "U",
    "placeOfBirth": "Barreiras/Ba",
    "maritalStatus": "UNKNOWN",
    "issuingState": "BRA",
    "issuingStateName": "Brazil",
    "warningMeta": {
      "duplicatedSessionId": "a4bfeef8-6d6e-4e9b-8fcb-44950912b2b4",
      "duplicatedSessionNumber": 2834,
      "duplicatedApiService": "ID_VERIFICATION"
    },
    "frontImageQualityScore": {
      "overall_score": 98.2,
      "focus_score": 100,
      "brightness_score": 94,
      "is_document_fully_visible": true
    },
    "formattedAddress": null,
    "extraFields": {
      "license_category": "AB",
      "restrictions": "01"
    },
    "mrz": {
      "line1": "IDBRA085856265<<<<<<<<<<<<<<<",
      "line2": "0408299M2503077BRA<<<<<<<<<<<6",
      "line3": "SILVA<<BRENO<HENRIQUE<FERREIRA"
    },
    "parsedAddress": {},
    "backImageQualityScore": {
      "overall_score": 97.1,
      "focus_score": 100
    },
    "barcodes": []
  },
  "warnings": ["DOCUMENT_EXPIRED", "POSSIBLE_DUPLICATED_USER"]
}
```

**Ejemplo (DNI argentino):**

```json theme={null}
{
  "status": "approved",
  "extractedData": {
    "fullName": "Carlos Emmanuel Finos",
    "firstName": "Carlos Emmanuel",
    "lastName": "Finos",
    "documentNumber": "38966181",
    "personalNumber": "00460759387",
    "documentType": "Identity Card",
    "taxNumber": "20389661814",
    "ejemplar": "C",
    "dateOfBirth": "1995-05-22",
    "expirationDate": "2031-10-17",
    "nationality": "ARG",
    "issuingState": "ARG",
    "firstSurname": "Finos"
  },
  "warnings": []
}
```

## Ejemplo de solicitud

<CodeGroup>
  ```javascript Node.js (archivos) theme={null}
  const form = new FormData();
  form.append('documentFront', documentFrontFile); // File object
  if (documentBackFile) form.append('documentBack', documentBackFile);
  form.append('entityId', '123e4567-e89b-12d3-a456-426614174000');

  const response = await fetch('https://api.gu1.ai/api/kyc/id-verification', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer TU_API_KEY' },
    body: form,
  });
  const result = await response.json();
  console.log('Status:', result.status, 'Data:', result.extractedData);
  ```

  ```javascript Node.js (base64 en campos) theme={null}
  const form = new FormData();
  form.append('documentFront', 'data:image/jpeg;base64,/9j/4AAQ...');
  form.append('documentBack', 'data:image/jpeg;base64,/9j/4AAQ...');
  form.append('entityId', '123e4567-e89b-12d3-a456-426614174000');

  const response = await fetch('https://api.gu1.ai/api/kyc/id-verification', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer TU_API_KEY' },
    body: form,
  });
  const result = await response.json();
  ```

  ```python Python (archivos) theme={null}
  import requests

  with open('frente.jpg', 'rb') as front:
      files = {'documentFront': ('frente.jpg', front, 'image/jpeg')}
      data = {'entityId': '123e4567-e89b-12d3-a456-426614174000'}
      # opcional: files['documentBack'] = ('reverso.jpg', open('reverso.jpg', 'rb'), 'image/jpeg')
      response = requests.post(
          'https://api.gu1.ai/api/kyc/id-verification',
          headers={'Authorization': 'Bearer TU_API_KEY'},
          files=files,
          data=data,
      )
  result = response.json()
  print('Status:', result['status'], 'Data:', result.get('extractedData'))
  ```

  ```python Python (base64 en campos) theme={null}
  import requests
  import base64

  with open('frente.jpg', 'rb') as f:
      front_b64 = 'data:image/jpeg;base64,' + base64.b64encode(f.read()).decode()

  response = requests.post(
      'https://api.gu1.ai/api/kyc/id-verification',
      headers={'Authorization': 'Bearer TU_API_KEY'},
      data={
          'documentFront': front_b64,
          'entityId': '123e4567-e89b-12d3-a456-426614174000',
      },
  )
  result = response.json()
  ```

  ```curl cURL (archivos) theme={null}
  curl -X POST https://api.gu1.ai/api/kyc/id-verification \
    -H "Authorization: Bearer TU_API_KEY" \
    -F "documentFront=@frente.jpg" \
    -F "documentBack=@reverso.jpg" \
    -F "entityId=123e4567-e89b-12d3-a456-426614174000"
  ```

  ```curl cURL (base64) theme={null}
  curl -X POST https://api.gu1.ai/api/kyc/id-verification \
    -H "Authorization: Bearer TU_API_KEY" \
    -F "documentFront=data:image/jpeg;base64,/9j/4AAQ..." \
    -F "documentBack=data:image/jpeg;base64,/9j/4AAQ..." \
    -F "entityId=123e4567-e89b-12d3-a456-426614174000"
  ```
</CodeGroup>

## Respuestas de error

Códigos de error habituales:

| Código                | HTTP | Significado                                                                                                                 |
| --------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------- |
| `NOT_CONFIGURED`      | 403  | Credenciales de ID Verification (API key) no configuradas en la organización.                                               |
| `NOT_ENABLED`         | 403  | Integración ID Verification no activada para esta organización.                                                             |
| `INVALID_REQUEST`     | 400  | Content-Type no es multipart/form-data, o falta/inválido el frente del documento (sin archivo ni base64, o formato/tamaño). |
| `FORBIDDEN`           | 403  | No se pudo completar la verificación (p. ej. créditos).                                                                     |
| `VERIFICATION_FAILED` | 500  | No se pudo completar la verificación; reintentar u otro documento.                                                          |

## Auditoría y listado de verificaciones

Cada solicitud de ID Verification (éxito o fallo) se guarda en **`id_verification_verifications`** para auditoría y cumplimiento. La respuesta incluye **`verificationId`** (ID del registro de auditoría) cuando la persistencia tiene éxito. Todos los endpoints siguientes son de la API Gu1.

### Obtener una verificación

```
GET https://api.gu1.ai/api/kyc/id-verification/verifications/:id
```

Devuelve un registro de auditoría por ID. **Path:** `id` — UUID de la verificación (el `verificationId` de la respuesta del POST o del listado).

**Respuesta (200):** Mismo formato que un ítem del listado: `id`, `organizationId`, `entityId`, `status`, `requestId`, `vendorData`, `errorMessage`, `warnings`, `extractedData`, `createdAt`, `documentFrontStoragePath`, `documentBackStoragePath`, `storageProvider`, etc.\
**404** si no existe o no pertenece a tu organización.

### Listar registros de auditoría

```
GET https://api.gu1.ai/api/kyc/id-verification/verifications?entityId={entityId}&limit=50&offset=0
```

**Parámetros de query:**

| Parámetro       | Tipo          | Descripción                                                                                                         |
| --------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- |
| `entityId`      | string (UUID) | Opcional. Filtrar por entidad persona.                                                                              |
| `withoutEntity` | boolean       | Si `true`, solo devuelve verificaciones sin entidad asociada (p. ej. pestaña «ID Verification sin entidad» en KYC). |
| `status`        | string        | Opcional. Filtrar por estado (`approved`, `declined`, `failed`).                                                    |
| `limit`         | number        | Máximo de ítems (por defecto 50, máx. 100).                                                                         |
| `offset`        | number        | Desplazamiento de paginación.                                                                                       |

**Respuesta:** `{ "verifications": [ ... ], "pagination": { "limit", "offset", "total" } }`. Cada verificación incluye `id`, `entityId`, `status`, `requestId`, `extractedData`, `warnings`, `errorMessage`, `createdAt` y rutas de almacenamiento cuando se guardaron imágenes.

### Obtener imágenes del documento almacenadas

Si la verificación tiene imágenes guardadas (`documentFrontStoragePath` / `documentBackStoragePath`), podés obtenerlas con:

```
GET https://api.gu1.ai/api/kyc/id-verification/verifications/:id/document-front-image
GET https://api.gu1.ai/api/kyc/id-verification/verifications/:id/document-back-image
```

**Path:** `id` — UUID de la verificación. **Respuesta:** bytes de la imagen (p. ej. `Content-Type: image/jpeg`). **404** si la verificación no existe o ese lado no se almacenó.

## Convivencia con otros flujos KYC

* **Flujo por sesión** crea un registro en `kyc_validations` y usa una URL alojada; la decisión almacenada puede incluir documento, liveness y face match de la sesión en vivo.
* **Face Match** compara retrato del documento + selfie y devuelve coincidencia + puntuación; auditoría en `face_match_verifications`.
* **ID Verification** valida el documento (frente/reverso), extrae datos y devuelve Aprobado/Rechazado; auditoría en `id_verification_verifications`. **No** crea un registro en `kyc_validations`. Usalo cuando necesitás solo validación y extracción del documento sin sesión alojada.

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Face Match (Documento + Selfie)" icon="play" href="/es/use-cases/kyc/face-match">
    Comparar documento y selfie
  </Card>

  <Card title="Crear validación KYC" icon="play" href="/es/use-cases/kyc/create-validation">
    Verificación por sesión con URL alojada
  </Card>
</CardGroup>
