---
title: "Brazil - CPF Biometric Database Verification"
slug: "cpf-biometric-database-check"
description: "Validate end-user identity in Brazil with the CPF Biometric Database Check, ensuring accurate data and secure API integration for seamless verification."
updated: 2026-06-03T05:38:52Z
published: 2026-06-03T05:38:52Z
---

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

# Brazil - CPF Biometric Database Verification

| Available via API | Available via SDK | Needs configuration on Veriff’s side | Needs a separate integration | Needs a solution-specific webhook |
| --- | --- | --- | --- | --- |
| ✅ | ❌ | ✅ | ✅ | ❌ |

Brazil (CPF) Biometric Database Check allows validation of end-user identity against government biometric registries in Brazil. It **confirms the accuracy of****data****collected** and **performs a biometric face match** to augment standard identity verification.

Brazil (CPF) Biometric Database Check can be used as a standalone and the whole flow is done over the API.

> [!NOTE]
> Contact your **solutions engineer** for info and configuration.

All **session-related** **info is returned via** decision webhook and can be **polled from different API endpoints**. The results of the verification can also be viewed in the **Veriff Customer Portal →** **Webhook tab**, inside a webhook payload.

---

## Prerequisites

- You have an [integration set up](https://devdocs.veriff.com/v1/docs/how-to-create-an-integration) with Veriff
- The **database check** feature is configured for that integration **by your Solutions Engineer**
- You have configured the [decision webhook](https://devdocs.veriff.com/v1/docs/decision-webhook) to get responses from Veriff (see the how-to in webhooks’ [Set up webhooks](https://devdocs.veriff.com/docs/webhooks-guide#set-up-webhooks) section)
- You are ready to collect and **send** Veriff your **end-user’s data and selfie**
- Because the solution is available only over API:
  - Veriff **strongly recommends** that you **create and send** us the endUserId or vendorData

### Key terminology

| Term | Description |
| --- | --- |
| CPF | *Cadastro de Pessoas Físicas*, the Brazilian individual taxpayer registry identification. |
| CPF number | Brazilian individual taxpayer registry’s 11-digit number |
| Field validation | A single named check that compares one specific data field submitted by you against the corresponding value held by the government registry (e.g. `name_match` or `drivers_license_number_match`). |
| SERPRO | The Federal Data Processing Service in Brazil providing the CPF registry data (via DataValid). |
| Validation | An umbrella term that refers to any individual check performed during the verification process. Includes field-validations (the per-data-point comparisons), and system-level validations (infrastructure and business-logic checks). In this documentation, `validation_check` is used as its placeholder value. |

---

## End-user data sources

The “end-user data sources” refer to the origins from where the end-user’s information can be collected for database verification. Brazil (CPF) Biometric Database Check uses the **initData**.

The minimum data combination to run a successful check is:

- Brazil - CPF Biometric Database VerificationCPF number + document country code + document type

### initData

This is **data that you provide** when creating a verification session, i.e. the parameters you specify in the <meta charset="utf-8">[POST /sessions](https://veriff-dev-documentation.document360.io/apidocs/v1sessions)[↗] request. Includes information like names, date of birth, address, phone number, ID number, gender etc.

Parameters that can be sent via initData:

- `verification`: `object` Root object containing all session parameters
  - `person`: `object` Object containing person information
    - `idNumber`: `string` 11-digit CPF number (e.g.,`12345678901`). [REQUIRED]
    - `firstName`: `string` End-user's first name. Matched against SERPRO records. [OPTIONAL]
    - `lastName`: `string` End-user's last name. Matched against SERPRO records. [OPTIONAL]
    - `dateOfBirth`: `string` Date of birth in `YYYY-MM-DD` format. [OPTIONAL]
    - `gender`: `string` End-user’s gender, `M` or `F`. [OPTIONAL]
  - `document`: `object` Object containing document information
    - `country`: `string` Must be `BR`. [REQUIRED]
    - `type`: `string` Document type, always `DRIVERS_LICENSE`). [REQUIRED]
    - `number`: `string` Brazilian driver's license registration number. [OPTIONAL]
    - `category`: `string` License category, of `AB`, `B`, `C`, `D`, `E`). [OPTIONAL]
    - `firstIssue`: `string` Date of first license issue in `YYYY-MM-DD` format. [OPTIONAL]
    - `validFrom`: `string` License validity start date in `YYYY-MM-DD` format. [OPTIONAL]
    - `validUntil`: `string` License validity end date in `YYYY-MM-DD` format. [OPTIONAL]

---

## Flow overview

This solution is available only via API. You are responsible for the selfie capture interface and image quality.

### Use via API

1. Generate a verification session using the API keys and the `baseURL` of your integration (see the [API Documentation and API Reference](/v1-api/docs/veriff-public-api-guides#api-url) how to find these)
  - Make sure to pass the mandatory `verification.person.idNumber` parameter with the end-user’s CPF value
  - Make sure to pass the mandatory `verification.document.country` parameter with the `BR` value
  - Make sure to pass the mandatory `verification.document.type` parameter with the `DRIVERS_LICENSE` value
  - Veriff strongly recommends you create and send the `endUserId` or `vendorData`

**Session creation example (minimal payload)**

**Bash**

```bash
curl -X POST \
  --url '/v1/sessions/' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
  "verification": {
    "callback": "https://exampleURL.com",
    "person": {
      "idNumber": "12345678901"
    },
    "document": {
      "country": "BR",
      "type": "DRIVERS_LICENSE"
    },
    "vendorData": "12345678"
  }
}'
```

**JSON**

```json
{
  "verification": {
    "callback": "https://exampleURL.com",
    "person": {
      "idNumber": "12345678901"
    },
    "document": {
      "country": "BR",
      "type": "DRIVERS_LICENSE"
    },
    "vendorData": "12345678"
  }
}
```

**Session creation example (extended payload)**

**Bash**

```bash
curl -X POST \
  --url '/v1/sessions/' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "verification": {
      "callback": "https://exampleURL.com",
      "vendorData": "12345678",
      "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
      "document": {
        "country": "BR",
        "type": "DRIVERS_LICENSE",
        "number": "04821937650",
        "category": "AB",
        "firstIssue": "2015-03-22",
        "validFrom": "2020-07-14",
        "validUntil": "2030-07-14"
      },
      "person": {
        "idNumber": "12345678901",
        "firstName": "Lucas",
        "lastName": "Ferreira",
        "dateOfBirth": "1988-11-05",
        "gender": "M"
      }
    }
  }'
```

**JSON**

```json
{
  "verification": {
    "callback": "https://exampleURL.com",
    "vendorData": "12345678",
    "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
    "document": {
      "country": "BR",
      "type": "DRIVERS_LICENSE",
      "number": "04821937650",
      "category": "AB",
      "firstIssue": "2015-03-22",
      "validFrom": "2020-07-14",
      "validUntil": "2030-07-14"
    },
    "person": {
      "idNumber": "12345678901",
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M"
    }
  }
}
```

2. Upload the end-user's selfie via [POST /sessions/{{sessionId}}/media](/v1-api/apidocs/v1sessionsidmedia-3) call. This is matched agains the portrait stored in the government registry.

- Use your image-capturing method, or send previously collected end-user selfie image(s) (see the [POST /sessions/{{sessionId}}/media](/v1-api/apidocs/v1sessionsidmedia-3) documentation for more info about how to upload the image files).
- This solution supports .`jpeg` and `.png` formats.
- Specify the `image.context` as `face` for the image (see [Context types (image, video)](/v1/docs/context-types-image-video-1) for more info about image context types).
- This endpoint requires endpoint level authentication via `x-hmac-signature` header. See [HMAC Authentication and Endpoint Security](/v1/docs/hmac-authentication-and-endpoint-security#public-api-v1) article for general info about signature creation.

**Media upload example**

**Bash**

```bash
curl -X POST \
  --url '/v1/sessions/aea9ba6d-1b47-47fc-a4fc-f72b6d3584a7/media' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'x-hmac-signature: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
  -H 'Content-Type: application/json' \
  -d '{
  "image": {
    "context": "face",
    "content": "data:image/jpeg;base64,...",
    "timestamp": "2026-04-01T10:00:00.000Z"
  }
}'
```

**JSON**

```json
{
  "image": {
    "context": "face",
    "content": "data:image/jpeg;base64,...",
    "timestamp": "2026-04-01T10:00:00.000Z"
  }
}
```

3. Patch session status to `submitted` status using [PATCH /sessions](/v1-api/apidocs/v1sessionsid-2) call.

- This endpoint requires endpoint level authentication via `x-hmac-signature` header. See [HMAC Authentication and Endpoint Security](/v1/docs/hmac-authentication-and-endpoint-security#public-api-v1) article for general info about signature creation.

**Session update example**

**Bash**

```bash
curl -X PATCH \
  --url '/v1/sessions/fd5c1563-1d23-4b1a-ae46-7ba429927ed8' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'x-hmac-signature: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
  -H 'Content-Type: application/json' \
  -d '{
  "verification": {
    "status": "submitted"
  }
}'
```

**JSON**

```json
{
  "verification": {
    "status": "submitted"
  }
}
```

1. Check the decision data and/or session related info from the decision webhook and/or query the data from the [GET /sessions/{{sessionId}}/decision](/v1-api/docs/v1sessionsiddecision-1) endpoint. Solution-specific overview of what to expect is provided below in the **Find decision and/or session related info** > [Solution-specific parameters](/v1/docs/cpf-biometric-database-check#solutionspecific-parameters) section.

---

## Find decision and/or session related info

You can get the data from three sources:

- Receive the decision webhook (full example with placeholder values [below](/v1/docs/cpf-biometric-database-check#webhook-payload))
- Query the results via GET sessions/sessionId/decision endpoint (payload identical to webhook)
- View the session in **Veriff Customer Portal** > **Webhooks** tab

Note that the **decision webhook** and GET /sessions/{sessionId}/decision **API response payloads are identical**.

### Solution-specific parameters

Info related to the solution is returned in `registryValidations.BR_CPF` object. This parameter contains the match results and person data (where applicable) from government registries to confirm the end-user's identity.

#### Structure of `BR_CPF` object

```json
{
  "BR_CPF": {
    "status": "success | failure | error",
    "data": { ... } | null,
    "validations": { ... } | null,
    "error": { ... } | null,
    "timestamp": "ISO-8601 string" | null
  }
}
```

#### Parameters in `BR_CPF` explained

- `verification`: `object` Verification results object
- `registryValidations`: `object` Registry validation results object
  - `BR_CPF`: `object` Registry validation result for Brazil CPF
    - `status`: `string` Overall result of the registry check. One of: `success` , `failure` or `error` . See [below](/v1/docs/cpf-biometric-database-check#possible-status-values) for more info.
    - `data`: `null` Always `null` The CPF registry does not return person data, it only confirms or denies matches
    - `validations`: `object | null` Map of specific validation checks. `null` when `status` is `error`.
      - `&lt;validation_check&gt;`: `object` A specific validation check run results. See [below](/v1/docs/cpf-biometric-database-check#available-validationcheck-values) for more info.
        - `result`: `string` Outcome of the validation. One of: `success` (passed), `failure` (failed), `not_applicable` (could not run)
        - `reason`: `string | null` Machine-readable reason for the result
    - `error`: `object | null` Error details when `status` is `error`
      - `code`: `string` Machine-readable error code, always `registry_error`
      - `message`: `string` Human-readable error description, enum `registry_unavailable` , `technical_issues`
    - `timestamp`: `string | null` ISO-8601 timestamp of when the registry responded, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset`. `null` when registry was not reached

#### Possible `status` values

| Status | Description |
| --- | --- |
| `success` | All checks passed or are not applicable |
| `failure` | One or more validations failed |
| `error` | Registry could not be reached or returned an unexpected response |

#### Available `validation_check` values

| Validation check | Description |
| --- | --- |
| `person_registered` | Whether the person was found in the CPF registry |
| `selfie_registry_match` | Whether the uploaded selfie matches the registry portrait |
| `name_match` | Whether the provided name matches the registry name |
| `date_of_birth_match` | Whether the provided DOB matches the registry DOB |
| `gender_match` | Whether the provided gender matches the registry gender |
| `drivers_license_number_match` | Whether the DL number matches |
| `drivers_license_category_match` | Whether the DL category matches |
| `drivers_license_is_valid` | Whether the DL is currently valid in the registry |
| `drivers_license_first_issue_match` | Whether the DL first issue date matches |
| `drivers_license_valid_from_match` | Whether the DL valid-from date matches |
| `drivers_license_valid_until_match` | Whether the DL valid-until date matches |

#### Note about object and field visibility

Some objects and fields within the `registryValidations.BR_CPF` object are **optional**.

You should expect that any key may be omitted from the payload or return a `null` value.

A field is included in the response only when:

- The registry check was successfully performed
- The specific validation (e.g., `name_match`) is enabled for configuration
- The input data required for that specific check was provided

Because the response schema is dynamic and based on both your specific configuration and the quality of the image(s) provided, your application logic must account for omitted keys and `null` values as a standard part of the verification workflow.

#### Note on session outcomes

An `approved` session is identified by a `verification.status` of `approved`. Depending on your configuration, a "clean" result may also include:

- A `status` of `success` within the `BR_CPF` object, indicating all enabled validations passed or were not applicable.

If optional field checks are not enabled, they are omitted from the payload and do not impact the `approved` status.

#### Validation cascade

> [!NOTE]
> The biometric registry uses a validation cascade: if a **core validation fails, downstream validations**are **automatically omitted**, meaning they are **set to**`not_applicable`****and its `reason` value **reflects the upstream failure that caused it to be omitted**, not a result of the validation itself.
> 
> Do not use the reason of a `not_applicable` validation to diagnose that check.

**Cascade order**

```markdown
Registry check executes
│
├── Registry error (unavailable, timeout, or invalid response)
│     → All validations: N/A
│
└── Registry responds successfully
      │
      └── Person found in registry?
            ├─ NO → person_registered = FAIL
            │       reasonCode: 902
            │       selfie_registry_match = N/A
            │       All 9 configurable validations = N/A
            │
            └─ YES → person_registered = PASS
                     │
                     └── Face match score ≥ threshold?
                           ├─ NO → selfie_registry_match = FAIL
                           │       reasonCode: 581
                           │       All 9 configurable validations = N/A
                           │
                           └─ YES → selfie_registry_match = PASS
                                    │
                                    └── Each enabled field validation runs independently
                                          ├─ name_match
                                          ├─ date_of_birth_match
                                          ├─ gender_match
                                          ├─ drivers_license_is_valid
                                          ├─ drivers_license_number_match
                                          ├─ drivers_license_category_match
                                          ├─ drivers_license_first_issue_match
                                          ├─ drivers_license_valid_from_match
                                          └─ drivers_license_valid_until_match
                                                FAIL → reasonCode: 903
```

**Cascade rules**

1. If the registry is unavailable, all validations result in `not_applicable`. No further evaluation occurs.
2. If `person_registered` fails, all remaining validations are omitted and result in `not_applicable`.
3. If `selfie_registry_match` fails, all field validations are omitted and result in `not_applicable`.
4. For omitted validations, the `reason` value shows what caused the skip, not a result of the validation itself.
5. Each validation can also fail for operational reasons beyond its core check. For example, if the registry was unavailable or a required input was missing. In these cases, the validation's `reason` reflects the operational condition, not the match outcome.
6. If `selfie_registry_match` passes, each enabled field validation is evaluated independently. A failure in one does not block the others.
7. Field validations are optional. Only those enabled in the workflow configuration are evaluated.

*****Click to open an example of a***`declined`***session where***`person_not_found`***caused a cascading failure of other checks*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "status": "declined",
    "code": 9102,
    "reason": "Value mismatch",
    "reasonCode": 903,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "failure",
        "data": null,
        "validations": {
          "person_registered": {
            "result": "failure",
            "reason": "person_not_found"
          },
          "selfie_registry_match": {
            "result": "failure",
            "reason": "person_not_found"
          },
          "name_match": {
            "result": "not_applicable",
            "reason": "person_not_found"
          },
          "date_of_birth_match": {
            "result": "not_applicable",
            "reason": "person_not_found"
          },
          "gender_match": {
            "result": "not_applicable",
            "reason": "person_not_found"
          }
        },
        "error": null,
        "timestamp": "2026-04-01T10:01:05.000Z"
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

#### Sample payload of `registryValidations.BR_CPF` object

> [!NOTE]
> The following is a sample response for a approved session with all possible `registryValidations.BR_CPF` object values. All strings and IDs are **placeholder values used for illustrative purposes only**. Your production payload will contain real-time data extracted from the end-user's document.

```json
{
  "verification": {
    "registryValidations": {
        "BR_CPF": {
          "status": "success",
          "data": null,
          "validations": {
            "person_registered": {
              "result": "success",
              "reason": null
            },
            "selfie_registry_match": {
              "result": "success",
              "reason": null
            },
            "name_match": {
              "result": "success",
              "reason": null
            },
            "date_of_birth_match": {
              "result": "success",
              "reason": null
            },
            "gender_match": {
              "result": "success",
              "reason": null
            },
            "drivers_license_number_match": {
              "result": "success",
              "reason": null
            },
            "drivers_license_category_match": {
              "result": "success",
              "reason": null
            },
            "drivers_license_is_valid": {
              "result": "success",
              "reason": null
            },
            "drivers_license_first_issue_match": {
              "result": "success",
              "reason": null
            },
            "drivers_license_valid_from_match": {
              "result": "success",
              "reason": null
            },
            "drivers_license_valid_until_match": {
              "result": "success",
              "reason": null
            }
          },
          "error": null,
          "timestamp": "2026-04-01T10:01:05.000Z"
        }
    }
  }
}
```

### Webhook payload

> [!NOTE]
> The example below uses **placeholder data** to show all **mandatory parameters and possible Brazil (CPF) Biometric Database Check fields**. While mandatory fields are always present, solution-specific keys are omitted if a feature is disabled.
> 
> **Depending on your integration’s configuration**, your **production payload may contain additional parameters**; for info on fields from other solutions, see the [**decision webhook’s** documentation](/v1/docs/decision-webhook).

#### Sample requests

*****Click to open an example of a***`approved`***session (all validations passed)*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "status": "approved",
    "code": 9001,
    "reason": null,
    "reasonCode": null,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "success",
        "data": null,
        "validations": {
          "person_registered": {
            "result": "success",
            "reason": null
          },
          "selfie_registry_match": {
            "result": "success",
            "reason": null
          },
          "name_match": {
            "result": "success",
            "reason": null
          },
          "date_of_birth_match": {
            "result": "success",
            "reason": null
          },
          "gender_match": {
            "result": "success",
            "reason": null
          },
          "drivers_license_number_match": {
            "result": "success",
            "reason": null
          },
          "drivers_license_category_match": {
            "result": "success",
            "reason": null
          },
          "drivers_license_is_valid": {
            "result": "success",
            "reason": null
          },
          "drivers_license_first_issue_match": {
            "result": "success",
            "reason": null
          },
          "drivers_license_valid_from_match": {
            "result": "success",
            "reason": null
          },
          "drivers_license_valid_until_match": {
            "result": "success",
            "reason": null
          }
        },
        "error": null,
        "timestamp": "2026-04-01T10:01:05.000Z"
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

*****Click to open an example of a***`approved`***session where optional fields data was not provided (approved with***`not_applicable`***)*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "status": "approved",
    "code": 9001,
    "reason": null,
    "reasonCode": null,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "success",
        "data": null,
        "validations": {
          "person_registered": {
            "result": "success",
            "reason": null
          },
          "selfie_registry_match": {
            "result": "success",
            "reason": null
          },
          "name_match": {
            "result": "not_applicable",
            "reason": "input_not_provided"
          },
          "date_of_birth_match": {
            "result": "success",
            "reason": null
          },
          "gender_match": {
            "result": "success",
            "reason": null
          }
        },
        "error": null,
        "timestamp": "2026-04-01T10:01:05.000Z"
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

*****Click to open an example of a***`declined`***session where selfie mismatch caused a cascading failure of other checks*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "status": "declined",
    "code": 9102,
    "reason": "Selfie mismatch with registry",
    "reasonCode": 902,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "failure",
        "data": null,
        "validations": {
          "person_registered": {
            "result": "success",
            "reason": null
          },
          "selfie_registry_match": {
            "result": "failure",
            "reason": "selfie_mismatch"
          },
          "name_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "date_of_birth_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "gender_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_number_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_category_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_is_valid": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_first_issue_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_valid_from_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          },
          "drivers_license_valid_until_match": {
            "result": "not_applicable",
            "reason": "selfie_mismatch"
          }
        },
        "error": null,
        "timestamp": "2026-04-01T10:01:05.000Z"
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

*****Click to open an example of a***`declined`***session where name mismatch caused a cascading failure of other checks*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
    "status": "declined",
    "code": 9102,
    "reason": "Value mismatch",
    "reasonCode": 903,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Fredo",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "failure",
        "data": null,
        "validations": {
          "person_registered": {
            "result": "success",
            "reason": null
          },
          "selfie_registry_match": {
            "result": "success",
            "reason": null
          },
          "name_match": {
            "result": "failure",
            "reason": "value_mismatch"
          },
          "date_of_birth_match": {
            "result": "success",
            "reason": null
          },
          "gender_match": {
            "result": "success",
            "reason": null
          }
        },
        "error": null,
        "timestamp": "2026-04-01T10:01:05.000Z"
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

*****Click to open an example of a***`declined`***session where registry was unavailable*****

```json
{
  "status": "success",
  "verification": {
    "id": "12df6045-3846-3e45-946a-14fa6136d78b",
    "attemptId": "00bca969-b53a-4fad-b065-874d41a7b2b8",
    "vendorData": "12345678",
    "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
    "status": "declined",
    "code": 9102,
    "reason": "Registry unavailable",
    "reasonCode": 903,
    "decisionTime": "2026-04-01T10:01:05.916Z",
    "acceptanceTime": "2026-04-01T10:00:27.000Z",
    "submissionTime": "2026-04-01T10:01:00.736Z",
    "person": {
      "firstName": "Lucas",
      "lastName": "Ferreira",
      "dateOfBirth": "1988-11-05",
      "gender": "M",
      "nationality": null,
      "idNumber": "12345678901",
      "yearOfBirth": null,
      "placeOfBirth": null
    },
    "document": {
      "number": null,
      "type": "DRIVERS_LICENSE",
      "country": "BR",
      "state": null
    },
    "registryValidations": {
      "BR_CPF": {
        "status": "error",
        "data": null,
        "validations": null,
        "error": {
          "code": "registry_error",
          "message": "registry_unavailable"
        },
        "timestamp": null
      }
    },
    "additionalVerifiedData": {}
  },
  "technicalData": {
    "ip": "127.0.0.1"
  }
}
```

#### Request properties explained

- `status`: `string` Status of the response
- `verification`: `object` Verification request decision object. `null` if decision is not available yet
  - `id`: `string` UUID v4 which identifies the verification session
  - `attemptId`: `string` UUID v4 of the attempt which received a status (as shown in `verification.status` field)
  - `vendorData`: `string | null` The unique identifier that you created for your end-user. `null` if not specified
  - `endUserId`: `string | null` The UUID that you created for your end-user. `null` if not specified
  - `status`: `string` Verification status, one of `approved`, `declined`, `resubmission_requested`, `expired`, `abandoned`
  - `code`: `integer` Verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`. For more info, see the verification session decision codes
  - `reason`: `string | null` Reason why the verification failed. For more info, see the Session decision statuses and status reasons section below
  - `reasonCode`: `integer | null` Reason code of the failed verification
  - `decisionTime`: `string | null` Timestamp of the decision, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - `acceptanceTime`: `string` Timestamp of the session generation, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - `submissionTime`: `string` Timestamp of when the session was submitted, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSSSSS+Timezone Offset` (ISO 8601)
  - `person`: `object` Data about the verified person
    - `firstName`: `string | null` Person's first name
    - `lastName`: `string | null` Person's last name
    - `dateOfBirth`: `string` Person's date of birth, represented as `YYYY-MM-DD`
    - `gender`: `string | null` Person's gender, represented as `M` or `F`, or `null` if not present
    - `nationality`: `string | null` Person's nationality, represented as ISO 3166 `alpha-2` or `alpha-3` code
    - `idNumber`: `string | null` Person's CPF number
    - `yearOfBirth`: `string | null` Person's year of birth, represented as `YYYY`
    - `placeOfBirth`: `string | null` Person's place of birth
  - `document`: `object` Verified document
    - `number`: `string | null` Document number, `[a-zA-Z0-9]` characters only
    - `type`: `string | null` Document type, always`DRIVERS_LICENSE`
    - `country`: `string | null` Document issuing country, represented as ISO 3166 `alpha-2` code
    - `state`: `string | null` Document issuing state, represented as ISO 3166 `alpha-2` or `alpha-3` code
  - `registryValidations`: `object` Registry validation results for this session
    - `BR_CPF`: `object` Results of the Brazilian CPF registry check
      - `status`: `string` Overall result of the registry check: `success`, `failure`, or `error`
      - `data`: `object | null` Always `null` for BR, because the CPF registry does not return person data, it only confirms/denies matches
      - `validations`: `object | null` Map of validation results. `null` when `status` is `error`
        - `person_registered`: `object` Whether the person was found in the CPF registry
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `selfie_registry_match`: `object` Whether the uploaded selfie matches the registry portrait
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `name_match`: `object` Whether the provided name matches the registry name
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `date_of_birth_match`: `object` Whether the provided date of birth matches the registry date of birth
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `gender_match`: `object` Whether the provided gender matches the registry gender
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_number_match`: `object` Whether the driver's license number matches the registry record
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_category_match`: `object` Whether the driver's license category matches the registry record
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_is_valid`: `object` Whether the driver's license is currently valid in the registry
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_first_issue_match`: `object` Whether the driver's license first issue date matches the registry record
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_valid_from_match`: `object` Whether the driver's license valid-from date matches the registry record
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
        - `drivers_license_valid_until_match`: `object` Whether the driver's license valid-until date matches the registry record
          - `result`: `string` Validation result
          - `reason`: `string | null` Reason for the result
      - `error`: `object | null` Error details when `status` is `error`. `null` otherwise
        - `code`: `string` Machine-readable error code, always `registry_error`
        - `message`: `string` Human-readable error description, enum `registry_unavailable` , `technical_issues`
      - `timestamp`: `string | null` ISO 8601 timestamp of when the registry responded. `null` if the registry was not reached
  - `additionalVerifiedData`: `object` Data that has been optionally verified for the session. Optional, depending on the integration. Returns empty `{}` if no additional data was verified.
  - `comments`*:*`array`*(Deprecated) Always returns empty*`[]`
- `technicalData`: `object` Technical data object
  - `ip`: `string | null` IP address of the device from which the verification was made

### API call

#### Sample response

*The API response payload is identical to decision webhook payload. See the*[*sample payload above*](/v1/docs/cpf-biometric-database-check#sample-request)*.*

#### Response properties explained

*The API response payload is identical to decision webhook payload. See the*[*request properties explained above*](/v1/docs/cpf-biometric-database-check#request-properties-explained)*.*

### Veriff Customer Portal

You can find the verification session related info, including the decision, in the **Veriff Customer Portal** → **Webhooks** tab**.**

<meta charset="utf-8">

→ *See*[*Review verification in Veriff Customer Portal*](/v1/docs/how-to-review-verification-in-veriff-customer-portal)*about how to view the session info in the Veriff Customer portal*

---

## Status and reason codes

Veriff runs a series of automated checks on the submitted identity documents and biometric data. At the end, a decision is produced and delivered via webhook.

As the **primary decision signal**see:

- `verification.code` for verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`
- `verification.status` for verification decision status, one of `approved`, `declined`, `resubmission_requested`, `expired`, `abandoned`

If the Brazil (CPF) Biometric Database Check session was `declined` , you can find additional information by checking two closely related fields:

- `verification.reasonCode`: a numeric code identifying the rejection category (e.g., document fraud, image quality, biometric mismatch)
- `verification.reason`: a human-readable text string describing what specifically went wrong.

#### How to interpret `reasonCode` and `reason` fields?

> [!NOTE]
> Use the `verification.reasonCode` to determine what kind of problem occurred and to create programmatical actions based on rejection outcomes.
> 
> Use the `verification.reason` for logging, display, and human interpretation only.

The `verification.reasonCode` is produced by registry match validations aka **validations that run against the actual registry response** (e.g., "did the selfie match?"). These come from a flat list of integer constants, meaning they are deliberate, stable, machine-readable signals that can be used for integration logic.

The `verification.reason` is a **human-readable text string that describes why a verification was not approved**.

- The value is derived from the specific reason behind the registry validation that failed: for example, a name match check or a selfie match check. Each of these validations can fail for multiple different reasons (e.g., a name match can fail because the value did not match, or because the registry was unavailable). The `reason` field surfaces whichever specific reason applied in that session, translated into English.
- Because of this, there is no 1:1 relationship between `reasonCode` and `reason` . `reason` values like `Registry unavailable` or `Technical issues` can appear under any `reasonCode` because they indicate that the relevant validation could not complete, not that the match itself failed. For more detail on how validation failure reasons propagate through the cascade, see [Validation cascade](/v1/docs/cpf-biometric-database-check#validation-cascade) → Cascade rules section.

| `verification.reasonCode` | **What it means** | **Default behavior*** | **Typical**`verification.reason`**values**** |
| --- | --- | --- | --- |
| `218` | You have exceeded the upload limit of number the selfie images | `resubmission_requested` | `Upload limit is exceeded` |
| `581` | Selfie did not match the portrait in the CPF registry | `declined` | `Selfie mismatch with registry` |
| `901` | Registry provider error, the CPF registry was unreachable | `declined` | `Registry unavailable` `Technical issues` |
| `902` | Person not found in the CPF registry | `declined` | `Person not found in registry` |
| `903` | Personal information verification failed (driver's license checks: validity, number, category, dates). | `declined` | `Value mismatch` `Output not received` |

*The "default behavior" column reflects the session outcome on a default configuration. Veriff can configure some of these validations differently per your request (e.g., turning a decline into a resubmission, or ignoring a check entirely).

**The “typical value” reflects the core failure condition of that validation. Other values can appear when the validation could not complete normally, for example, due to registry unavailability, missing input, or a disabled validation.

---

## Additional information

### Best practices

- `document.country`**format validation**: ensure you pass exactly `BR` for Brazil. Passing any other value in an integration configured for this registry will result in an automatic session decline as the routing logic cannot identify the target registry.
- **Selfie exists**: sending end-user’s selfie image is a mandatory requirement for this solution.
- **Selfie image quality**: ensure that end-user’s selfie image is a good quality front-facing image. This will reduce the possibility of selfie mismatch failures.
- **Selfie image formats:** this solution supports uploading .jpeg and .png images.
- **Error handling**: implement proper error handling for all possible validation results.
- **Session declined due to third-party provider issues**: implement proper session handling flow when possibly legitimate end-user’s session is declined due to the third-party service provider having issues.
- **Webhook security**: secure your webhook endpoint and verify request signatures. See [HMAC Authentication and Endpoint Security](/v1/docs/hmac-authentication-and-endpoint-security) for more info.
- **User experience**: provide clear feedback to users about validation results
- **Ensure**[**backwards compatibility**](/v1/docs/backwards-compatible-changes) for webhooks and API connections

## FAQ

#### What are common use cases for CPF Biometric Database Check?

**Enhanced Account Onboarding**

- Financial services (banks, fintechs, lending companies) verifying customers during account opening against government records
- Digital banking: streamlined onboarding without requiring physical document verification, reducing friction while maintaining security
- Credit applications: identity validation for loan applications and credit assessments

**Regulatory Compliance**

- Social benefits programs: Brazil mandates biometric validation for establishing user identity when accessing social benefits and social security loans
- Anti-fraud compliance in financial services and high-risk sectors
- LGPD compliance: proper identity validation under Brazil's data protection regulations

**Fraud Prevention**

- Account takeover protection: verifying the legitimate account holder through biometric matching
- Identity theft mitigation: cross-referencing CPF numbers and facial biometrics against official government databases
- Transaction authentication for high-value or high-risk transactions

**Marketplace and Gig Economy**

- Driver/earner onboarding: validating driver's license data (number, category, validity, issue dates) for ride-sharing and delivery platforms
- Any risk-averse, high-value use case such as marketplace supply and HR

---

## Changelog

| Date | Description |
| --- | --- |
| Jun 3, 2026 | Code `218` added |
| Jun 1, 2026 | - Added support for Brazilian dirver’s license validation - [End-user data sources](/v1/docs/cpf-biometric-database-check#enduser-data-sources) section updated: - Temporary support for document as end-user data source removed - initData section expanded - Temporary SDK and add-on functionalities removed - [Solution-specific parameters](/v1/docs/cpf-biometric-database-check#solutionspecific-parameters) section expanded - [Webhook](/v1/docs/cpf-biometric-database-check#webhook-payload) section expanded with more examples - [Status and reason codes](/v1/docs/cpf-biometric-database-check#status-and-reason-codes) section expanded |
| May 25, 2026 | Title updated to “CPF Biometric Database Check” |
| Dec 18, 2025 | Image context type in media upload section changed to `face` |
| Dec 12. 2025 | Broken links fixed |
| ****Nov 10, 2025 | Documentation published |

Veriff customer back-office, a dashboard where you can see your end-users' verification data.

Depending on your setup, you may be required to access the environment via station.veriff.com or hub.veriff.com. Always **check your sign-up email** and make sure that you **log in via correct address**.

A UUID-format unique identifier ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}) created by you for your end-user to link an end-user to their session(s). Cannot be resolved outside your environment.

Veriff stores it only for identity verification and returns it unchanged in webhooks/API responses or as `null` if not provided.

Strongly recommended if you already use UUID identifiers. Works as an alternative to `vendorData` in Biometric Authentication solution.

A custom unique identifier (max 1,000 characters) created by you, containing only non-semantic data that can't be resolved outside your systems.

Veriff returns it unchanged in webhooks/API responses or as `null` if not provided.

It's referred to as "unique identifier" in Customer Portal and cannot be changed once set.

Required for Fraud solutions (Cross Links check and Velocity Abuse check) and serves as an alternative to `endUserId` in Biometric Authentication when using non-UUID identifiers.

A session during which the end-user is verified. It starts when a session is created, it can contain several attempts (i.e. steps of uploading media, sending additional data etc.) and it ends when a conclusive decision (“approved”, “declined”, “expired”/”abandoned”) is granted.

Each verification session receives an unique ID, aka the **session ID**, which can be added to the API URL when making API requests.
