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

Prev Next

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.

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 with Veriff

  • The database check feature is configured for that integration by your Solutions Engineer

  • You have configured the decision webhook to get responses from Veriff (see the how-to in webhooks’ 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 POST /sessions[↗] 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 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)

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"
  }
}'

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

Session creation example (extended payload)

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"
      }
    }
  }'

{
  "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 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 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) for more info about image context types).

  • This endpoint requires endpoint level authentication via x-hmac-signature header. See HMAC Authentication and Endpoint Security article for general info about signature creation.

Media upload  example

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"
  }
}'

{
  "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 call.

Session update example

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"
  }
}'

{
  "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 endpoint. Solution-specific overview of what to expect is provided below in the Find decision and/or session related info > Solution-specific parameters section.


You can get the data from three sources:

  • Receive the decision webhook (full example with placeholder values below)

  • 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

{
  "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 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.

        • <validation_check>: object A specific validation check run results. See below 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

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

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

{
  "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

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.

{
  "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

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.

Sample requests

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

{
  "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)

{
  "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

{
  "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

{
  "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

{
  "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, alwaysDRIVERS_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.

Response properties explained

The API response payload is identical to decision webhook payload. See the request properties explained above.

Veriff Customer Portal

You can find the verification session related info, including the decision, in the Veriff Customer PortalWebhooks tab.

See 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?

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 → 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 for more info.

  • User experience: provide clear feedback to users about validation results

  • Ensure backwards compatibility 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

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