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) |
Direct API (compare_min_score) | 0.67–0.95 (default 0.85 if omitted) |
Printed document faces (for example a Colombian CC photo vs a live selfie) often score lower than live-vs-live matches. A score around 0.67–0.75 can still be a valid match for printed-document gallery images; lowering the threshold increases acceptance of genuine printed-doc matches and may raise false accepts. 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).