Veris Compare · API
Is it the same person?One call to find out.
Send a live selfie and the photo from an ID from your backend. Compare returns a 0–100 score and a clear next step: accept, review or reject. No face models to host, and Veris never stores the images.
10 free comparisons in the sandbox · no card
Volumes, thresholds or a security review
Illustration: three example comparisons. A selfie and an ID photo of the same person score 96.4 and are accepted. Two different people score 8.2 and are rejected. The same person with a blurry ID photo scores 88.6, a match that is sent for manual review.
Trusted by teams in fintech, insurance, healthcare and e-commerce
- MontaFintech
SureLifeInsurance
CarevoHealthcare
ShoplyE-commerce
Matching faces yourself
is a project, not a feature.
Most teams need one answer: is the person on the selfie the person on the ID? Getting there in-house takes far more than that question suggests.
-
01
A face model to choose, host, tune and keep running.
CompareOne HTTPS call from your backend, in any language. There's nothing to host and no model to maintain.
-
02
A raw score that leaves your team guessing what to do.
CompareEvery result says accept, manual review or reject, with flags and a plain-English comment your operations team can act on.
-
03
Face images you then have to store and protect.
CompareImages are handled in memory only. They are never written to disk or logged, and Veris never stores them.
Two images in.
One decision out.
Everything below happens inside a single request, and your quota is only used when a comparison succeeds.
-
01 Your backend
Send two images
A captured face, usually a live selfie from Veris Capture, and a reference, usually the ID photo from Veris Scan. Base64 JSON or a file upload, JPEG or PNG, up to 5 MB each. Your license key is the only credential.
-
02 Every plan
Finds the face in each image
Each image gets a quality reading, the size of the face in pixels and, for the reference, the angle of the head. If either image has no face, you get
FACE_NOT_DETECTEDand nothing is charged. -
03 Every plan
Scores the similarity · Veris Match
The two faces are compared and scored from 0 to 100. The higher the score, the more alike they are.
-
04 Every plan
Applies your use case
Tell Compare what you're comparing, such as a selfie against an ID photo, and it applies the threshold for that scenario. You can set your own threshold on any request.
-
05 Every plan
Returns a decision
Accept, manual review or reject, with flags such as
low_reference_qualityand a comment that explains the result in plain English.
Three answers,
not a raw number.
Drag the score, switch the use case, add a flag. Your code only ever reads one field, recommendation, and your user sees the right screen.
Use case
A live selfie against the photo on a NIN slip, driver's licence or passport. More forgiving, because ID photos are often old, low resolution or printed under a watermark.
Similarity score
Flags on the images
matchtrue
confidence97.8
recommendationaccept
flags[]
"Strong match. The two faces are highly similar across both images.""accept"→approve(user)
What your app could show. The thresholds are starting defaults; you can set your own on any request.
Scan. Capture.
Compare.
Use all three for a complete check in one session, or bring Compare to images you already have.
- 01Scan the ID
Veris Scan reads the document and returns the face photo printed on it.
Veris Scan → - 02Capture a live selfie
Veris Capture confirms a real person is in front of the camera and returns their face image.
Veris Capture → - 03Compare the two
Your backend sends both images and gets one decision back.
You're here
Know it's them
with one request.
A plain HTTPS call with your license key, from any language. Keep the key on your server, never in your app.
curl https://compare.verisinfra.com/v1/compare/base64 \ -H "Authorization: Bearer $VERIS_LICENSE_KEY" \your license key, on your server -H "Content-Type: application/json" \ -d '{ "captured_b64": "<selfie from Veris Capture>", "reference_b64": "<ID photo from Veris Scan>", "use_case": "kyc_onboarding"selfie against an ID photo }'
curl https://compare.verisinfra.com/v1/compare/files \ -H "Authorization: Bearer $VERIS_LICENSE_KEY" \ -F [email protected] \JPEG or PNG, up to 5 MB -F [email protected] \ -F use_case=kyc_onboarding
# the fields your code acts oncurl … | jq '{recommendation, confidence, flags, comment}'# {# "recommendation": "accept",accept, manual_review or reject# "confidence": 97.8,# "flags": [],# "comment": "Strong match. …"# }
const res = await fetch('https://compare.verisinfra.com/v1/compare/base64', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VERIS_LICENSE_KEY}`,your license key, on your server 'Content-Type': 'application/json', }, body: JSON.stringify({ captured_b64: selfie, // from Veris Capture reference_b64: idPhoto, // from Veris Scan use_case: 'kyc_onboarding',selfie against an ID photo }),});const result = await res.json();
const form = new FormData();form.append('captured', new Blob([selfieBytes]), 'selfie.jpg');JPEG or PNG, up to 5 MBform.append('reference', new Blob([idBytes]), 'id-photo.jpg');form.append('use_case', 'kyc_onboarding');const res = await fetch('https://compare.verisinfra.com/v1/compare/files', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VERIS_LICENSE_KEY}` }, body: form,});
switch (result.recommendation) {always one of three case 'accept': await approve(user); break; case 'manual_review': await queueForReview(user, result.flags); break; case 'reject': await askToRetry(user); break;}
import os, requestsres = requests.post( "https://compare.verisinfra.com/v1/compare/base64", headers={"Authorization": f"Bearer {os.environ['VERIS_LICENSE_KEY']}"},your license key, on your server json={ "captured_b64": selfie, # from Veris Capture "reference_b64": id_photo, # from Veris Scan "use_case": "kyc_onboarding",selfie against an ID photo }, timeout=30,)result = res.json()
res = requests.post( "https://compare.verisinfra.com/v1/compare/files", headers={"Authorization": f"Bearer {os.environ['VERIS_LICENSE_KEY']}"}, files={"captured": open("selfie.jpg", "rb"), "reference": open("id-photo.jpg", "rb")},JPEG or PNG, up to 5 MB data={"use_case": "kyc_onboarding"}, timeout=30,)
if result["recommendation"] == "accept":always one of three approve(user)elif result["recommendation"] == "manual_review": queue_for_review(user, result["flags"])else: ask_to_retry(user)
body, _ := json.Marshal(map[string]string{ "captured_b64": selfie, // from Veris Capture "reference_b64": idPhoto, // from Veris Scan "use_case": "kyc_onboarding",selfie against an ID photo})req, _ := http.NewRequest("POST", "https://compare.verisinfra.com/v1/compare/base64", bytes.NewReader(body))req.Header.Set("Authorization", "Bearer "+os.Getenv("VERIS_LICENSE_KEY"))your license key, on your serverreq.Header.Set("Content-Type", "application/json")res, err := http.DefaultClient.Do(req)
var buf bytes.Bufferw := multipart.NewWriter(&buf)f, _ := w.CreateFormFile("captured", "selfie.jpg"); f.Write(selfieBytes)JPEG or PNG, up to 5 MBf, _ = w.CreateFormFile("reference", "id-photo.jpg"); f.Write(idBytes)w.WriteField("use_case", "kyc_onboarding")w.Close()req, _ := http.NewRequest("POST", "https://compare.verisinfra.com/v1/compare/files", &buf)req.Header.Set("Authorization", "Bearer "+os.Getenv("VERIS_LICENSE_KEY"))req.Header.Set("Content-Type", w.FormDataContentType())
var result struct { Recommendation string `json:"recommendation"` Flags []string `json:"flags"`}json.NewDecoder(res.Body).Decode(&result)switch result.Recommendation {always one of threecase "accept": approve(user)case "manual_review": queueForReview(user, result.Flags)default: askToRetry(user)}
Running…
→200{ "match": true, "confidence": 97.8, "recommendation": "accept" }Example values.
→200the same response shapeJPEG or PNG, up to 5 MB each.
→acceptmanual_reviewrejectAlways one of three.
Pay for answers,
never for errors.
Compare is on every plan. Only comparisons that succeed count against your calls: no face found, a bad image or a busy moment costs nothing. From Launch, extra calls are billed per call up to a fixed monthly cap.
| Feature | SparkFree | Build$9/mo | Launch$19/mo | Scale$39/mo | Pro$79/mo |
|---|---|---|---|---|---|
| Comparisons a month | 15 | 500 | 1,500 | 10,000 | 30,000 |
| Each extra comparison | Not available | Not available | $0.03 | $0.02 | $0.01 |
| Most you'll pay in extras | $0 | $0 | $30 a month | $50 a month | $80 a month |
| Use cases, decisions and flags | Yes | Yes | Yes | Yes | Yes |
| Charged only when it succeeds | Yes | Yes | Yes | Yes | Yes |
When you reach your limit, or the cap from Launch up, comparisons pause until your next billing cycle, or continue from your prepaid wallet if you've turned it on, so a bill never runs away. See full pricing
Match your first face
today.
The sandbox gives you 10 real comparisons with no card, and Spark keeps 15 a month free when you go live. Cancel any time. If your first paid month isn't right, get it back within 14 days.
- 1Create an accountEmail verification only. No card, no KYC.
- 2Compare two photos10 real comparisons in the sandbox.
- 3Go livePick a plan and swap in a live key on your server.
Questions about
Veris Compare.
Something else? Write to [email protected] or read the Compare docs.
What happens to the images?
Your backend sends them over HTTPS and they are compared in memory. They are never written to disk or logged, and Veris doesn't keep a copy.
Will an old or blurry ID photo still match?
Use kyc_onboarding, which is more forgiving of old, low-resolution and watermarked ID photos. When the faces match but the score is lower, you get manual_review with a flag such as low_reference_quality, rather than a rejection.
Do failed calls use my quota?
No. A comparison only counts once it succeeds. No face found, a bad image or a temporary error costs nothing.
What happens when I reach my limit?
On Spark and Build, comparisons pause at your monthly limit. From Launch, extra comparisons are billed per call up to a monthly cap of $30, $50 or $80, then pause until your next billing cycle, unless you've turned on the optional wallet, which pays for further comparisons from prepaid credit at the price shown in your dashboard. Your plan's bill never goes past the cap.
Does Compare check that the person is live?
No. Compare tells you whether two faces belong to the same person. Liveness runs on the phone in Veris Capture, so use the two together: Capture proves a real person is there, Compare proves it's the person on the ID.
Can I call it from my mobile app?
Call it from your backend. The request carries your license key, which must stay on your server and never ship inside an app.
Can I set my own threshold?
Yes. Each use case comes with its own threshold, and you can pass a threshold from 0 to 100 on any request. The threshold that was applied comes back in every response.
Can I try it before I pay?
Yes. The sandbox includes 10 real comparisons with no card and no KYC, Spark gives you 15 a month free when you go live, and your first paid payment is refundable within 14 days.



