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

# BRA - Biometric Identity Check (CPF + selfie)

> Biometric identity validation: matches the user's selfie against the face on record for their CPF and returns whether it is the same person, not the same person, or inconclusive. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.

<div hidden data-didit-db-validation-defaults="{&#x22;issuing_state&#x22;:&#x22;BRA&#x22;,&#x22;services&#x22;:&#x22;bra_unico_idcloud&#x22;,&#x22;consent&#x22;:&#x22;true&#x22;,&#x22;tax_number&#x22;:&#x22;11111111111&#x22;,&#x22;first_name&#x22;:&#x22;John&#x22;,&#x22;last_name&#x22;:&#x22;Doe&#x22;,&#x22;full_name&#x22;:&#x22;John Doe&#x22;,&#x22;date_of_birth&#x22;:&#x22;1990-01-01&#x22;,&#x22;vendor_data&#x22;:&#x22;user-1234&#x22;}" />

Biometric identity validation: matches the user's selfie against the face on record for their CPF and returns whether it is the same person, not the same person, or inconclusive. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results.

## Coverage

* **Coverage:** 96%
* **Country:** Brazil
* **Service ID:** `bra_unico_idcloud`
* **Data domain:** Identity
* **Category:** BiometricRiskScore

About 96% of Brazilian CPF holders resolve to a biometric record in the private registry — roughly double the reach of the government face-match source, [Datavalid](/api-reference/database-validation/brazil/cpf-facial), at about 50%.

## Inputs

| Field           | Required | Example         |
| --------------- | -------: | --------------- |
| `tax_number`    |      Yes | `11111111111`   |
| `selfie`        |      Yes | `@./selfie.jpg` |
| `first_name`    |       No | `John`          |
| `last_name`     |       No | `Doe`           |
| `full_name`     |       No | `John Doe`      |
| `date_of_birth` |       No | `1990-01-01`    |
| `vendor_data`   |       No | `user-1234`     |

* **Required inputs:** `tax_number`, `selfie`
* **Optional inputs:** `first_name`, `last_name`, `full_name`, `date_of_birth`, `vendor_data`
* **Consent:** Required
* **Workflow availability:** Available in workflow
* **Coverage:** 96%
* **Price:** \$0.20 per successful query

## Body parameters

<ParamField body="issuing_state" type="string" required default="BRA" placeholder="BRA">
  ISO 3166-1 alpha-3 country code for this database service.

  Example: `BRA`
</ParamField>

<ParamField body="services" type="string" required default="bra_unico_idcloud" placeholder="bra_unico_idcloud">
  Array containing this service ID. Pinning the service keeps the request scoped to this exact database.

  Example: `bra_unico_idcloud`
</ParamField>

<ParamField body="consent" type="boolean" required default="true" placeholder="true">
  Explicit end-user consent for this service.

  Example: `true`
</ParamField>

<ParamField body="tax_number" type="string" required default="11111111111" placeholder="11111111111">
  Tax or fiscal identification number.

  Example: `11111111111`
</ParamField>

<ParamField body="selfie" type="file" required placeholder="@./selfie.jpg">
  Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP.

  Example: `@./selfie.jpg`
</ParamField>

<ParamField body="first_name" type="string" default="John" placeholder="John">
  Given name to validate.

  Example: `John`
</ParamField>

<ParamField body="last_name" type="string" default="Doe" placeholder="Doe">
  Family name to validate.

  Example: `Doe`
</ParamField>

<ParamField body="full_name" type="string" default="John Doe" placeholder="John Doe">
  Full legal name to validate.

  Example: `John Doe`
</ParamField>

<ParamField body="date_of_birth" type="string" default="1990-01-01" placeholder="1990-01-01">
  Date of birth in `YYYY-MM-DD` format.

  Example: `1990-01-01`
</ParamField>

<ParamField body="vendor_data" type="string" default="user-1234" placeholder="user-1234">
  Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise.

  Example: `user-1234`
</ParamField>

## Input rules & validation notes

* Brazilian CPF (exactly 11 digits)
* `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request.
* `tax_number` must be exactly 11 characters long.

## How to call it

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://verification.didit.me/v3/database-validation/" \
    -H "x-api-key: YOUR_API_KEY" \
    -F "issuing_state=BRA" \
    -F "services=bra_unico_idcloud" \
    -F "vendor_data=user-1234" \
    -F "consent=true" \
    -F "tax_number=11111111111" \
    -F "selfie=@./selfie.jpg"
  ```
</RequestExample>

<ResponseExample>
  Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it.

  **`MATCH`** — The registry confirmed the identity and every checked field matched.

  ```json 200 OK — MATCH theme={null}
  {
    "request_id": "req_01H…",
    "status": "Approved",
    "issuing_state": "BRA",
    "match_type": "full_match",
    "validations": [
      {
        "outcome_code": "MATCH",
        "service_id": "bra_unico_idcloud",
        "service_name": "BRA - Biometric Identity Check (CPF + selfie)",
        "source_data": {
          "biometric_registry_face_match": "yes"
        },
        "validation": {
          "identification_number": "full_match"
        }
      }
    ]
  }
  ```

  **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo.

  ```json 200 OK — BIOMETRIC_NO_MATCH theme={null}
  {
    "request_id": "req_01H…",
    "status": "Declined",
    "issuing_state": "BRA",
    "match_type": "no_match",
    "validations": [
      {
        "outcome_code": "BIOMETRIC_NO_MATCH",
        "service_id": "bra_unico_idcloud",
        "service_name": "BRA - Biometric Identity Check (CPF + selfie)",
        "source_data": {
          "identification_number": "NO_MATCH"
        },
        "validation": {
          "identification_number": "no_match"
        }
      }
    ]
  }
  ```

  **`INCONCLUSIVE`** — The registry could not determine whether the person matches - the result is genuinely uncertain (they may or may not be in the registry). This is NOT a no-match and NOT a technical image problem; no field is asserted, so match\_type is null and the check is sent to review.

  ```json 200 OK — INCONCLUSIVE theme={null}
  {
    "request_id": "req_01H…",
    "status": "In Review",
    "issuing_state": "BRA",
    "match_type": null,
    "validations": [
      {
        "outcome_code": "INCONCLUSIVE",
        "service_id": "bra_unico_idcloud",
        "service_name": "BRA - Biometric Identity Check (CPF + selfie)",
        "source_data": {},
        "validation": {}
      }
    ]
  }
  ```
