Detect Faces
faceDetect runs face detection on an image and returns every face it finds, each with a bounding box and a quality
score. Faces that also match a known enrolled identity — above the engine's recognition threshold — additionally carry a
faceId, personId, and confidence.
This is a read-only operation: it never enrolls anything. To enroll a face, use
faceEnroll; to compare two specific images 1:1, use
faceCompare.
API Endpoint
- HTTP Method:
POST - Endpoint:
/api/v1/faces/faceDetect - Base URL (Cloud):
https://customername.econnectcloud.com/identities - Base URL (On-prem):
https://<server-host-or-ip>:5009
Authentication
Requires a JWT bearer token in the Authorization header. See Authentication.
Minimum Permission
The permission name and category below are what you'll see in the Identities web app under System → System settings → Roles.
| Permission | Category |
|---|---|
| Face Detection | Facial Recognition Services |
Request Body
Content-Type: application/json. The image field is sent as a base64-encoded string. Every field except
image is optional and defaults to the endpoint's original behavior, so existing callers are unaffected.
Required
| Field | Type | Description |
|---|---|---|
image | byte[] (base64) | The image to detect faces in. May contain zero, one, or many faces. |
Processing Options
| Field | Type | Default | Description |
|---|---|---|---|
largestFaceOnly | bool | false | If true, only the largest face (by bounding-box area) is returned. See below. |
matchThreshold | double | (system default) | Overrides the gallery-match confidence threshold. Must be within 0.7–1.0; out-of-range values return 400. See below. |
timeoutMs | int | 5000 | Fail-fast budget in milliseconds. Exceeding it returns 504 Gateway Timeout. Clamped to 250–30000; zero or negative values fall back to the default. See below. |
Person Inclusion Options
By default the response contains only face-level detection data. Set includePerson: true to enrich every matched
face with a person object — the same shape returned by
publishWithResponse. The
individual include* switches choose which sections of the person record to return.
| Field | Type | Default | Description |
|---|---|---|---|
includePerson | bool | false | Master switch. When true, matched faces include a person object. |
includeNames | bool | false | Include the person's names / aliases. |
includeAddresses | bool | false | Include the person's addresses. |
includeTags | bool | false | Include the person's tags. |
includeFields | bool | false | Include the person's entity-field attributes. |
excludeDisabledTags | bool | true | When true (default), tags whose definition is disabled are omitted, so downstream systems never trigger off a disabled tag. Set false to receive disabled tags too. |
A section is returned only when it is requested AND the caller holds at least one of the permissions below. A
requested section the caller isn't permitted to see is simply omitted (no error). includePerson only adds person data
for faces that matched a known person — unknown faces are returned with face data only.
| Switch | Returns | Needs any one of these permissions |
|---|---|---|
includeNames | person.aliases | Read All Identity, Mutate All Identity, Read Aliases |
includeAddresses | person.addresses | Read All Identity, Mutate All Identity, Read Addresses |
includeTags | person.personTags | Read All Identity, Mutate All Identity, Mutate Tags, Read Tags |
includeFields | person.entityFields | Read All Identity, Mutate All Identity, Mutate Entity Fields, Read Entity Fields |
These are in addition to the Face Detection permission required by the endpoint itself.
Matched vs. Unmatched Faces
A detected face is only considered a match when its recognition confidence meets the engine's minimum threshold:
- Match →
faceId,personId, andconfidenceare populated (plusboundingBoxandquality). - Below threshold →
faceId,personId, andconfidencecome backnull; you still get theboundingBoxandqualityso you know a face was located, just not recognized.
personId can also be null for a matched faceId when that face isn't linked to a person record.
Images are resized to fit within 2048×2048 before detection, but the returned boundingBox coordinates are scaled
back to the original image's pixel dimensions — so you can draw boxes directly onto the image you sent.
Largest Face Only
Set largestFaceOnly: true to return only the largest detected face (by bounding-box area) instead of every face
in the frame. This is what most integrations want when they expect a single dominant subject — the person at the door,
the customer at the counter. When includePerson is also set, only that one face is enriched.
Match-Threshold Override
By default a detected face counts as a match only when its recognition confidence meets the server-configured
minimum. Set matchThreshold to override that cutoff for a single call — raise it to demand a stronger match, or lower
it (down to the floor) to accept weaker ones. A face below the effective threshold comes back unmatched (null
faceId / personId / confidence).
matchThreshold must be within 0.7–1.0. A value below 0.7 (or above 1.0) is rejected with
400 Bad Request — the floor prevents surfacing identities on genuinely weak matches. Omit the field to use the system
default.
Fail-Fast Timeout
The whole call is bounded by timeoutMs (default 5000 ms). The budget starts once the request payload is on the
server (upload time is excluded); if detection can't finish inside it, the call fails fast with 504 Gateway Timeout
instead of hanging your integration. Raise it (up to 30000) for slower batch callers, or lower it (down to 250) if
you'd rather retry than wait.
Code Examples
- Curl
- PowerShell
- C#
API_URL="https://customername.econnectcloud.com/identities"
TOKEN="your_jwt" # from POST /api/v1/authenticate
IMG_B64=$(base64 -w 0 photo.jpg)
# Basic detect - returns one entry per detected face.
# Recognized faces carry faceId/personId/confidence; unrecognized faces return null for those.
curl -sk -X POST "$API_URL/api/v1/faces/faceDetect" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"image\": \"$IMG_B64\"}" | jq
# With options: only the largest face, enrich matched faces with the person (names + tags),
# override the match threshold (0.7-1.0), and fail fast after 3s.
# excludeDisabledTags defaults true, so disabled tags are omitted.
curl -sk -X POST "$API_URL/api/v1/faces/faceDetect" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"image\": \"$IMG_B64\",
\"largestFaceOnly\": true,
\"matchThreshold\": 0.85,
\"timeoutMs\": 3000,
\"includePerson\": true,
\"includeNames\": true,
\"includeTags\": true
}" | jq
$API_URL = "https://customername.econnectcloud.com/identities"
$TOKEN = "your_jwt" # from POST /api/v1/authenticate
$headers = @{ Authorization = "Bearer $TOKEN" }
$imgB64 = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes("photo.jpg"))
# Detect with options. Every field except "image" is optional.
$body = @{
image = $imgB64
largestFaceOnly = $true
matchThreshold = 0.85 # must be within 0.7-1.0, else 400
timeoutMs = 3000 # fail-fast budget in ms (default 5000, 504 when exceeded)
includePerson = $true
includeNames = $true
includeTags = $true
# excludeDisabledTags defaults to $true - disabled tags are omitted
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "$API_URL/api/v1/faces/faceDetect" -Method Post `
-Headers $headers -Body $body -ContentType "application/json"
$response.detections | ForEach-Object {
$who = if ($_.person) { "$($_.person.aliases[0].firstName) $($_.person.aliases[0].lastName)" } else { "(unrecognized)" }
"quality=$($_.quality) -> $who"
}
using eConnect.IdentitiesDbSdk;
// NuGet: eConnect.IdentitiesDbSdk (private package - request access from eConnect support).
var httpClient = new HttpClient();
var sdk = await IdentityDbSdk.GetSdk(
"https://customername.econnectcloud.com/identities",
httpClient,
"your_username",
"your_password");
byte[] image = await File.ReadAllBytesAsync("photo.jpg");
// Detect with options. All options are opt-in - omit them for the original face-level response.
var detected = await sdk.FaceDetectAsync(new FaceDetectRequest
{
Image = image,
LargestFaceOnly = true,
MatchThreshold = 0.85, // must be within 0.7-1.0, else 400
TimeoutMs = 3000, // fail-fast budget in ms (default 5000, 504 when exceeded)
IncludePerson = true,
IncludeNames = true,
IncludeTags = true
// ExcludeDisabledTags defaults true - disabled tags are omitted
});
foreach (var f in detected.Detections)
{
// faceId/personId/confidence are null when the face didn't match above the threshold.
// person is populated only when IncludePerson was requested AND the face matched a person.
var alias = f.Person?.Aliases?.FirstOrDefault();
var who = alias is not null ? $"{alias.FirstName} {alias.LastName}" : "(unrecognized)";
Console.WriteLine($"quality={f.Quality:P1} box=({f.BoundingBox.X},{f.BoundingBox.Y}) -> {who}");
}
Raw Sample
Request
POST https://customername.econnectcloud.com/identities/api/v1/faces/faceDetect
Authorization: Bearer <your_jwt_token>
Content-Type: application/json
{ "image": "base64_encoded_image" }
Response
200 OK — a FacesDetected object whose detections array has one entry per detected face:
{
"detections": [
{
"faceId": "5f9c2b7a-3e41-4d8a-9b6c-1a2b3c4d5e6f",
"personId": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"confidence": 0.981,
"quality": 0.93,
"boundingBox": { "x": 320, "y": 145, "width": 96, "height": 96 }
},
{
"faceId": null,
"personId": null,
"confidence": null,
"quality": 0.74,
"boundingBox": { "x": 512, "y": 210, "width": 64, "height": 64 }
}
]
}
The first entry is a recognized face; the second is a face that was located but didn't match above the threshold.
With includePerson
When includePerson: true is requested, each matched face additionally carries a person object populated with the
requested, permitted sections (unknown faces are returned with face data only):
{
"detections": [
{
"faceId": "5f9c2b7a-3e41-4d8a-9b6c-1a2b3c4d5e6f",
"personId": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"confidence": 0.981,
"quality": 0.93,
"boundingBox": { "x": 320, "y": 145, "width": 96, "height": 96 },
"person": {
"personId": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"friendlyName": "Doe, Jane",
"aliases": [ { "firstName": "Jane", "lastName": "Doe" } ],
"personTags": [ { "tag": { "name": "VIP", "disabled": false } } ]
}
}
]
}
By default (excludeDisabledTags: true) any disabled tag is omitted from person.personTags. Set
excludeDisabledTags: false to receive disabled tags too (each carries its own disabled flag).
Response Fields
| Field | Type | Description |
|---|---|---|
detections[].faceId | string | Matched face's identifier. null for a below-threshold (unrecognized) face. |
detections[].personId | string (GUID) | Matched person's identifier. null when unrecognized, or when the face isn't linked to a person. |
detections[].confidence | float | Recognition confidence, 0.0–1.0. null for a below-threshold face. |
detections[].quality | float | Face quality score, 0.0–1.0. Always present. |
detections[].boundingBox | object | { x, y, width, height } pixel coordinates in the original image. Always present. |
detections[].person | object | Person record (including personId). Present only with includePerson on a matched face; contains only the requested, permitted sections. Omitted when null. |
Response Codes
| Code | Meaning |
|---|---|
200 OK | Detection ran; detections contains the results (empty array if no faces were found). |
400 Bad Request | Invalid request — for example, matchThreshold is outside the 0.7–1.0 range. |
401 Unauthorized | Missing or invalid JWT. |
403 Forbidden | The user lacks the Face Detection permission. |
500 Internal Server Error | A server-side error occurred. |
504 Gateway Timeout | Detection did not complete within the timeoutMs budget. Safe to retry. |
Notes
- An unrecognized face returns
nullfaceId/personId/confidencebut still gives youboundingBoxandquality. boundingBoxcoordinates are in the original image's pixel space, not the downscaled detection space.- All options are opt-in — omit them and the response is exactly the original face-level shape.
includePersonadds person data inline only for matched faces; a requested section the caller isn't permitted to see is omitted silently (not an error). Disabled tags are excluded unlessexcludeDisabledTags: false.- Set
matchThresholdonly within0.7–1.0; uselargestFaceOnlywhen you expect a single dominant subject. - A
504means thetimeoutMsbudget was exceeded — retry, or raise the budget if your integration can tolerate the wait. - To turn a detected face into an enrolled identity, feed the image to
faceEnroll.