curl -X POST 'https://verification.didit.me/v3/face-match/' \
-H 'x-api-key: YOUR_API_KEY' \
-F 'user_image=@./selfie.jpg' \
-F 'ref_image=@./id_portrait.jpg' \
-F 'face_match_score_decline_threshold=50' \
-F 'save_api_request=true' \
-F 'vendor_data=user-123'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.face_match.compare(
user_image=open("user_image.jpg", "rb"),
ref_image=open("ref_image.jpg", "rb"),
face_match_score_decline_threshold=50.0,
rotate_image=False,
save_api_request=True,
vendor_data="user-123",
metadata={"flow": "login"},
)
print(result)import Didit, { fileFromPath } from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.faceMatch.compare({
user_image: await fileFromPath("user_image.jpg"),
ref_image: await fileFromPath("ref_image.jpg"),
face_match_score_decline_threshold: 50.0,
rotate_image: false,
save_api_request: true,
vendor_data: "user-123",
metadata: { flow: "login" },
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.FaceMatch.Compare(ctx, didit.FaceMatchCompareParams{
UserImage: didit.FileFromPath("user_image.jpg"),
RefImage: didit.FileFromPath("ref_image.jpg"),
FaceMatchScoreDeclineThreshold: didit.Float(50.0),
RotateImage: didit.Bool(false),
SaveAPIRequest: didit.Bool(true),
VendorData: didit.String("user-123"),
Metadata: didit.Some(map[string]any{"flow": "login"}),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import java.nio.file.Path;
import java.util.Map;
import me.didit.Didit;
import me.didit.types.FaceMatchCompareParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.faceMatch().compare(FaceMatchCompareParams.builder()
.userImage(Path.of("user_image.jpg"))
.refImage(Path.of("ref_image.jpg"))
.faceMatchScoreDeclineThreshold(50.0)
.rotateImage(false)
.saveApiRequest(true)
.vendorData("user-123")
.metadata(Map.of("flow", "login"))
.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->faceMatch->compare([
'user_image' => File::fromPath('user_image.jpg'),
'ref_image' => File::fromPath('ref_image.jpg'),
'face_match_score_decline_threshold' => 50.0,
'rotate_image' => false,
'save_api_request' => true,
'vendor_data' => 'user-123',
'metadata' => ['flow' => 'login'],
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.face_match.compare(
user_image: Pathname("user_image.jpg"),
ref_image: Pathname("ref_image.jpg"),
face_match_score_decline_threshold: 50.0,
rotate_image: false,
save_api_request: true,
vendor_data: "user-123",
metadata: { flow: "login" }
)
puts result.to_husing System;
using System.Collections.Generic;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.FaceMatch.CompareAsync(new FaceMatchCompareParams
{
UserImage = FileUpload.FromPath("user_image.jpg"),
RefImage = FileUpload.FromPath("ref_image.jpg"),
FaceMatchScoreDeclineThreshold = 50.0,
RotateImage = false,
SaveApiRequest = true,
VendorData = "user-123",
Metadata = new Dictionary<string, object> { ["flow"] = "login" },
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"request_id": "f9f5a777-8002-44c6-baaf-128bcfd6e226",
"face_match": {
"status": "Approved",
"score": 99.41,
"user_image": {
"entities": [
{
"bbox": [
661,
728,
1688,
2188
],
"confidence": 0.732973,
"age": 26.91,
"gender": "male",
"race": null
}
],
"best_angle": 0
},
"ref_image": {
"entities": [
{
"bbox": [
653,
745,
1691,
2185
],
"confidence": 0.722082,
"age": 27,
"gender": "male",
"race": null
}
],
"best_angle": 0
},
"warnings": []
},
"vendor_data": "user-123",
"metadata": {
"flow": "login"
},
"created_at": "2026-06-12T01:04:42.763237+00:00"
}Face Match API: 1:1 Face Comparison
POST /v3/face-match/ for 1:1 face comparison. Identity verification, access control, re-auth. Sub-2s inference, pay-per-use pricing, no monthly minimums.
curl -X POST 'https://verification.didit.me/v3/face-match/' \
-H 'x-api-key: YOUR_API_KEY' \
-F 'user_image=@./selfie.jpg' \
-F 'ref_image=@./id_portrait.jpg' \
-F 'face_match_score_decline_threshold=50' \
-F 'save_api_request=true' \
-F 'vendor_data=user-123'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.face_match.compare(
user_image=open("user_image.jpg", "rb"),
ref_image=open("ref_image.jpg", "rb"),
face_match_score_decline_threshold=50.0,
rotate_image=False,
save_api_request=True,
vendor_data="user-123",
metadata={"flow": "login"},
)
print(result)import Didit, { fileFromPath } from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.faceMatch.compare({
user_image: await fileFromPath("user_image.jpg"),
ref_image: await fileFromPath("ref_image.jpg"),
face_match_score_decline_threshold: 50.0,
rotate_image: false,
save_api_request: true,
vendor_data: "user-123",
metadata: { flow: "login" },
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.FaceMatch.Compare(ctx, didit.FaceMatchCompareParams{
UserImage: didit.FileFromPath("user_image.jpg"),
RefImage: didit.FileFromPath("ref_image.jpg"),
FaceMatchScoreDeclineThreshold: didit.Float(50.0),
RotateImage: didit.Bool(false),
SaveAPIRequest: didit.Bool(true),
VendorData: didit.String("user-123"),
Metadata: didit.Some(map[string]any{"flow": "login"}),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import java.nio.file.Path;
import java.util.Map;
import me.didit.Didit;
import me.didit.types.FaceMatchCompareParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.faceMatch().compare(FaceMatchCompareParams.builder()
.userImage(Path.of("user_image.jpg"))
.refImage(Path.of("ref_image.jpg"))
.faceMatchScoreDeclineThreshold(50.0)
.rotateImage(false)
.saveApiRequest(true)
.vendorData("user-123")
.metadata(Map.of("flow", "login"))
.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->faceMatch->compare([
'user_image' => File::fromPath('user_image.jpg'),
'ref_image' => File::fromPath('ref_image.jpg'),
'face_match_score_decline_threshold' => 50.0,
'rotate_image' => false,
'save_api_request' => true,
'vendor_data' => 'user-123',
'metadata' => ['flow' => 'login'],
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.face_match.compare(
user_image: Pathname("user_image.jpg"),
ref_image: Pathname("ref_image.jpg"),
face_match_score_decline_threshold: 50.0,
rotate_image: false,
save_api_request: true,
vendor_data: "user-123",
metadata: { flow: "login" }
)
puts result.to_husing System;
using System.Collections.Generic;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.FaceMatch.CompareAsync(new FaceMatchCompareParams
{
UserImage = FileUpload.FromPath("user_image.jpg"),
RefImage = FileUpload.FromPath("ref_image.jpg"),
FaceMatchScoreDeclineThreshold = 50.0,
RotateImage = false,
SaveApiRequest = true,
VendorData = "user-123",
Metadata = new Dictionary<string, object> { ["flow"] = "login" },
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"request_id": "f9f5a777-8002-44c6-baaf-128bcfd6e226",
"face_match": {
"status": "Approved",
"score": 99.41,
"user_image": {
"entities": [
{
"bbox": [
661,
728,
1688,
2188
],
"confidence": 0.732973,
"age": 26.91,
"gender": "male",
"race": null
}
],
"best_angle": 0
},
"ref_image": {
"entities": [
{
"bbox": [
653,
745,
1691,
2185
],
"confidence": 0.722082,
"age": 27,
"gender": "male",
"race": null
}
],
"best_angle": 0
},
"warnings": []
},
"vendor_data": "user-123",
"metadata": {
"flow": "login"
},
"created_at": "2026-06-12T01:04:42.763237+00:00"
}Authorizations
Your application's API key, from Developers -> API keys in the Business Console. The primary key has full access. A named key can be scoped: none, read or write per resource, limited to some workflows or to approved sessions, to a list of IP addresses, and to an expiry date. 401 means the key is wrong, revoked or expired; 403 means no key was sent, the key has no access to this resource or action, or the request came from an address outside its IP list; 404 on a session route means the session is outside the key's workflows or statuses. A key without media access receives image, video and PDF URLs as null, and a key without sessions write receives session links and tokens as null. See https://docs.didit.me/console/api-keys.
Body
Live or candidate face image to verify (e.g. a selfie). Submit a single front-facing photo with the subject's face clearly visible and well lit. Allowed extensions: tiff, jpg, jpeg, png, webp. Maximum upload size: 5 MB (larger files are rejected with 400). Images are automatically compressed to ~0.5 MB before processing, so very high resolutions do not improve accuracy.
Similarity threshold (0–100) that drives the response status. A computed score at or below this value sets status to Declined and adds a LOW_FACE_MATCH_SIMILARITY warning; a score strictly above it returns Approved. Default 30 is permissive — raise it (e.g. 50–60) for stricter verification. Values outside 0–100 return 400.
0 <= x <= 10050
When true, the service tries the input images in 90-degree increments (0, 90, 180, 270) and uses the orientation that yields the best face detection — useful for mobile captures with missing EXIF orientation. Adds latency, so only enable it if you cannot guarantee upright images.
false
When true (default), persists the call as an API-type session — visible in the Business Console, retrievable via GET /v3/session/{sessionId}/decision/ using the returned request_id, and announced through a status.updated webhook. When false, nothing is stored and request_id is a transient UUID for response correlation only.
true
Response
Face match computed. face_match.score is a 0–100 float (two decimals); status is Approved when the score is strictly above face_match_score_decline_threshold, otherwise Declined with an explanatory warning. A low similarity or unscorable pair still returns 200 — inspect face_match.status and face_match.warnings, not just the HTTP code. When save_api_request=true, request_id is the persisted session id.