biofrq.enroll
Create a subject with one face template attached. A subject
is unique per (tenantId, externalId) and belongs to one or more
groups. Once enrolled, the subject can be matched by identify
and verify.
Params
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
images[0] | ImageItem | yes | — | Must contain exactly one face. See Envelope → Image inputs. |
externalId | string | yes | — | Your stable ID for the person (employee number, customer id). Unique per tenant — the join key in your system. |
groupNames | string[] | yes (or groupName) | — | 1..30 entries, 1..120 chars each. |
groupName | string | legacy | — | Deprecated one-element alias for groupNames. Don't send both — it's INVALID_REQUEST. |
displayName | string | no | — | Human-readable label for dashboards. |
attributes | object | no | {} | Free-form JSONB. Searchable via identify.predicate.attributesContains. |
mode | "create" | "addReference" | no | "create" | "addReference" attaches another template to an existing subject. |
matchThreshold | float | no | tenant default | Dedup gate — see callout. |
forceEnroll | bool | no | false | Skip the dedup gate. |
Request
json
{
"action": "biofrq.enroll",
"params": {
"images": [
{ "kind": "image", "bytes": "<base64>", "contentType": "image/jpeg" }
],
"externalId": "emp-4421",
"groupNames": ["Staff", "VIP"],
"displayName": "Asha Rao",
"attributes": { "department": "ops" },
"mode": "create"
}
}
Response
The per-action payload lives at data.results[0].value:
json
{
"subject": {
"tenantId": "...",
"subjectId": "8a1c...",
"externalId": "emp-4421",
"groups": ["Staff", "VIP"],
"groupName": "Staff"
},
"reference": {
"templateId": "...",
"vectorId": "...",
"subjectId": "8a1c...",
"embeddingProvider": "SFace",
"embeddingModelVersion": "2021",
"embeddingDimension": 128,
"qualityScore": 0.81
}
}
subject.groupName is a legacy alias for groups[0] kept for one
customer-release cycle. New clients should read groups.
Common errors
INVALID_REQUEST— zero or > 1 face in the image; missingexternalId; missing bothgroupNamesandgroupName; both group fields provided;groupNamesempty or > 30;modenot"create"/"addReference".CONFLICT(externalId taken) — a subject with the sameexternalIdalready exists in the tenant. Message:Subject already exists: tenant=... externalId='...'.CONFLICT(dedup gate) — the probe face matched an existing subject in the gallery with cosine score abovematchThreshold. Bypass withforceEnroll: true.