> ## 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 (Document Front/Back)

> Verify identity document (front and optional back), extract MRZ and data, get Approved or Declined in a single API call — in the gu1 KYC API for identity.

## Overview

ID Verification is a **Gu1 verification service** that validates an identity document by sending the **front image** (required) and optionally the **back image** (for two-sided documents such as national IDs). The API returns **Approved** or **Declined**, plus extracted data (name, document number, date of birth, address, MRZ, etc.) and optional warnings. No hosted session is involved—you send the images and get the result in one call.

<Note>
  **When to use which**

  * **Session-based KYC** (`POST /api/kyc/validations`): Full flow with hosted URL, live selfie, liveness, and document capture. Best for onboarding and regulated flows.
  * **Face Match** (`POST /api/kyc/face-match`): Compare two images (document portrait + selfie) to verify they are the same person; returns match + score.
  * **ID Verification** (`POST /api/kyc/id-verification`): Send document front (and optional back); get document validation, extracted data (MRZ, name, address, etc.), and Approved/Declined. Best when you already have document images and need extraction + validation only.
</Note>

## Prerequisites

Before using ID Verification:

1. **ID Verification integration enabled**: Your organization must have the ID Verification KYC integration activated (e.g. in Marketplace / Integrations).
2. **Credentials configured**: The API key for the ID Verification integration must be set in your organization's KYC settings (configured by the Gu1 administrator). Only the API key is required (no webhook secret for this endpoint).

<Info>
  ID Verification is a Gu1 service. All verification is performed by Gu1 infrastructure.
</Info>

## Request

### Endpoint

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

### Content-Type

**Only `multipart/form-data`** is accepted. You can send images in either of two ways (or mix):

1. **As file parts**: attach image/files to the form fields `documentFront` and (optional) `documentBack`.
2. **As base64 strings**: send the same field names with base64-encoded image strings (with or without `data:image/...;base64,` prefix).

**documentFront** is required: you must send either a file or a base64 string for it. If neither is provided, the API returns **400**. **documentBack** is optional. For each image, if you send both a file and a base64 string, the file is used.

### Headers

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

Do **not** set `Content-Type` manually when using FormData; the client will set it with the correct boundary.

If your account uses organization scoping, include:

```
X-Organization-Id: YOUR_ORGANIZATION_ID
```

### Form Fields

<ParamField body="documentFront" type="file | string" required>
  Front image of the identity document. Send as a **file part** (recommended) or as a **string** (base64, with or without `data:image/...;base64,` prefix). Formats: JPEG, PNG, WebP, TIFF, PDF. Max 5MB.
</ParamField>

<ParamField body="documentBack" type="file | string">
  Back image of the document (optional; required for two-sided documents such as national IDs). Same as `documentFront`: file part or base64 string.
</ParamField>

<ParamField body="entityId" type="string">
  Optional UUID of the person entity to associate with this check. Used for audit and for listing verifications by entity.
</ParamField>

<ParamField body="vendorData" type="string">
  Optional reference (e.g. your user ID) for tracking. Stored with the audit record.
</ParamField>

<ParamField query="doubleCheckRenaper" type="boolean">
  When `true`, after document verification is **approved**, runs RENAPER **data** check (DNI + gender + trámite from OCR vs `renaper/data`). Requires org RENAPER credentials. Query overrides body.
</ParamField>

<ParamField body="doubleCheckRenaper" type="boolean">
  Same as query param `doubleCheckRenaper`.
</ParamField>

<ParamField body="performDocumentLiveness" type="boolean">
  Whether to perform document liveness (detect screen/copy). Default `false`. Send as string `"true"` or `"false"` in form.
</ParamField>

<ParamField body="minimumAge" type="number">
  Minimum age (1–120); users below are Declined. Optional. Send as string in form.
</ParamField>

<ParamField body="expirationDateNotDetectedAction" type="string">
  `"NO_ACTION"` or `"DECLINE"` when expiration date is not detected. Optional.
</ParamField>

<ParamField body="invalidMrzAction" type="string">
  `"NO_ACTION"` or `"DECLINE"` when MRZ is invalid or unreadable. Optional.
</ParamField>

<ParamField body="inconsistentDataAction" type="string">
  `"NO_ACTION"` or `"DECLINE"` when visual zone data does not match MRZ. Optional.
</ParamField>

## Response

### Success Response (200 OK)

