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"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="BRA",
services=["bra_unico_idcloud"],
consent=True,
tax_number="11111111111",
vendor_data="user-1234",
selfie=open("selfie.jpg", "rb"),
)
print(result)
import Didit, { fileFromPath } from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: await fileFromPath("selfie.jpg"),
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "BRA",
Services: didit.Some([]string{"bra_unico_idcloud"}),
Consent: didit.Bool(true),
TaxNumber: didit.String("11111111111"),
VendorData: didit.String("user-1234"),
Selfie: didit.Some(didit.FileFromPath("selfie.jpg")),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
import java.nio.file.Path;
import java.util.List;
import me.didit.Didit;
import me.didit.types.DatabaseValidationValidateParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.databaseValidation().validate(DatabaseValidationValidateParams.builder()
.issuingState("BRA")
.services(List.of("bra_unico_idcloud"))
.consent(true)
.taxNumber("11111111111")
.vendorData("user-1234")
.selfie(Path.of("selfie.jpg"))
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
use Didit\File;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'BRA',
'services' => ['bra_unico_idcloud'],
'consent' => true,
'tax_number' => '11111111111',
'vendor_data' => 'user-1234',
'selfie' => File::fromPath('selfie.jpg'),
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: Pathname("selfie.jpg")
)
puts result.to_h
using System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.DatabaseValidation.ValidateAsync(new DatabaseValidationValidateParams
{
IssuingState = "BRA",
Services = new string[] { "bra_unico_idcloud" },
Consent = true,
TaxNumber = "11111111111",
VendorData = "user-1234",
Selfie = FileUpload.FromPath("selfie.jpg"),
});
Console.WriteLine(JsonSerializer.Serialize(result));
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"unico_face_match": "yes"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {},
"validation": {}
}
]
}
🇧🇷 巴西
巴西 Unico IDCloud(CPF + 自拍)身份验证 API | Didit
巴西 Unico IDCloud(CPF + 自拍):通过 Didit 进行权威的巴西数据库核验。按次计费,起价 $0.20,无合同、无最低消费。
POST
/
v3
/
database-validation
/
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"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="BRA",
services=["bra_unico_idcloud"],
consent=True,
tax_number="11111111111",
vendor_data="user-1234",
selfie=open("selfie.jpg", "rb"),
)
print(result)
import Didit, { fileFromPath } from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: await fileFromPath("selfie.jpg"),
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "BRA",
Services: didit.Some([]string{"bra_unico_idcloud"}),
Consent: didit.Bool(true),
TaxNumber: didit.String("11111111111"),
VendorData: didit.String("user-1234"),
Selfie: didit.Some(didit.FileFromPath("selfie.jpg")),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
import java.nio.file.Path;
import java.util.List;
import me.didit.Didit;
import me.didit.types.DatabaseValidationValidateParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.databaseValidation().validate(DatabaseValidationValidateParams.builder()
.issuingState("BRA")
.services(List.of("bra_unico_idcloud"))
.consent(true)
.taxNumber("11111111111")
.vendorData("user-1234")
.selfie(Path.of("selfie.jpg"))
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
use Didit\File;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'BRA',
'services' => ['bra_unico_idcloud'],
'consent' => true,
'tax_number' => '11111111111',
'vendor_data' => 'user-1234',
'selfie' => File::fromPath('selfie.jpg'),
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: Pathname("selfie.jpg")
)
puts result.to_h
using System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.DatabaseValidation.ValidateAsync(new DatabaseValidationValidateParams
{
IssuingState = "BRA",
Services = new string[] { "bra_unico_idcloud" },
Consent = true,
TaxNumber = "11111111111",
VendorData = "user-1234",
Selfie = FileUpload.FromPath("selfie.jpg"),
});
Console.WriteLine(JsonSerializer.Serialize(result));
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"unico_face_match": "yes"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {},
"validation": {}
}
]
}
Unico IDCloud 生物识别核验:将用户的自拍照与其 CPF 登记的人脸进行比对,并返回是否为同一人、非同一人或结果不确定。Didit 通过
费用: 使用被动活体检测时,每位已核验用户约 $0.30,即 IDCloud 查询 $0.20 加活体检测 $0.10;使用主动方式时约 $0.35,其中活体检测为 $0.15。这些均为标准价格:您的套餐折扣适用于每一项。请参阅定价。
针对约 4% 无覆盖用户的备选方案。 当 IDCloud 返回
POST /v3/database-validation/ 提供此服务,便于您将提交的数据与权威数据源进行核验,并获得标准化的比对结果。输入格式:tax_number 接收巴西 CPF(恰好 11 位数字)。
覆盖范围
- 覆盖率: 96%
- 国家/地区: 巴西
- 服务 ID:
bra_unico_idcloud - 数据域: 身份
- 类别: BiometricRiskScore
输入
| 字段 | 必填 | 示例 |
|---|---|---|
tax_number | 是 | 11111111111 |
selfie | 是 | @./selfie.jpg |
first_name | 否 | John |
last_name | 否 | Doe |
full_name | 否 | John Doe |
date_of_birth | 否 | 1990-01-01 |
vendor_data | 否 | user-1234 |
- 必填输入:
tax_number、selfie - 可选输入:
first_name、last_name、full_name、date_of_birth、vendor_data - 同意: 必填
- 工作流可用性: 可在工作流中使用
- 覆盖率: 96%
- 价格: 每次成功查询 $0.20
请求体参数
string
默认值:"BRA"
必填
此数据库服务的 ISO 3166-1 alpha-3 国家/地区代码。示例:
BRAstring
默认值:"bra_unico_idcloud"
必填
包含此服务 ID 的数组。锁定该服务可确保请求限定为使用此确切数据库。示例:
bra_unico_idcloudboolean
默认值:"true"
必填
终端用户针对此服务的明确同意。示例:
truestring
默认值:"11111111111"
必填
税号或纳税识别号。示例:
11111111111file
必填
要上传的自拍照图像文件,用于生物识别数据库核验。支持格式:JPEG、PNG 或 WebP。示例:
@./selfie.jpgstring
需核验的名字。示例:
Johnstring
需核验的姓氏。示例:
Doestring
需核验的完整法定姓名。示例:
John Doestring
出生日期,格式为
YYYY-MM-DD。示例:1990-01-01string
默认值:"user-1234"
您为该用户设置的稳定用户标识,例如内部用户 ID。Didit 使用它将独立核验关联到同一终端用户,并减少重复检测的干扰。示例:
user-1234输入规则与校验说明
- 巴西 CPF(必须恰好为 11 位数字)
tax_number只能包含数字;发送请求前,请去除空格、连字符和标点符号。tax_number的长度必须恰好为 11 个字符。
调用方法
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"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="BRA",
services=["bra_unico_idcloud"],
consent=True,
tax_number="11111111111",
vendor_data="user-1234",
selfie=open("selfie.jpg", "rb"),
)
print(result)
import Didit, { fileFromPath } from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: await fileFromPath("selfie.jpg"),
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "BRA",
Services: didit.Some([]string{"bra_unico_idcloud"}),
Consent: didit.Bool(true),
TaxNumber: didit.String("11111111111"),
VendorData: didit.String("user-1234"),
Selfie: didit.Some(didit.FileFromPath("selfie.jpg")),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
import java.nio.file.Path;
import java.util.List;
import me.didit.Didit;
import me.didit.types.DatabaseValidationValidateParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.databaseValidation().validate(DatabaseValidationValidateParams.builder()
.issuingState("BRA")
.services(List.of("bra_unico_idcloud"))
.consent(true)
.taxNumber("11111111111")
.vendorData("user-1234")
.selfie(Path.of("selfie.jpg"))
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
use Didit\File;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'BRA',
'services' => ['bra_unico_idcloud'],
'consent' => true,
'tax_number' => '11111111111',
'vendor_data' => 'user-1234',
'selfie' => File::fromPath('selfie.jpg'),
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "BRA",
services: ["bra_unico_idcloud"],
consent: true,
tax_number: "11111111111",
vendor_data: "user-1234",
selfie: Pathname("selfie.jpg")
)
puts result.to_h
using System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.DatabaseValidation.ValidateAsync(new DatabaseValidationValidateParams
{
IssuingState = "BRA",
Services = new string[] { "bra_unico_idcloud" },
Consent = true,
TaxNumber = "11111111111",
VendorData = "user-1234",
Selfie = FileUpload.FromPath("selfie.jpg"),
});
Console.WriteLine(JsonSerializer.Serialize(result));
每次成功调用都返回 HTTP 200。outcome_code 字段说明实际发生了什么,例如可区分真正的生物识别不匹配(BIOMETRIC_NO_MATCH)与无法读取的自拍照(BIOMETRIC_IMAGE_UNUSABLE)。所示的 status 为默认功能状态;您配置的部分匹配 / 不匹配操作可以覆盖它。MATCH:登记库确认了身份,且所有已核验字段均匹配。{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"unico_face_match": "yes"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
BIOMETRIC_NO_MATCH:人脸比对分数低于通过阈值,即自拍照中的人与登记库照片不是同一人。{
"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 - Unico IDCloud (CPF + selfie)",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
INCONCLUSIVE:登记库无法判定该人是否匹配,结果确实不确定(此人可能在登记库中,也可能不在其中)。这既不是不匹配,也不是技术性的图像问题;由于没有字段被确认,match_type 为 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 - Unico IDCloud (CPF + selfie)",
"source_data": {},
"validation": {}
}
]
}
返回数据
source_data 中实际返回的具体字段取决于登记库的返回内容。bra_unico_idcloud 的生成示例目前记录了以下标准化结构:
unico_face_match
定价与 SLA
BRA - Unico IDCloud(CPF + 自拍照)查询仅在 Didit 从核验数据源收到明确结果时计费。- 单次调用价格: $0.20 USD。
- 计费: 按成功查询计费。登记库无法访问、必填字段缺失或请求在到达数据源前被拒绝时,均不收费。
- 延迟: 典型 p95 < 2 s。
- 可用性: Didit 侧每季度 99.9%;下游数据源的可用性因国家和数据集而异。
关于此数据来源
Unico 是一家巴西身份技术公司,运营着该国最大的私营人脸生物识别库。其 IDCloud 平台保存着超过 10 亿条人脸特征向量,每月新增约 3500 万张人脸,数据来自 800 多家巴西企业的入驻和重新认证流程,其中包括五大银行中的四家。正是这一规模支撑了上文的覆盖率数据:CPF 查询可为约 96% 的巴西成年人匹配到生物识别记录。 Didit 与 Unico 有直接合作关系,因此你可以通过标准的数据库核验 API 查询 IDCloud。该服务按次计费,无需单独签订 Unico 合同,没有最低用量要求,也无需额外的入驻流程。 与政府登记库的区别。 Didit 还提供 Brazil - CPF + face match (Datavalid),其数据来自官方的 SERPRO 数据源,适用于你明确需要以政府登记库作为事实依据的场景。在其他所有场景下,IDCloud 都是更好的选择,你可以从两个维度自行核实:它可覆盖约 96% 的成年人,而 Datavalid 约为 50%;并且它比对的是登记库自身维护的生物识别记录,而不是用户提供的证件照片,因此既能防范证件伪造,也能防范盗用 CPF 的欺诈。此外,每次查询的价格还不到 Datavalid 的一半。巴西推荐流程
对于大多数巴西使用场景,您根本不需要采集证件。用户提供 CPF,再由经过活体检测的自拍照确认其本人就是该 CPF 对应的人。1
采集 CPF
您唯一需要的文本输入是 11 位 CPF,无需证件照片,也无需手动输入姓名或出生日期。由于此流程不读取任何证件,除非您说明 CPF 的来源,否则 Didit 无从获取。请在创建会话时通过会话的 然后使用该键下的值创建每个会话:若未设置映射,该步骤仍会运行,但会将
metadata 发送 CPF,并将其映射为数据库核验步骤的 tax_number 输入。在 Business Console 中,这是该步骤的输入映射;通过工作流 API 则是节点的 database_validation_field_sources:{
"database_validation_countries": {"BRA": {"services": ["bra_unico_idcloud"]}},
"database_validation_field_sources": {
"tax_number": {"source": "expected_data", "key": "metadata.cpf"}
}
}
{"workflow_id": "<workflow_id>", "metadata": {"cpf": "12345678909"}}
tax_number 报告为缺失,且不会查询登记库。此时不产生任何费用,会话的 database_validations 条目会记录原因。2
采集带活体检测的自拍照
在同一工作流中添加一个活体检测步骤,并根据您的风险偏好选择相应方式:被动活体检测(用户无需任何操作)、3D 闪光,或 3D 动作与闪光(主动方式,通过投射光图案进行检测,后者还会加入随机动作)。可在 Business Console 中或通过工作流 API 使用
face_liveness_method(PASSIVE、FLASHING 或 ACTIVE_3D)进行设置。无论选择哪种方式,Didit 都会呈现采集步骤,并确认是真实且在场的人。这可防止提交存储的照片或屏幕回放。3
使用 Unico IDCloud 核验 CPF 与自拍照
在会话流程内,Didit 会自动复用活体自拍照,您无需处理图像,并从上述映射中读取 CPF。随后 IDCloud 确认该面孔是否属于该 CPF 对应的人。此步骤仅需这两项输入;如果您还在
metadata 中发送 full_name 或 date_of_birth 并完成映射,它们会作为交叉核对项传递给 Unico,但并非必需。此仅凭 CPF 的流程适用于会话和工作流集成,此时 Didit 负责采集,并将活体自拍照传递给本服务。如果您直接调用
POST /v3/database-validation/,则 selfie 是必填文件输入,需要由您自行提供图像。两种模式请参阅数据库核验概览。INCONCLUSIVE 时,表示登记库无法将该 CPF 解析为可用的生物特征记录,通常是因为该人员不在库中。应将其视为”无结果”而非核验失败,并转为完整的身份证件验证:采集证件并将人脸与证件照进行比对。所有用户仍可完成核验,且您只需为其中一小部分用户支付证件核验费用。
处理拒绝结果。 BIOMETRIC_NO_MATCH 表示登记库明确不一致,即该面孔不属于该 CPF。应将其视为强烈的否定信号,而非提示重试:直接引导用户进行证件采集,恰恰是冒名者希望的路径,因为证件是他们能够控制的凭证。不过,确实会出现假阴性,例如外观变化、登记库照片过旧或采集质量差,因此应将这些情况转入人工审核,而不是自动通过或让用户就此中止。BIOMETRIC_IMAGE_UNUSABLE 则不同:自拍照无法读取,因此请求用户重新提供。使用部分匹配/不匹配操作决定每种结果对会话的影响,完整列表请参阅结果代码。
回访用户。 登记库查询只需付费一次。用户通过此流程后,活体自拍照会与其 vendor_data 一同存储,因此您之后可以通过生物识别认证对其重新核验:即活体检测加上与该存储人脸的比对,费用为 $0.10,并可选择同样的活体检测方式。请注意,这仅适用于回访用户:生物识别认证会话需要已存储的人脸(或您提供的 portrait_image),若用户二者皆无,会话创建时将失败,因此首次使用的用户仍需按上述流程操作。
继续阅读
最后修改于 2026年11月7日