Enroll a Face
faceEnroll is the REST entry point for giving an identity a face. Send a face image and the engine enrolls it — either
by creating a new person from that face or by attaching another photo to a person that already exists.
- Omit the
personIdquery parameter → a new person is created and itspersonIdis returned. - Provide
personId→ the face is added as another enrollment photo for that existing person.
Use it together with Person Management to fill in names, tags, and attributes after the face is enrolled. To read faces back out, see Detect Faces; to avoid duplicate enrollments on retries, pair this endpoint with Check Image Reference.
API Endpoint
- HTTP Method:
POST - Endpoint:
/api/v1/faces/faceEnroll - 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 Enrollment | Facial Recognition Services |
Assign this permission to a Role, then assign the role to your integration User.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
personId | Guid | (none) | Attach the face to this existing person. Omit to create a new person. |
forceEnrollment | bool | false | Enroll even if the quality / similarity checks would normally reject the image. See below. |
Request Body
Content-Type: application/json. Binary fields (e.g. faceImage) are sent as base64-encoded strings.
| Field | Type | Required | Description |
|---|---|---|---|
faceImage | byte[] (base64) | Yes | The face image to enroll. |
photoReferenceId | string | No | A caller-supplied reference id for the image. Enables idempotent retries and is what checkImageReference looks up. See below. |
Create vs. Attach
Whether you get a new person or add to an existing one is decided entirely by the personId query parameter:
- No
personId→ the engine creates a person, enrolls the face against it, and returns the newpersonId. personIdsupplied → the face is added to that person. If the id doesn't match a person, the call returns404 Not Foundand nothing is enrolled.
When you enroll without a personId, the person record is created before the face is enrolled. If the
enrollment then fails (for example, no face could be detected in the image), that just-created person is removed
automatically — a failed enrollment never leaves an empty person behind.
Idempotent Retries with photoReferenceId
If you pass a photoReferenceId, the engine first checks whether that reference has already been enrolled. If it
has, the existing enrollment is treated as a definite match and the image is not enrolled a second time. This makes
enrollment safe to retry after a network blip without creating duplicate faces.
For a belt-and-braces retry flow, call
checkImageReference with your
photoReferenceId before re-sending. If it reports exists: true, the face is already enrolled and you can skip the
faceEnroll call entirely.
Quality Gate & forceEnrollment
By default, enrollment applies quality and similarity checks and rejects images that are too low-quality or too
similar to an existing enrollment. Set forceEnrollment: true to bypass that gate and enroll the image anyway.
forceEnrollment sparinglyThe gate exists to keep enrollment data clean. Force-enrolling low-quality or near-duplicate images degrades match accuracy over time. Reserve it for cases where you've already validated the image out-of-band.
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 face.jpg)
# Enroll a face - creates a NEW person and returns its personId.
# photoReferenceId is optional but makes retries idempotent (see checkImageReference).
curl -sk -X POST "$API_URL/api/v1/faces/faceEnroll" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"faceImage\": \"$IMG_B64\", \"photoReferenceId\": \"ext-123\"}" | jq
# Add a face to an EXISTING person instead (pass personId as a query parameter):
# POST "$API_URL/api/v1/faces/faceEnroll?personId=<personId>&forceEnrollment=false"
# Force enrollment past the quality/similarity gate (use sparingly):
# POST "$API_URL/api/v1/faces/faceEnroll?forceEnrollment=true"
$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("face.jpg"))
# Enroll a face - creates a NEW person and returns its personId.
$enroll = @{ faceImage = $imgB64; photoReferenceId = "ext-123" } | ConvertTo-Json
Invoke-RestMethod -Uri "$API_URL/api/v1/faces/faceEnroll" -Method Post `
-Headers $headers -Body $enroll -ContentType "application/json"
# Add to an existing person: append ?personId=<personId> to the URL.
# Force past the quality gate: append ?forceEnrollment=true (use sparingly).
using eConnect.IdentitiesDbSdk;
// NuGet: eConnect.IdentitiesDbSdk (private package - request access from eConnect support).
var httpClient = new HttpClient();
// GetSdk authenticates and keeps the JWT fresh for you.
var sdk = await IdentityDbSdk.GetSdk(
"https://customername.econnectcloud.com/identities",
httpClient,
"your_username",
"your_password");
byte[] image = await File.ReadAllBytesAsync("face.jpg");
// Enroll a face - omit personId to create a NEW person; returns its personId.
var enroll = await sdk.FaceEnrollAsync(body: new FaceEnrollRequest
{
FaceImage = image,
PhotoReferenceId = "ext-123" // optional - makes retries idempotent
});
Console.WriteLine($"Enrolled person: {enroll.PersonId}");
// Add a face to an EXISTING person (pass personId); forceEnrollment bypasses the quality gate.
// await sdk.FaceEnrollAsync(
// personId: existingId,
// forceEnrollment: false,
// body: new FaceEnrollRequest { FaceImage = image });
Raw Sample
Request
POST https://customername.econnectcloud.com/identities/api/v1/faces/faceEnroll
Authorization: Bearer <your_jwt_token>
Content-Type: application/json
{
"faceImage": "base64_encoded_face_image",
"photoReferenceId": "ext-123"
}
To attach to an existing person instead of creating one, add the query string:
POST .../api/v1/faces/faceEnroll?personId=0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d&forceEnrollment=false
Response
200 OK — a FaceEnrollResponse with the person the face was enrolled against:
{ "personId": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d" }
When no personId was supplied this is the newly created person; when one was supplied it echoes that same person.
Response Fields
| Field | Type | Description |
|---|---|---|
personId | string (GUID) | The person the face was enrolled against — newly created when no personId was supplied, otherwise the one you passed. |
Response Codes
| Code | Meaning |
|---|---|
200 OK | The face was enrolled; personId is returned. |
400 Bad Request | The request body is malformed or fails validation. |
401 Unauthorized | Missing or invalid JWT. |
403 Forbidden | The user lacks the Face Enrollment permission. |
404 Not Found | The supplied personId was not found. |
500 Internal Server Error | Enrollment failed — for example, no face could be detected in faceImage, or the image was otherwise rejected. |
Notes
- Omit
personIdto create a person from a face; supply it to add another photo to an existing person. - A new person created for an enrollment that then fails is rolled back automatically — no empty people.
- Supply a stable
photoReferenceIdto make retries idempotent, and check it up front withcheckImageReference. - Leave
forceEnrollment: falsein production so the quality/similarity gate can protect your enrollment data. - After enrolling, use Person Management to add names, tags, and fields.