Face Comparison
Endpoint
POST https://api.verifik.co/v2/face-recognition/compare
Compares a probe image against one or more gallery images and returns a similarity score. Use search_mode to balance speed and accuracy.
Headers
| Name | Value |
|---|---|
| Content-Type | application/json |
| Authorization | Bearer <token> |
Params
| Name | Type | Required | Description |
|---|---|---|---|
probe | string[] | Yes | Array with at least one base64 image string. |
gallery | string[] | Yes | Array of base64 image strings to compare against. |
search_mode | string | Yes | One of FAST or ACCURATE. |
compare_min_score | number | No | Pass threshold for the comparison score (0.67–0.95). Default: 0.85. |
Image requirements
Match scores degrade when either face is small, cropped, heavily rotated or occluded. Comparison is more forgiving than liveness, but the same capture guidance still raises your match rates.
See Face Image Requirements for the capture rules and threshold reference shared by the comparison, liveness and search endpoints.
Request
- Node.js
- PHP
- Python
- Go
const fetch = require("node-fetch");
async function run() {
const res = await fetch("https://api.verifik.co/v2/face-recognition/compare", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.VERIFIK_TOKEN}`,
},
body: JSON.stringify({
probe: ["<base64>"];
gallery: ["<base64>", "<base64>"];
search_mode: "ACCURATE"
}),
});
console.log(await res.json());
}
run();
<?php
$ch = curl_init("https://api.verifik.co/v2/face-recognition/compare");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Bearer " . getenv("VERIFIK_TOKEN")
]);
$body = json_encode([
"probe" => ["<base64>"],
"gallery" => ["<base64>", "<base64>"],
"search_mode" => "FAST"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import os, requests
url = "https://api.verifik.co/v2/face-recognition/compare"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.getenv('VERIFIK_TOKEN')}"
}
payload = {
"probe": ["<base64>"],
"gallery": ["<base64>", "<base64>"],
"search_mode": "FAST"
}
r = requests.post(url, json=payload, headers=headers)
print(r.json())
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload := map[string]interface{}{
"probe": []string{"<base64>"},
"gallery": []string{"<base64>", "<base64>"},
"search_mode": "ACCURATE",
}
b, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.verifik.co/v2/face-recognition/compare", bytes.NewBuffer(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+os.Getenv("VERIFIK_TOKEN"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var out map[string]interface{}
json.NewDecoder(resp.Body).Decode(&out)
fmt.Println(out)
}
Response
- 200
- 401/403
- 409
- 412
- 500
{
"id": "AB12C",
"data": {
"score": 0.91
},
"signature": {
"message": "Certified by Verifik.co",
"dateTime": "January 16, 2024 3:44 PM"
}
}
{
"message": "Authentication required",
"code": "UNAUTHORIZED"
}
or
{
"message": "token_expired",
"code": "FORBIDDEN"
}
{
"message": "\"search_mode\" is required",
"code": "MissingParameter"
}
{
"message": "only_images_in_base64",
"code": "ERROR"
}
{
"message": "internal_error",
"code": "ERROR"
}
Face-match thresholds
| Context | Typical / allowed values |
|---|---|
| Hosted SmartEnroll / project flow default | 0.85 (compareMinScore) |
| Hosted SmartEnroll / project flow allowed range | 0.65–0.95 |
Direct API (compare_min_score) | 0.67–0.95 (default 0.85 if omitted) |
Printed ID portraits are often faded, scratched, or low-resolution. Some Colombian cédulas are especially poor, and the same document-quality problem can appear in other countries. Live selfie vs printed photo scores lower than live-vs-live. A score around 0.65–0.75 can still be a valid match for printed-document gallery images. Lowering the hosted threshold toward 0.65 increases acceptance of genuine printed-doc matches and may raise false accepts. Keep 0.85 unless you see real users failing. Prefer face-focused gallery/probe images; server-side cropFace is not supported on face-recognition compare endpoints (omit the field; prepare crops client-side if needed).
Notes
probeandgallerymust be base64 strings; images shorter than ~100 characters are rejected with412:only_images_in_base64.search_modemust beFASTorACCURATE(required by validation).- Response is wrapped with
id,data, andsignatureper standard middleware. - There is no
GET /v2/face-verifications/:id. To read a SmartEnroll face-compare result, useGET /v2/app-registrations/:id?populates[]=compareFaceVerification. FaceVerification records expire after about 90 days in production (shorter in development).