Publish With Response
publishWithResponse submits a face image captured by an edge detector to the facial-recognition engine and
synchronously returns the faces it detected — each with a face ID, detection ID, bounding box, confidence, and quality
score. This is the endpoint to use when you need the detection result back in the same request (unlike the fire-and-forget
publish endpoint).
Optionally, set includePerson to have each matched face returned together with its
person record — name, tags, and attributes — in the same response, so you don't need a follow-up call.
The endpoint is built to answer fast: a quick face-presence check runs
before anything is published (an image with no detectable face returns immediately instead of waiting on the
recognition pipeline), and the whole call is bounded by a configurable timeoutMs
budget (default 5 seconds) so a slow pipeline fails fast rather than hanging your integration.
API Endpoint
- HTTP Method:
POST - Endpoint:
/api/v1/faceEdge/publishWithResponse - 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 Publishing | Facial Recognition Services |
Assign this permission to a Role, then assign the role to your integration User.
Request Body
Content-Type: application/json. Binary fields (e.g. expanded) are sent as base64-encoded strings.
Required Fields
| Field | Type | Description |
|---|---|---|
expanded | byte[] (base64) | The detected face image bytes captured by the edge detector. |
detectorName | string | Identifier of the detector/source that produced the image. |
ianaTimeZone | string | IANA time zone of the detection (e.g. America/Los_Angeles). |
detectTimeUtc | string (ISO-8601 UTC) | The UTC timestamp of the detection. |
Processing Options
| Field | Type | Default | Description |
|---|---|---|---|
largestFaceOnly | bool | false | If true, only the largest / most prominent face is returned. |
allowDoubleDetection | bool | false | If true, disables duplicate-detection prevention. Use sparingly to avoid spam. |
timeoutMs | int | 5000 | Fail-fast budget in milliseconds for the entire call (face-presence check + publish). Exceeding it returns 504 Gateway Timeout. Clamped to 250–30000; zero or negative values fall back to the default. See below. |
largestFaceOnly: true for most integrationsThis is the option you'll care about most. When an image contains more than one face, largestFaceOnly: true returns
only the dominant subject — which is almost always what an edge detector wants (the person at the door, the customer at
the counter). Leave it false only when you genuinely need every face in the frame.
Face-Presence Gate & Fail-Fast Timeout
publishWithResponse always runs a face-presence gate before anything is published:
- A single-pass face detection checks the submitted image.
- No face found → the endpoint responds immediately with
200 OKand an emptydetectedFacesarray, and nothing is published — the publish is gated on the photo actually containing a face, so no-face frames never enter the recognition pipeline or its storage. - Face(s) found → the image is published and the call waits for the recognition result.
The whole operation — gate plus publish — runs inside the timeoutMs budget (default 5000 ms). If the pipeline
cannot answer inside the budget, the call fails fast with 504 Gateway Timeout instead of blocking your
integration; the detection may still complete server-side, but no result is returned for that request.
timeoutMsThe default of 5000 ms suits interactive integrations (kiosks, door readers) that need an answer now. Raise it (up to 30000 ms) for batch-style callers that prefer completeness over latency; lower it (down to 250 ms minimum) if your integration would rather retry than wait.
Person Inclusion Options
By default the response contains only face-level detection data. Set includePerson: true to enrich every matched
face (a face linked to a known person) with a person object. The individual include* switches then 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 from person.personTags, 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 itself 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 Publishing permission required by the endpoint itself.
Code Examples
- Curl
- PowerShell
- C#
# Define variables
API_URL="https://customername.econnectcloud.com/identities"
TOKEN="your_jwt" # from POST /api/v1/authenticate
FACE_FILE="face.jpg" # the detected face image
# byte[] fields are sent as base64 strings in JSON. "expanded" is required.
EXPANDED_B64=$(base64 -w 0 "$FACE_FILE")
REQUEST=$(cat <<EOF
{
"expanded": "$EXPANDED_B64",
"detectorName": "FrontDoorCam",
"ianaTimeZone": "America/Los_Angeles",
"detectTimeUtc": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"largestFaceOnly": true,
"timeoutMs": 5000,
"includePerson": true,
"includeNames": true,
"includeTags": true,
"includeFields": true
}
EOF
)
curl -sk -X POST "$API_URL/api/v1/faceEdge/publishWithResponse" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$REQUEST" | jq
# Define variables
$API_URL = "https://customername.econnectcloud.com/identities"
$TOKEN = "your_jwt" # from POST /api/v1/authenticate
$FACE_FILE = "face.jpg" # the detected face image
# byte[] fields are sent as base64 strings in JSON. "expanded" is required.
$expandedBytes = [System.IO.File]::ReadAllBytes($FACE_FILE)
$expandedB64 = [Convert]::ToBase64String($expandedBytes)
$body = @{
expanded = $expandedB64
detectorName = "FrontDoorCam"
ianaTimeZone = "America/Los_Angeles"
detectTimeUtc = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
largestFaceOnly = $true
timeoutMs = 5000 # fail-fast budget in ms (default 5000, 504 when exceeded)
includePerson = $true
includeNames = $true
includeTags = $true
includeFields = $true
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "$API_URL/api/v1/faceEdge/publishWithResponse" `
-Method Post `
-Headers @{ Authorization = "Bearer $TOKEN" } `
-Body $body -ContentType "application/json"
$response.detectedFaces | ForEach-Object {
"$($_.faceId) -> $($_.person.aliases[0].firstName) $($_.person.aliases[0].lastName)"
}
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");
// The "expanded" image is the face captured by your edge detector.
byte[] faceBytes = await File.ReadAllBytesAsync("face.jpg");
var response = await sdk.FaceEdgePublishWithResponseAsync(new FaceEdgeRecognizeWithOptions
{
Expanded = faceBytes, // required - detected face image bytes
DetectorName = "FrontDoorCam", // required
IanaTimeZone = "America/Los_Angeles", // required
DetectTimeUtc = DateTime.UtcNow, // required
LargestFaceOnly = true, // recommended - return only the dominant face
TimeoutMs = 5000, // fail-fast budget in ms (default 5000, 504 when exceeded)
// Person enrichment - matched faces are returned with their person record.
IncludePerson = true,
IncludeNames = true,
IncludeTags = true,
IncludeFields = true
// IncludeAddresses = true, // also available
// CroppedAligned / Embeddings / RecognitionModel are eConnect-internal - leave unset.
});
foreach (var face in response.DetectedFaces)
{
Console.WriteLine($"FaceId={face.FaceId} quality={face.FaceQuality:P1}");
// person is populated only when IncludePerson was requested AND the face matched a person.
if (face.Person is not null)
{
var alias = face.Person.Aliases?.FirstOrDefault();
Console.WriteLine($" Person {face.Person.PersonId}: {alias?.FirstName} {alias?.LastName}");
}
}
Raw Sample
Request
POST https://customername.econnectcloud.com/identities/api/v1/faceEdge/publishWithResponse
Authorization: Bearer <your_jwt_token>
Content-Type: application/json
{
"expanded": "base64_encoded_face_image",
"detectorName": "FrontDoorCam",
"ianaTimeZone": "America/Los_Angeles",
"detectTimeUtc": "2026-06-16T18:32:05Z",
"largestFaceOnly": true,
"timeoutMs": 5000,
"includePerson": true,
"includeNames": true,
"includeTags": true,
"includeFields": true
}
Response
200 OK — a FaceEdgePublishResponse containing every detected face (an empty array if none were found). When
includePerson is requested, matched faces also carry a person object (which includes its own personId),
populated with the requested, permitted sections:
{
"detectedFaces": [
{
"faceId": "5f9c2b7a-3e41-4d8a-9b6c-1a2b3c4d5e6f",
"detectId": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"confidence": 0.987,
"faceQuality": 0.912,
"boundingBox": { "x": 320, "y": 145, "width": 96, "height": 96 },
"person": {
"personId": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"friendlyName": "Jane Doe",
"aliases": [
{ "firstName": "Jane", "lastName": "Doe", "middleName": null, "title": null }
],
"personTags": [
{ "tagId": "4c5d6e7f-8091-2345-6789-abcdef012345", "created": "2026-01-15T12:00:00Z", "expires": null, "tag": { "name": "VIP" } }
],
"entityFields": [
{ "name": "LoyaltyTier", "stringValue": "Gold", "dateValue": null, "numberValue": null, "boolValue": null }
]
}
}
]
}
When includePerson is omitted (the default), the person object is absent and the response is exactly the face-level
shape. Unknown (unmatched) faces are always returned without a person.
Response Fields
| Field | Type | Description |
|---|---|---|
detectedFaces[].faceId | string | Unique identifier of the detected face. |
detectedFaces[].detectId | string | Identifier of this detection event. |
detectedFaces[].confidence | float | Detection confidence, 0.0–1.0. |
detectedFaces[].faceQuality | float | Face quality score, 0.0–1.0. |
detectedFaces[].boundingBox | object | { x, y, width, height } pixel coordinates of the face. |
detectedFaces[].person | object | Person record (including personId). Present only with includePerson on a matched face; contains only the requested, permitted sections (aliases, addresses, personTags, entityFields, friendlyName). |
A person.personTags[] entry carries the tagId plus a slim tag object. To fetch full tag details (description,
default expiry), use the Tag Management endpoints.
Response Codes
| Code | Meaning |
|---|---|
200 OK | Detection ran; detectedFaces contains the results. Empty means the face-presence gate found no face (nothing was published). |
400 Bad Request | Invalid request — for example, expanded is missing ("Face bytes are empty"). |
401 Unauthorized | Missing or invalid JWT. |
403 Forbidden | The user lacks the Face Publishing permission. |
500 Internal Server Error | A server-side error occurred. |
504 Gateway Timeout | The recognition pipeline did not answer within the timeoutMs budget. Safe to retry. |
How includePerson Is Resolved
Notes
expandedis required — the call fails fast with400if it is empty.- An empty
detectedFacesarray comes back in well under a second — the face-presence gate short-circuits no-face images before they reach the recognition pipeline, and nothing is published for them. - The call is bounded by
timeoutMs(default 5000 ms). A504means the budget was exceeded — retry, or raise the budget if your integration can tolerate the wait. - Set
largestFaceOnly: truewhen you expect a single subject and want just the best face. - Leave
allowDoubleDetection: false(the default) in production so the same face isn't processed repeatedly. includePersonadds person data inline only for matched faces; unknown faces return face data only.- A requested
include*section the caller isn't permitted to see is omitted silently — it is not an error. - Disabled tags are excluded from
person.personTagsby default (excludeDisabledTags: true) so downstream systems never trigger off a disabled tag; setexcludeDisabledTags: falseto receive them. - For high-throughput feeds where you don't need the result, use
publishinstead.
Advanced
eConnect edge-model fields (leave unset)
The following request fields are highly proprietary and intended for eConnect's own edge models only. Partner integrations should not set them — leave them unset and let the platform handle recognition.
| Field | Type | Description |
|---|---|---|
croppedAligned | byte[] (base64) | eConnect models only. Do not set. |
embeddings | float[] | eConnect models only. Do not set. |
recognitionModel | string | eConnect models only. Do not set. |