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. This solution does not return any data from the registry, it returns validation results for data validations and face match results.
Brazil (CPF) Biometric Database Check can be used in two ways: as an add-on to your identity verification flow or as a standalone check.
As an add-on to your IDV flow
The solution is available via SDK, web and API, and the check runs automatically once your verification flow has captured a supported Brazilian driving license and a selfie. No new integration is needed i.e., it uses the same integration that is used for the identity verification.
As a standalone check
The solution is available only via API (there is no end-user flow) and a new integration is required. You are responsible for collecting and sending relevant Driver’s license data and end-user’s selfie.
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.
If any data was extracted from the document (for example during the end-user flow), this data is provided in the decision webhook payload and GET /decision endpoint’s response 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)
If using this as an add-on to an identity verification flow, your flow must already capture the Brazilian driver’s license and a selfie.
Note: if any other document is presented, this check is not performed, but it will not affect the overall result of the identity verification session.
If using this as a standalone check via API, make sure you are ready to collect and send Veriff your end-user’s data and selfie
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. |
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, |
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 Verification uses the document extraction or initData, depending if the solution is an add-on or used as standalone.
The minimum data combination to run a successful check is: CPF number + document country code + document type
Document data
When used as an add-on, data is extracted from the end-user's document during document capture: name, date of birth, gender, license number, license category, first-issue date, and validity dates. None of these are required in the POST /sessions payload for an add-on session, they are populated once the document is captured.
However, if both a document-extracted value and a matching initData value are present for the same field, the document-extracted value takes priority.
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, document country, license category info, ID number, gender etc.
Parameters that can be sent via initData:
verification:objectRoot object containing all session parametersperson:objectObject containing person informationidNumber:string11-digit CPF number (e.g.,12345678901). [REQUIRED]firstName:stringEnd-user's first name. Matched against SERPRO records. [OPTIONAL]lastName:stringEnd-user's last name. Matched against SERPRO records. [OPTIONAL]dateOfBirth:stringDate of birth inYYYY-MM-DDformat. [OPTIONAL]gender:stringEnd-user’s gender,MorF. [OPTIONAL]
document:objectObject containing document informationcountry:stringMust beBR. [REQUIRED]type:stringDocument type, alwaysDRIVERS_LICENSE). [REQUIRED]registrationNumber:stringBrazilian driver's license registration number. [OPTIONAL]category:stringLicense category, ofAB,B,C,D,E). [OPTIONAL]firstIssue:stringDate of first license issue inYYYY-MM-DDformat. [OPTIONAL]validFrom:stringLicense validity start date inYYYY-MM-DDformat. [OPTIONAL]validUntil:stringLicense validity end date inYYYY-MM-DDformat. [OPTIONAL]
Flow overview
Use as an identity verification add-on
Use these steps when the check should run automatically as part of your existing identity verification flow. This add-on runs on any session created on an integration where your Solutions Engineer has enabled it.
Create the session as you normally would for your identity verification flow. No add-on-specific parameter is required.
Session creation bash example
curl -X POST \
--url '/v1/sessions/' \
-H 'X-AUTH-CLIENT: your-api-key' \
-H 'Content-Type: application/json' \
-d '{
"verification": {
"callback": "https://exampleURL.com"
}
}'
The end-user submits their document. For the check to run, the end-user must use their Brazilian driver’s license.
Veriff extracts the required data from it.
The end-user captures a selfie.
Veriff forwards the identity data extracted from the document, together with the selfie, to the government registry.
The registry returns whether the person was found, the face-match result, and the result of each enabled identity-data match.
Check the decision data and/or session-related info from the decision webhook and/or query the data from the {{variable.GET-sessions-decision-link}} endpoint, exactly as in the standalone flow below.
Use as standalone check via API
Generate a verification session using the API keys and the
baseURLof your integration (see the API Documentation and API Reference how to find these)Make sure to pass the mandatory
verification.person.idNumberparameter with the end-user’s CPF valueMake sure to pass the mandatory
verification.document.countryparameter with theBRvalueMake sure to pass the mandatory
verification.document.typeparameter with theDRIVERS_LICENSEvalueVeriff strongly recommends you create and send the
endUserIdorvendorData
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"
}
}
}'
{
"verification": {
"callback": "https://exampleURL.com",
"person": {
"idNumber": "12345678901"
},
"document": {
"country": "BR",
"type": "DRIVERS_LICENSE"
}
}
}
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",
"registrationNumber": "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 .
jpegand.pngformats.Specify the
image.contextasfacefor the image (see Context types (image, video) for more info about image context types).This endpoint requires endpoint level authentication via
X-HMAC-SIGNATUREheader. 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.
This endpoint requires endpoint level authentication via
X-HMAC-SIGNATUREheader. See HMAC Authentication and Endpoint Security article for general info about signature creation.
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"
}
}
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 below.
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)
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 Brazil - CPF Biometric Database Verification solution is returned in registryValidations.BR_CPF object. This parameter contains the match results and person data (if 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:objectVerification results objectregistryValidations:objectRegistry validation results objectBR_CPF:objectRegistry validation result for Brazil - CPF Biometric Verificationstatus:stringOverall result of the registry check. One of:success,failureorerror. See below for more info.data:nullAlwaysnullThe CPF registry does not return person data, it only confirms or denies matchesvalidations:object | nullMap of specific validation checks.nullwhenstatusiserror.<validation_check>:objectA specific validation check run results. See below for more info.result:stringOutcome of the validation. One of:success(passed),failure(failed),not_applicable(could not run)reason:string | nullMachine-readable reason for the result.nullonresult:success. See below for more info
error:object | nullError details whenstatusiserrorcode:stringMachine-readable error code, alwaysregistry_errormessage:stringHuman-readable error description, enumregistry_unavailable,technical_issues
timestamp:string | nullISO-8601 timestamp of when the registry responded, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset.nullwhen registry was not reached. Always sent.
Possible BR_CPF.status values
Status | Description |
|---|---|
| All checks passed or are not applicable |
| One or more validations failed |
| Registry could not be reached or returned an unexpected response |
Available BR_CPF.validation_check values
Validation check | Description |
|---|---|
| Whether the person was found in the CPF registry |
| Whether the uploaded selfie matches the registry portrait |
| Whether the provided name matches the registry name |
| Whether the provided DOB matches the registry DOB |
| Whether the provided gender matches the registry gender |
| Whether the DL number matches |
| Whether the DL category matches |
| Whether the DL is currently valid in the registry |
| Whether the DL first issue date matches |
| Whether the DL valid-from date matches |
| Whether the DL valid-until date matches |
Possible validation_check.reason values
| When it appears |
|---|---|
| On |
| A field validation's own input was not sent. If that field is required, the registry is not called, and every other validation cascades to CPF and selfie are always mandatory and cannot be missing. |
| Validation passed. |
| On each of the 9 field validations, when they are set to |
| On |
| The registry was unreachable. |
| On |
| An internal processing error occurred. |
| On an individual field validation: its value did not match the registry record. |
Possible error.message values
| When it appears |
|---|---|
| The registry could not be reached, or the request timed out. |
| An internal processing error occurred while performing the check. |
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 configurationThe 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
statusofsuccesswithin theBR_CPFobject, 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 set to
not_applicable. The propagatedreasonis not always the same as the failing check's ownreason, it depends on how far downstream the validation sits. See the cascade order and scenarios below for the exact propagation
Cascade order
Registry check requested
│
├── A field validation is configured as required, and its input is missing at runtime → registry is not called
│ → that field validation = FAIL, reason: input_not_provided
│ → person_registered = N/A, reason: input_not_provided
│ → selfie_registry_match = N/A, reason: input_not_provided
│ → each of the remaining 8 field validations = N/A, reason: input_not_provided
│
└── Registry is called
│
├── Registry error (unavailable, timeout, or invalid response)
│ → status: error, data: null, validations: null
│ → error.message: registry_unavailable / technical_issues
│
└── Registry responds
│
├── CPF is invalid → person_registered = FAIL, reason: input_invalid
│ → selfie_registry_match = N/A, reason: input_invalid
│ → each of the 9 field validations = N/A, reason: output_not_received
│
├── Person not found → person_registered = FAIL, reason: person_not_found
│ reasonCode: 902
│ → selfie_registry_match = N/A, reason: person_not_found
│ → each of the 9 field validations = N/A, reason: output_not_received
│
└── Person found → person_registered = PASS
│
└── Face match score ≥ threshold?
├─ NO → selfie_registry_match = FAIL, reason: selfie_mismatch
│ reasonCode: 581
│ each of the 9 field validations = N/A, reason: selfie_mismatch
│
└─ YES → 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 → reason: value_mismatch, reasonCode: 903
Cascade rules
If one of the 9 field validations is configured as required and its input is missing at runtime, the registry is not called at all. CPF and selfie are always mandatory for this check and cannot themselves be missing, this rule only applies to the 9 configurable field validations.
That field validation returns
failure.person_registeredandselfie_registry_matchresult innot_applicable.The remaining 8 field validations result in
not_applicable.Every one of these carries
reason:input_not_provided.
If the registry cannot be reached at all:
statusiserror,data and validations are
null,and
error.messageisregistry_unavailableortechnical_issues.No individual validation results are returned in this case. No further evaluation occurs.
If the CPF is invalid:
person_registeredfails withreason:input_invalid,selfie_registry_matchis set tonot_applicablewithreason:input_invalid.The 9 field validations are set to
not_applicablewithreason:output_not_received.
If
person_registeredfails because the person was not found:it carries
reason:person_not_found.selfie_registry_matchis set tonot_applicablewithreason:person_not_found.The 9 field validations are set to
not_applicablewithreason:output_not_received.
If
selfie_registry_matchfails on its own check (a face-match mismatch, person was found), all field validations are set tonot_applicablewith the same reason,selfie_mismatch. This is the one case where the reason propagates unchanged all the way down.If
selfie_registry_matchpasses, each enabled field validation is evaluated independently. A failure in one does not block the others.Field validations are optional. Only those enabled in your configuration are evaluated.
Click to open an example of a declined session where person_not_found caused a cascading failure of other checks
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": "Person not found in 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": "failure",
"reason": "person_not_found"
},
"selfie_registry_match": {
"result": "not_applicable",
"reason": "person_not_found"
},
"name_match": {
"result": "not_applicable",
"reason": "output_not_received"
},
"date_of_birth_match": {
"result": "not_applicable",
"reason": "output_not_received"
},
"gender_match": {
"result": "not_applicable",
"reason": "output_not_received"
}
},
"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_CPFobject 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)
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)
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
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": 581,
"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
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
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": 901,
"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:stringStatus of the responseverification:objectVerification request decision object.nullif decision is not available yetid:stringUUID v4 which identifies the verification sessionattemptId:stringUUID v4 of the attempt which received a status (as shown inverification.statusfield)vendorData:string | nullThe unique identifier that you created for your end-user.nullif not specifiedendUserId:string | nullThe UUID that you created for your end-user.nullif not specifiedstatus:stringVerification status, one ofapproved,declined,resubmission_requested,expired,abandonedcode:integerVerification session decision code, one of9001,9102,9103,9104. For more info, see the verification session decision codesreason:string | nullReason why the verification failed. For more info, see the Session decision statuses and status reasons section belowreasonCode:integer | nullReason code of the failed verificationdecisionTime:string | nullTimestamp of the decision, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)acceptanceTime:stringTimestamp of the session generation, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)submissionTime:stringTimestamp of when the session was submitted, represented asUTC YYYY-MM-DDTHH:MM:SS.SSSSSS+Timezone Offset(ISO 8601)person:objectData about the verified personfirstName:string | nullPerson's first namelastName:string | nullPerson's last namedateOfBirth:stringPerson's date of birth, represented asYYYY-MM-DDgender:string | nullPerson's gender, represented asMorF, ornullif not presentnationality:string | nullPerson's nationality, represented as ISO 3166alpha-2oralpha-3codeidNumber:string | nullPerson's CPF numberyearOfBirth:string | nullPerson's year of birth, represented asYYYYplaceOfBirth:string | nullPerson's place of birth
document:objectVerified documentnumber:string | nullDocument number,[a-zA-Z0-9]characters onlytype:string | nullDocument type, alwaysDRIVERS_LICENSEcountry:string | nullDocument issuing country, represented as ISO 3166alpha-2codestate:string | nullDocument issuing state, represented as ISO 3166alpha-2oralpha-3code
registryValidations:objectRegistry validation results for this sessionBR_CPF:objectResults of the Brazilian CPF registry checkstatus:stringOverall result of the registry check:success,failure, orerrordata:object | nullAlwaysnullfor BR, because the CPF registry does not return person data, it only confirms/denies matchesvalidations:object | nullMap of validation results.nullwhenstatusiserrorperson_registered:objectWhether the person was found in the CPF registryresult:stringValidation resultreason:string | nullReason for the result
selfie_registry_match:objectWhether the uploaded selfie matches the registry portraitresult:stringValidation resultreason:string | nullReason for the result
name_match:objectWhether the provided name matches the registry nameresult:stringValidation resultreason:string | nullReason for the result
date_of_birth_match:objectWhether the provided date of birth matches the registry date of birthresult:stringValidation resultreason:string | nullReason for the result
gender_match:objectWhether the provided gender matches the registry genderresult:stringValidation resultreason:string | nullReason for the result
drivers_license_number_match:objectWhether the driver's license number matches the registry recordresult:stringValidation resultreason:string | nullReason for the result
drivers_license_category_match:objectWhether the driver's license category matches the registry recordresult:stringValidation resultreason:string | nullReason for the result
drivers_license_is_valid:objectWhether the driver's license is currently valid in the registryresult:stringValidation resultreason:string | nullReason for the result
drivers_license_first_issue_match:objectWhether the driver's license first issue date matches the registry recordresult:stringValidation resultreason:string | nullReason for the result
drivers_license_valid_from_match:objectWhether the driver's license valid-from date matches the registry recordresult:stringValidation resultreason:string | nullReason for the result
drivers_license_valid_until_match:objectWhether the driver's license valid-until date matches the registry recordresult:stringValidation resultreason:string | nullReason for the result
error:object | nullError details whenstatusiserror.nullotherwisecode:stringMachine-readable error code, alwaysregistry_errormessage:stringHuman-readable error description, enumregistry_unavailable,technical_issues
timestamp:string | nullISO 8601 timestamp of when the registry responded.nullif the registry did not respond. Always sent.
additionalVerifiedData:objectData 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:objectTechnical data objectip:string | nullIP 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 Portal → Webhooks 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.codefor verification session decision code, one of9001,9102,9103,9104verification.statusfor verification decision status, one ofapproved,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.reasonCodeto determine what kind of problem occurred and to create programmatic actions based on rejection outcomes.Use the
verification.reasonfor 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
reasonfield surfaces whichever specific reason applied in that session, translated into English.Because of this, there is no 1:1 relationship between
reasonCodeandreason.reasonvalues likeRegistry unavailableorTechnical issuescan appear under anyreasonCodebecause 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.
| What it means | Default behaviour* | Typical |
|---|---|---|---|
| You have exceeded the upload limit of number the selfie images |
|
|
| Selfie did not match the portrait in the CPF registry |
|
|
| Registry provider error, the CPF registry was unreachable |
|
|
| Person not found in the CPF registry |
|
|
| Personal information verification failed (driver's license checks: validity, number, category, dates). |
|
|
*The "default behaviour" 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.countryformat validation: ensure you pass exactlyBRfor 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 |
|---|---|
Sep 30, 2026 |
|
Jun 3, 2026 | Code |
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 |
Dec 12. 2025 | Broken links fixed |
Nov 10, 2025 | Documentation published |