Face verification
The face endpoints compare faces two ways: 1:1, is this selfie the person on this document, and 1:N, is this face already in your tenant's gallery. Every comparison is a cosine similarity between face embeddings computed on the server, judged against a threshold your tenant can tune on the dashboard's Decision thresholds page.
1:1 verification
POST /v1/face/verify takes two images as image_a and image_b
(multipart) and returns:
{
"match": true,
"similarity": 0.71,
"threshold": 0.45,
"image_a": { "face_bbox": { "…": "…" }, "quality": { "…": "…" } },
"image_b": { "face_bbox": { "…": "…" }, "quality": { "…": "…" } },
"model_version": "…",
"request_id": "…"
}
match is similarity >= threshold (face_match_threshold, default
0.45). A document photo can be sent as image_a directly: the main
portrait is located on a CID, SRC, passport or work permit, and the small
ghost portrait printed on the card is ignored; a second, different
person's face in image_a fails with multiple_faces_detected_in_image_a.
Run /v1/ocr on the same photo first, which checks the face against the
document's portrait frame. Each image must contain exactly one clear face;
otherwise the call fails with no_face_detected, multiple_faces_detected
or low_quality_face, suffixed with the image (…_in_image_b).
Inside a verification session the match runs on the server between the document portrait and the frame the liveness check scored; the app never uploads a selfie for matching.
The gallery: 1:N search and duplicates
Registering a face stores its embedding, not the image unless your storage
policy keeps source images, under a customer_ref. Every gallery call is
secret key only: make it from your server. A session token or publishable
key gets 403 forbidden.
| Call | Purpose |
|---|---|
POST /v1/face/registrations (image, customer_ref) | Add a face to the gallery. Returns fr_…. |
POST /v1/face/registrations/verify (image, customer_ref) | 1:1 against everything registered for that customer_ref. |
POST /v1/face/search (image, optional limit, min_similarity) | 1:N: the most similar registrations, best first. |
POST /v1/face/dedupe (image) | The single best match against the whole gallery, with is_duplicate judged against face_dedupe_threshold (default 0.55). Use it before onboarding to catch the same person under two identities. |
GET /v1/face/registrations, GET / DELETE /v1/face/registrations/{id} | List (cursor-paginated), read and delete registrations. |
Embeddings are tied to the model version that produced them. After a model
upgrade, a comparison against an older embedding returns
409 model_version_mismatch; re-register that face.
Storage
Embeddings are kept for face_embedding_ttl_days (default 365) and source
images only when store_source_images is on. Registrations appear on the
dashboard's Face registrations page.
Webhook
POST /v1/face/verify publishes face.verify.completed with the result.
See Webhooks.