# Enroll an identity

`POST /functions/v1/process-biovital-enrollment`

One call creates an identity from a live capture. The account is born with face and voice; the document is not part of enrollment.

Browser-safe: a publishable `pk_` key is correct here, because the capture happens on the person's own device.

## Body

| Field | Type | Notes |
| --- | --- | --- |
| action | ACTION_GENESIS | required |
| merchant_id | string | required |
| sieve_hash | string | required |
| consent | object | { version, locale, accepted_at } — mandatory; there is no bypass flag |
| device_signature | string | required |
| client_instance_id | string | required |
| device_label | string | What the person will recognise in her device list |
| face_template | object | { vector: exactly 128 numbers, quality } |
| biometric_vitals | object | { bpm, hrv, stress_score, voice_pulse_correlation, liveness_confidence, liveness_proof } |

## Response

```
{
  "success": true,
  "status": "enrolled",
  "subject_ref": "sr_2f91c8de44",
  "session_token_hash": "e91c...",
  "consent": { "version": "2026-06", "retention_days": 3650 }
}
```

`subject_ref` is `HMAC(sieve_id, merchant_id)` — a per-merchant pseudonym, never the real identifier.

## Two facts to build on

- The account is born with **face and voice**. The document is not part of enrollment — it is asked for at the first operation that requires it, see [the document rule](/document).
- `user_id` is minted by the engine — a surface never supplies, chooses or guesses one. An alias is only a public handle attached to that identity, see [alias](/alias).

## Sessions

The identity session lives in the storage of the domain that ran the capture. Sessions do not cross domains, and there is no separate “create an iframe session” call.

## Errors

| Status | Code |
| --- | --- |
| 400 | INVALID_INPUT (carries fields) |
| 403 | CONSENT_REQUIRED, BIOMETRIC_LIVENESS_FAILED |
| 409 | SESSION_PRESENT, IDENTITY_UNREACHABLE |
| 422 | FACE_TEMPLATE_REQUIRED |
| 500 | IDENTITY_CREATE_FAILED, TEMPLATE_STORE_FAILED, SESSION_MINT_FAILED |
