AI services
Integrate face comparison
Send two face photos and get back whether they belong to the same person, with a similarity score.
Request
Send multipart/form-data with both images:
| Field | Meaning |
|---|---|
sourceImage | sourceImage is required. JPEG or PNG, up to 5 MB. The reference face. |
targetImage | targetImage is required. JPEG or PNG, up to 5 MB. Compared against every face found in this image. |
Examples
curl -X POST https://core.roammoon.com/v1/ai/face-comparison/compare \
-H "X-API-Key: rm_live_YOUR_KEY" \
-F "sourceImage=@id-card.jpg" \
-F "targetImage=@selfie.jpg"Response
Returns whether the two faces belong to the same person:
{
"isSamePerson": true,
"similarity": 97.52
}similarity is null rather than 0, because there was nothing to score, whether the target image has no matching face or no face at all. isSamePerson is false either way.
{
"isSamePerson": false,
"similarity": null
}Fields that matter
| Field | Meaning |
|---|---|
isSamePerson | true once at least one face in targetImage matches sourceImage. |
similarity | The highest match confidence found, 0–100. null when isSamePerson is false. |
Billing
10 credits are charged only when the comparison succeeds and a result is returned. Every failure is refunded, whether the images were rejected or the service itself could not complete the request.
The charge policy is charge-on-success: credit is reserved when the request is accepted and only committed once processing succeeds. A failure refunds the reservation.
Getting good accuracy
- Well-lit, front-facing photos where the face is a meaningful part of the frame. Extreme angles and heavy shadow are the most common cause of missed matches.
- sourceImage should contain exactly the face you are checking against, and if it has several faces, the largest one is used.
- This is a probabilistic comparison, not identity verification. Treat a low-confidence result as inconclusive rather than a definitive no-match, and keep a human in the loop for anything that affects a person's rights or access.
Errors
Every error uses the same shape. Branch on code, not on message, because messages can change.
{
"error": {
"code": "NO_FACE_DETECTED",
"message": "No face was detected in one of the images."
}
}| HTTP | Code | What to do |
|---|---|---|
| 401 | API_KEY_REQUIRED | The X-API-Key header is missing. |
| 401 | API_KEY_INVALID | The key is wrong, disabled or expired. Check it or create a new one. |
| 403 | API_KEY_FORBIDDEN | The key is not permitted to use this service. |
| 400 | INVALID_FACE_COMPARISON_REQUEST | The sourceImage or targetImage field is missing or empty. No credit is charged. |
| 400 | NO_FACE_DETECTED | No face was detected in one of the images. No credit is charged. |
| 402 | CREDIT_LIMIT_EXCEEDED | The period's credits are exhausted. Upgrade or wait for the next period. |
| 413 | IMAGE_TOO_LARGE | The image exceeds 5 MB. Compress or resize it. |
| 415 | UNSUPPORTED_IMAGE_TYPE | Only JPEG and PNG are supported. |
| 429 | RATE_LIMIT_EXCEEDED | Per-minute request limit exceeded. Slow down. |
| 429 | FACE_COMPARISON_SERVICE_BUSY | The comparison service is saturated. Retry after a few seconds. |
| 502 | FACE_COMPARISON_UPSTREAM_ERROR | The face comparison model could not complete the request. Retryable. |
| 503 | FACE_COMPARISON_SERVICE_MISCONFIGURED | The service is not configured correctly. This is an operator problem, not something a retry fixes. |
Retrying safely
429 and 502 are retryable, so use exponential backoff. Other errors return the same result on retry. Only a successful comparison is charged, so retrying after a failure costs nothing extra. The exception is a network timeout: if the first attempt actually succeeded, the retry is charged as a second call.