curl -X POST "https://verification.didit.me/v3/database-validation/" \
-H "x-api-key: YOUR_API_KEY" \
-F "issuing_state=ZAF" \
-F "services=zaf_dha_fingerprint_match" \
-F "vendor_data=user-1234" \
-F "consent=true" \
-F "national_id=1111111111111" \
-F "right_thumb=RIGHT_THUMB_TEMPLATE" \
-F "left_thumb=LEFT_THUMB_TEMPLATE"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="ZAF",
services=["zaf_dha_fingerprint_match"],
consent=True,
national_id="1111111111111",
right_thumb="RIGHT_THUMB_TEMPLATE",
left_thumb="LEFT_THUMB_TEMPLATE",
vendor_data="user-1234",
)
print(result)
import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234",
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "ZAF",
Services: didit.Some([]string{"zaf_dha_fingerprint_match"}),
Consent: didit.Bool(true),
NationalID: didit.String("1111111111111"),
RightThumb: didit.String("RIGHT_THUMB_TEMPLATE"),
LeftThumb: didit.String("LEFT_THUMB_TEMPLATE"),
VendorData: didit.String("user-1234"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
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("ZAF")
.services(List.of("zaf_dha_fingerprint_match"))
.consent(true)
.nationalId("1111111111111")
.rightThumb("RIGHT_THUMB_TEMPLATE")
.leftThumb("LEFT_THUMB_TEMPLATE")
.vendorData("user-1234")
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'ZAF',
'services' => ['zaf_dha_fingerprint_match'],
'consent' => true,
'national_id' => '1111111111111',
'right_thumb' => 'RIGHT_THUMB_TEMPLATE',
'left_thumb' => 'LEFT_THUMB_TEMPLATE',
'vendor_data' => 'user-1234',
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234"
)
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 = "ZAF",
Services = new string[] { "zaf_dha_fingerprint_match" },
Consent = true,
NationalId = "1111111111111",
RightThumb = "RIGHT_THUMB_TEMPLATE",
LeftThumb = "LEFT_THUMB_TEMPLATE",
VendorData = "user-1234",
});
Console.WriteLine(JsonSerializer.Serialize(result));
{
"request_id": "req_01H…",
"status": "Approved",
"issuing_state": "ZAF",
"match_type": "full_match",
"validations": [
{
"outcome_code": "MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "SAMPLE-ID-12345"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
{
"request_id": "req_01H…",
"status": "Declined",
"issuing_state": "ZAF",
"match_type": "no_match",
"validations": [
{
"outcome_code": "NO_MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
🇿🇦 South Africa
South Africa - DHA Fingerprint Match API: ID Match
South Africa - DHA Fingerprint Match: authoritative South Africa database lookup via Didit. Pay-per-call from $1.28, no contracts, no minimums.
POST
/
v3
/
database-validation
/
curl -X POST "https://verification.didit.me/v3/database-validation/" \
-H "x-api-key: YOUR_API_KEY" \
-F "issuing_state=ZAF" \
-F "services=zaf_dha_fingerprint_match" \
-F "vendor_data=user-1234" \
-F "consent=true" \
-F "national_id=1111111111111" \
-F "right_thumb=RIGHT_THUMB_TEMPLATE" \
-F "left_thumb=LEFT_THUMB_TEMPLATE"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="ZAF",
services=["zaf_dha_fingerprint_match"],
consent=True,
national_id="1111111111111",
right_thumb="RIGHT_THUMB_TEMPLATE",
left_thumb="LEFT_THUMB_TEMPLATE",
vendor_data="user-1234",
)
print(result)
import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234",
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "ZAF",
Services: didit.Some([]string{"zaf_dha_fingerprint_match"}),
Consent: didit.Bool(true),
NationalID: didit.String("1111111111111"),
RightThumb: didit.String("RIGHT_THUMB_TEMPLATE"),
LeftThumb: didit.String("LEFT_THUMB_TEMPLATE"),
VendorData: didit.String("user-1234"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
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("ZAF")
.services(List.of("zaf_dha_fingerprint_match"))
.consent(true)
.nationalId("1111111111111")
.rightThumb("RIGHT_THUMB_TEMPLATE")
.leftThumb("LEFT_THUMB_TEMPLATE")
.vendorData("user-1234")
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'ZAF',
'services' => ['zaf_dha_fingerprint_match'],
'consent' => true,
'national_id' => '1111111111111',
'right_thumb' => 'RIGHT_THUMB_TEMPLATE',
'left_thumb' => 'LEFT_THUMB_TEMPLATE',
'vendor_data' => 'user-1234',
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234"
)
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 = "ZAF",
Services = new string[] { "zaf_dha_fingerprint_match" },
Consent = true,
NationalId = "1111111111111",
RightThumb = "RIGHT_THUMB_TEMPLATE",
LeftThumb = "LEFT_THUMB_TEMPLATE",
VendorData = "user-1234",
});
Console.WriteLine(JsonSerializer.Serialize(result));
{
"request_id": "req_01H…",
"status": "Approved",
"issuing_state": "ZAF",
"match_type": "full_match",
"validations": [
{
"outcome_code": "MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "SAMPLE-ID-12345"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
{
"request_id": "req_01H…",
"status": "Declined",
"issuing_state": "ZAF",
"match_type": "no_match",
"validations": [
{
"outcome_code": "NO_MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
Verifies provided fingerprint images against the Department of Home Affairs fingerprint register. 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. Input format: national_id takes the South African ID number (13 digits, the last one a Luhn check digit).
Coverage
- Coverage: —
- Country: South Africa
- Service ID:
zaf_dha_fingerprint_match - Data domain: Biometric
- Category: Government
Inputs
| Field | Required | Example |
|---|---|---|
national_id | Yes | 1111111111111 |
right_thumb | Yes | RIGHT_THUMB_TEMPLATE |
left_thumb | Yes | LEFT_THUMB_TEMPLATE |
vendor_data | No | user-1234 |
- Required inputs:
national_id,right_thumb,left_thumb - Optional inputs:
vendor_data - Consent: Required
- Workflow availability: Standalone API only
- Coverage: —
- Price: $1.28 per successful query
right_thumb and left_thumb, which are not something a workflow step produces, so it is available only on the standalone API, where you supply the values directly.
Body parameters
Array containing this service ID. Pinning the service keeps the request scoped to this exact database.Example:
zaf_dha_fingerprint_matchNational identity number for this service.Example:
1111111111111right_thumb value required by this database service.Example: RIGHT_THUMB_TEMPLATEleft_thumb value required by this database service.Example: LEFT_THUMB_TEMPLATEYour 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-1234Input rules & validation notes
- South African ID number (13 digits, the last one a Luhn check digit)
national_idmust contain digits only; remove spaces, hyphens, and punctuation before sending the request.national_idmust be exactly 13 characters long.
How to call it
curl -X POST "https://verification.didit.me/v3/database-validation/" \
-H "x-api-key: YOUR_API_KEY" \
-F "issuing_state=ZAF" \
-F "services=zaf_dha_fingerprint_match" \
-F "vendor_data=user-1234" \
-F "consent=true" \
-F "national_id=1111111111111" \
-F "right_thumb=RIGHT_THUMB_TEMPLATE" \
-F "left_thumb=LEFT_THUMB_TEMPLATE"
from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.database_validation.validate(
issuing_state="ZAF",
services=["zaf_dha_fingerprint_match"],
consent=True,
national_id="1111111111111",
right_thumb="RIGHT_THUMB_TEMPLATE",
left_thumb="LEFT_THUMB_TEMPLATE",
vendor_data="user-1234",
)
print(result)
import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.databaseValidation.validate({
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234",
});
console.log(result);
ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{
IssuingState: "ZAF",
Services: didit.Some([]string{"zaf_dha_fingerprint_match"}),
Consent: didit.Bool(true),
NationalID: didit.String("1111111111111"),
RightThumb: didit.String("RIGHT_THUMB_TEMPLATE"),
LeftThumb: didit.String("LEFT_THUMB_TEMPLATE"),
VendorData: didit.String("user-1234"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)
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("ZAF")
.services(List.of("zaf_dha_fingerprint_match"))
.consent(true)
.nationalId("1111111111111")
.rightThumb("RIGHT_THUMB_TEMPLATE")
.leftThumb("LEFT_THUMB_TEMPLATE")
.vendorData("user-1234")
.build());
System.out.println(result);
<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->databaseValidation->validate([
'issuing_state' => 'ZAF',
'services' => ['zaf_dha_fingerprint_match'],
'consent' => true,
'national_id' => '1111111111111',
'right_thumb' => 'RIGHT_THUMB_TEMPLATE',
'left_thumb' => 'LEFT_THUMB_TEMPLATE',
'vendor_data' => 'user-1234',
]);
print_r($result->toArray());
require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.database_validation.validate(
issuing_state: "ZAF",
services: ["zaf_dha_fingerprint_match"],
consent: true,
national_id: "1111111111111",
right_thumb: "RIGHT_THUMB_TEMPLATE",
left_thumb: "LEFT_THUMB_TEMPLATE",
vendor_data: "user-1234"
)
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 = "ZAF",
Services = new string[] { "zaf_dha_fingerprint_match" },
Consent = true,
NationalId = "1111111111111",
RightThumb = "RIGHT_THUMB_TEMPLATE",
LeftThumb = "LEFT_THUMB_TEMPLATE",
VendorData = "user-1234",
});
Console.WriteLine(JsonSerializer.Serialize(result));
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 can override it.MATCH — The registry confirmed the identity and every checked field matched.{
"request_id": "req_01H…",
"status": "Approved",
"issuing_state": "ZAF",
"match_type": "full_match",
"validations": [
{
"outcome_code": "MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "SAMPLE-ID-12345"
},
"validation": {
"identification_number": "full_match"
}
}
]
}
NO_MATCH — The registry returned no match for the submitted data.{
"request_id": "req_01H…",
"status": "Declined",
"issuing_state": "ZAF",
"match_type": "no_match",
"validations": [
{
"outcome_code": "NO_MATCH",
"service_id": "zaf_dha_fingerprint_match",
"service_name": "South Africa - DHA Fingerprint Match",
"source_data": {
"identification_number": "NO_MATCH"
},
"validation": {
"identification_number": "no_match"
}
}
]
}
Returned data
The exact fields surfaced insource_data depend on what the registry returns. The generated example for zaf_dha_fingerprint_match currently documents this normalized shape:
identification_number
Pricing & SLAs
South Africa - DHA Fingerprint Match queries are billed only when Didit receives a conclusive result from the validation source.- Per-call price: $1.28 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.
Continue reading
Last modified on November 11, 2026