| Field                   | Type                 | Description                                                                                                                                                                                                           |
| ----------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                | string               | `"approved"` \| `"declined"`.                                                                                                                                                                                         |
| `verificationId`        | string (optional)    | ID of the audit record in `id_verification_verifications` (for support and listing).                                                                                                                                  |
| `requestId`             | string (optional)    | Internal request ID (for support).                                                                                                                                                                                    |
| `extractedData`         | object (optional)    | Normalized OCR and verification metadata from the Gu1 ID Verification service, persisted in audit. See [extractedData fields](#extracteddata-fields) below.                                                           |
| `warnings`              | string\[] (optional) | Array of **risk codes** from the verification (e.g. `DOCUMENT_EXPIRED`, `POSSIBLE_DUPLICATED_USER`). Use for display or i18n. See [Warning risk codes](/en/use-cases/kyc/warning-risk-codes) for all possible values. |
| `debugProviderResponse` | object (optional)    | **Non-production only** (Gu1 API `NODE_ENV=development`). Sanitized full verification response for debugging (image/base64 redacted). Do not rely on this in production integrations.                                 |
| `doubleCheckRenaper`    | boolean (optional)   | `true` when RENAPER double-check was requested.                                                                                                                                                                       |
| `responseDoubleChecks`  | object (optional)    | When `doubleCheckRenaper=true`: `renaper` with data/trámite result. See [KYC validations RENAPER](/en/use-cases/kyc/create-validation#renaper-double-check-argentina).                                                |

If RENAPER double-check fails after OCR approval, `status` becomes `"declined"` and RENAPER codes are added to `warnings`.

### extractedData fields

The following fields are returned in `extractedData` and stored on `id_verification_verifications.extracted_data` (list/get audit endpoints). Empty fields are omitted.

**Identity and document (common):**

| Field                                             | Type            | Description                                                                                                                                                                                                                  |
| ------------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `providerStatus`                                  | string          | Document verification status detail (e.g. `Approved`, `Declined`). Top-level `status` is normalized to `approved` / `declined`.                                                                                              |
| `fullName`, `firstName`, `lastName`               | string          | Name from OCR.                                                                                                                                                                                                               |
| `firstSurname`, `secondSurname`                   | string          | When returned in supplementary fields (e.g. some LATAM IDs).                                                                                                                                                                 |
| `documentNumber`, `personalNumber`                | string          | Document number and personal/national ID number when present.                                                                                                                                                                |
| `documentType`                                    | string          | e.g. `Driver's License`, `National ID`.                                                                                                                                                                                      |
| `taxNumber`                                       | string          | Tax ID when present (e.g. CUIT/CUIL for Argentina, CPF for Brazil).                                                                                                                                                          |
| `ejemplar`                                        | string          | Argentine DNI copy letter (`A`–`D`), when returned by OCR. Used for RENAPER cross-check when enabled. With KYC auto-population (or empty-field sync), also written to `entityData.person.ejemplar` when that field is empty. |
| `dateOfBirth`, `age`                              | string / number | Date of birth and computed age.                                                                                                                                                                                              |
| `expirationDate`, `dateOfIssue`, `firstIssueDate` | string          | Document dates (ISO `YYYY-MM-DD` when provided).                                                                                                                                                                             |
| `nationality`, `gender`                           | string          | ISO country code and gender code when present.                                                                                                                                                                               |
| `placeOfBirth`, `maritalStatus`                   | string          | When returned by OCR.                                                                                                                                                                                                        |
| `address`, `formattedAddress`                     | string          | Address lines when present.                                                                                                                                                                                                  |
| `issuingState`, `issuingStateName`                | string          | Issuing jurisdiction (e.g. `BRA`, `Brazil`).                                                                                                                                                                                 |

**Supplementary (nested; may be empty):**

| Field                                             | Type   | Description                                                                                                                                        |
| ------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `extraFields`                                     | object | Document keys **not promoted** to top-level fields (e.g. license category, regional codes). Extension bucket for future OCR keys.                  |
| `warningMeta`                                     | object | Metadata from warnings, e.g. `duplicatedSessionId`, `duplicatedSessionNumber`, `duplicatedApiService` when `POSSIBLE_DUPLICATED_USER` is returned. |
| `frontImageQualityScore`, `backImageQualityScore` | object | OCR quality scores (focus, brightness, overall, etc.) when available.                                                                              |
| `mrz`                                             | object | Parsed MRZ fields when non-empty.                                                                                                                  |
| `parsedAddress`                                   | object | Structured address when returned.                                                                                                                  |
| `barcodes`                                        | array  | Barcode reads when returned.                                                                                                                       |

<Note>
  **Promoted fields vs. extension bucket**

  * Common keys (`taxNumber`, `firstSurname`, `secondSurname`, `firstIssueDate`, `ejemplar`, etc.) are **promoted** to the top level of `extractedData` when OCR returns them.
  * Any other document keys stay in `extractedData.extraFields` (same object on POST and audit list/get).
</Note>

<Note>
  **Not included in API responses or audit JSON**

  * Temporary external image URLs from the verification pipeline — use [stored document images](/en/use-cases/kyc/id-verification-images) (`document-front-image` / `document-back-image`) for images Gu1 saved from your upload.
  * Full raw verification response body (not exposed in production APIs).
</Note>

**Example (approved):**

```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": []
}
```

**Example (declined with warnings and LATAM extra fields):**

```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"]
}
```

**Example (Argentine DNI):**

```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": []
}
```

## Example Request

<CodeGroup>
  ```javascript Node.js (files) 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 YOUR_API_KEY' },
    body: form,
  });
  const result = await response.json();
  console.log('Status:', result.status, 'Data:', result.extractedData);
  ```

  ```javascript Node.js (base64 in form fields) 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 YOUR_API_KEY' },
    body: form,
  });
  const result = await response.json();
  ```

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

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

  ```python Python (base64 in form fields) theme={null}
  import requests
  import base64

  with open('front.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 YOUR_API_KEY'},
      data={
          'documentFront': front_b64,
          'entityId': '123e4567-e89b-12d3-a456-426614174000',
      },
  )
  result = response.json()
  ```

  ```curl cURL (files) theme={null}
  curl -X POST https://api.gu1.ai/api/kyc/id-verification \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "documentFront=@front.jpg" \
    -F "documentBack=@back.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 YOUR_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>

## Error Responses

Common error codes:

| Code                  | HTTP | Meaning                                                                                                          |
| --------------------- | ---- | ---------------------------------------------------------------------------------------------------------------- |
| `NOT_CONFIGURED`      | 403  | ID Verification credentials (API key) not set in organization KYC settings.                                      |
| `NOT_ENABLED`         | 403  | ID Verification integration is not enabled for this organization.                                                |
| `INVALID_REQUEST`     | 400  | Content-Type not multipart/form-data, or missing/invalid document front (no file and no base64, or format/size). |
| `FORBIDDEN`           | 403  | Verification could not be completed (e.g. credits).                                                              |
| `VERIFICATION_FAILED` | 500  | Verification could not be completed; retry or try another document.                                              |

## Audit and Listing Verifications

Every ID Verification request (success or failure) is stored in **`id_verification_verifications`** for audit and compliance. The response includes **`verificationId`** (the audit record ID) when persistence succeeds. All endpoints below are part of the Gu1 API.

### Get a Single Verification

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

Returns one audit record by ID. **Path:** `id` — UUID of the verification (from the POST response `verificationId` or from the list).

**Response (200):** Same shape as one item in the list: `id`, `organizationId`, `entityId`, `status`, `requestId`, `vendorData`, `errorMessage`, `warnings`, `extractedData`, `createdAt`, `documentFrontStoragePath`, `documentBackStoragePath`, `storageProvider`, etc.\
**404** if not found or not in your organization.

### List Audit Records

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

**Query parameters:**

| Parameter       | Type          | Description                                                                                                                   |
| --------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `entityId`      | string (UUID) | Optional. Filter by person entity.                                                                                            |
| `withoutEntity` | boolean       | If `true`, only returns verifications with no associated entity (e.g. for the KYC page "ID Verification without entity" tab). |
| `status`        | string        | Optional. Filter by status (`approved`, `declined`, `failed`).                                                                |
| `limit`         | number        | Max items (default 50, max 100).                                                                                              |
| `offset`        | number        | Pagination offset.                                                                                                            |

**Response:** `{ "verifications": [ ... ], "pagination": { "limit", "offset", "total" } }`. Each verification includes `id`, `entityId`, `status`, `requestId`, `extractedData`, `warnings`, `errorMessage`, `createdAt`, and storage paths when images were stored.

### Get Stored Document Images

If the verification has stored images (`documentFrontStoragePath` / `documentBackStoragePath`), you can stream them with:

```
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 of the verification. **Response:** Image bytes (e.g. `Content-Type: image/jpeg`). **404** if the verification does not exist or that side was not stored.

## Coexistence with Other KYC Flows

* **Session flow** creates a `kyc_validations` record and uses a hosted URL; the stored decision can include document, liveness, and face match from the live session.
* **Face Match** compares document portrait + selfie and returns match + score; audit in `face_match_verifications`.
* **ID Verification** validates the document (front/back), extracts data, and returns Approved/Declined; audit in `id_verification_verifications`. It does **not** create a `kyc_validations` record. Use it when you need document-only validation and extraction without a hosted session.

## Next Steps

<CardGroup cols={2}>
  <Card title="Face Match (Document + Selfie)" icon="play" href="/en/use-cases/kyc/face-match">
    Compare document photo and selfie
  </Card>

  <Card title="Create KYC Validation" icon="play" href="/en/use-cases/kyc/create-validation">
    Session-based verification with hosted URL
  </Card>
</CardGroup>