</ResponseExample>

## Returned data

The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_unico_idcloud` currently documents this normalized shape:

* `biometric_registry_face_match`

## Pricing & SLAs

BRA - Biometric Identity Check (CPF + selfie) queries are billed only when Didit receives a conclusive result from the validation source.

* **Per-call price:** \$0.20 USD.
* **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source.
* **Latency:** typical p95 \< 2 s.
* **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset.

## About this source

This service runs on Brazil's largest private facial-biometric registry, operated by a Brazilian IDtech. The registry holds more than a billion facial embeddings and adds roughly 35 million new faces every month, fed by the onboarding and re-authentication flows of over 800 Brazilian companies — including four of the five largest banks. That scale is what produces the coverage figure above: a CPF lookup resolves to a biometric record for about 96% of Brazilian adults.

Didit has a direct partnership with the registry operator, so you can query it through the standard Database Validation API — pay-per-call, with no separate vendor contract, no minimum volume, and no onboarding process.

**How this differs from the government registry.** Didit also offers [Brazil - CPF + face match (Datavalid)](/api-reference/database-validation/brazil/cpf-facial), which is the official SERPRO source and the right choice when you specifically need the government registry as your source of truth. The private registry is the stronger choice for everything else, on two axes you can check: it reaches about 96% of adults against Datavalid's roughly 50%, and it matches against a biometric record the registry maintains itself rather than a portrait taken from a document the user hands you — so it resists both document forgery and stolen-CPF fraud. It is also less than half the price per query.

## Recommended flow for Brazil

For most Brazilian use cases you do not need document capture at all. The user gives you a CPF, and a liveness-checked selfie confirms they are the person behind it.

<Steps>
  <Step title="Collect the CPF">
    Your only text input is the 11-digit CPF — no document photo, and no manually typed name or date of birth.
  </Step>

  <Step title="Capture the selfie with a liveness check">
    Add a [liveness](/core-technology/liveness/overview) step to the same workflow and pick the method that matches your risk appetite — **Passive Liveness** (no user action at all), **3D Flash**, or **3D Action & Flash** (active methods that project light patterns, the last one adding a randomized action). Set it with `face_liveness_method` (`PASSIVE`, `FLASHING`, or `ACTIVE_3D`) in the Business Console or through the workflows API. Whichever you pick, Didit renders the capture step and confirms a real, present person — this is what stops a stored photo or a screen replay from being submitted.
  </Step>

  <Step title="Validate the CPF and selfie against the biometric registry">
    Inside a session flow Didit re-uses the liveness selfie automatically — you never handle the image. The registry then confirms whether that face belongs to the person the CPF belongs to.
  </Step>
</Steps>

<Note>
  This CPF-only flow applies to **session and workflow** integrations, where Didit performs the capture and passes the liveness selfie to this service for you. If you call `POST /v3/database-validation/` **directly**, `selfie` is a required file input and you supply the image yourself — see [Database Validation overview](/core-technology/database-validation/overview) for both modes.
</Note>

**Cost:** about \$0.30 per verified user with Passive Liveness — \$0.20 for the IDCloud query plus \$0.10 for the liveness check — or about \$0.35 with an active method, where the liveness check costs \$0.15. Liveness includes a free monthly tier, so early volume costs less; see [pricing](/getting-started/pricing).

**Fallback for the roughly 4% without coverage.** When the registry returns `INCONCLUSIVE`, the registry could not resolve that CPF to a usable biometric record — typically because the person is not in it. Treat this as "no answer" rather than a failed check, and fall back to full [ID Verification](/core-technology/id-verification/overview): document capture plus face match against the document portrait. Everyone stays verifiable, and you pay for document verification only on the small remainder.

**Handling declines.** `BIOMETRIC_NO_MATCH` means the registry actively disagreed — the face does not belong to that CPF. Treat it as a strong negative rather than a prompt to retry: sending the user straight to document capture is exactly the path an impostor wants, since the document is the artefact they control. Genuine false negatives do happen, though — a changed appearance, an old registry photo, or a poor capture — so route these to manual review instead of either auto-approving or dead-ending the user. `BIOMETRIC_IMAGE_UNUSABLE` is different: the selfie simply could not be read, so ask for a fresh one. Decide what each result does to the session with [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings), and see [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) for the full list.

**Returning users.** You only need to pay for a registry lookup once. After a user passes this flow, the liveness selfie is stored against their `vendor_data`, so you can re-verify them later with [Biometric Authentication](/core-technology/biometric-auth/overview) — a liveness check plus a face match against that stored face — for \$0.10, with the same choice of liveness methods. Note that this is for **returning** users specifically: a biometric-authentication session needs a stored face (or a `portrait_image` you supply) and fails at creation if the user has neither, so first-time users still go through the flow above.

## Continue reading

* [Brazil Database Validation overview](/api-reference/database-validation/brazil)
* [Database Validation overview](/core-technology/database-validation/overview)
* [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes)
