> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# How voice biometrics verification works

> Voiceprint enrollment, the challenge phrase, the verify call's double gate, per-tenant thresholds, and how the biometric score feeds the composite risk verdict.

# Voice biometrics: enrollment, challenge, verify

Voice biometrics verifies a **person**, not a device or a code. An OTP session proves a recipient can read a message sent to a number; a voiceprint proves the person speaking *is* the enrolled contact. The capability pairs with the [verification session lifecycle](/concepts/verification-lifecycle) as a second factor, or stands alone for agent-assisted call verification.

Request and response shapes live in the [Voice Biometrics API reference](/api-reference/endpoints/voice-biometrics). This page explains the model behind it.

## What a voiceprint is

A voiceprint is a stored **speaker embedding** — a 192-dimensional vector produced by an ECAPA-TDNN speaker model — bound to one of your contacts. Enrollment flow:

1. You upload a short WAV clip (mono, up to 30 seconds) as base64 in `POST /api/v1/verify/voice-biometrics/enroll`, alongside the contact id and the consent text/version you captured. Biometric data requires explicit consent (GDPR Article 9); the consent string is stored with the record.
2. The clip is analyzed before anything is stored. Two scores come back: the embedding and an anti-spoof score (bonafide probability from an AASIST model — near 1 means a live human, near 0 means a played-back or synthesized recording).
3. If the clip is judged spoofed, enrollment is **refused** and nothing is written. If it passes, the embedding is encrypted at rest and stored against the contact, and you get back a `vp_`-prefixed voiceprint id.

Other properties you'll run into:

* **Tenant enrollment cap.** Each organization has a voiceprint quota; exceeding it returns `429 voiceprint_tenant_cap_exceeded`.
* **Rate limits.** Enrollment per contact is bounded per hour — enroll, don't script a thousand retries.
* **Erasure is real.** `DELETE /api/v1/verify/voice-biometrics/{voiceprintId}` permanently removes the voiceprint and its encrypted embedding (GDPR Article 17) — a hard delete, not a soft-delete flag. `GET /api/v1/verify/voice-biometrics/enroll/{id}` reports the enrollment status of a known id and returns 404 after erasure.
* **Metadata-only listing.** `GET /api/v1/verify/voice-biometrics/` lists voiceprints for your tenant — ids, contacts, timestamps — never embedding bytes.

## The challenge and the verify step

Verification has two gates, and both must pass.

**The challenge (replay resistance).** `POST /api/v1/verify/voice-biometrics/challenge` issues a per-attempt random phrase plus an opaque nonce id. Your caller reads the phrase aloud, records it, and your next `POST /api/v1/verify/voice-biometrics/verify` submits the audio **together with** the nonce id and phrase. The verify path consumes the nonce exactly once and rejects missing, expired, reused, or mismatched values — a recorded voice ripped from a previous call cannot satisfy a fresh phrase. Nonces expire after five minutes. The challenge is optional (older integrations keep working), but for anything fraud-sensitive you should use it.

**The verify gates.** `verify` compares the submitted clip against the contact's enrolled voiceprints:

1. **Cosine similarity.** The new clip's embedding is compared with the stored embeddings. This score must clear your **confidence threshold**.
2. **Anti-spoof.** The clip must independently pass the anti-spoof check. A perfect voice match on a played-back recording still fails.

The verdict is therefore *match AND live*, never just match.

## Tenant thresholds and the overview

Voice biometrics is **tenant-scoped and tunable** — the platform ships a default; the verdict is yours:

* `PATCH /api/v1/verify/voice-biometrics/settings` sets your `confidence_threshold` (0.50 most permissive → 0.95 most strict) on the cosine-similarity gate, and the `auto_2fa_on_low_confidence` flag — when enabled, a below-threshold result signals step-up to a second factor instead of a hard failure.
* `GET /api/v1/verify/voice-biometrics/overview` is the health view: enrolled voiceprint count, recent verification events, the 7-day **false-accept-rate trend**, and your current threshold settings. Watch the false-accept trend after loosening the threshold — that is the dial that tells you whether permissive became sloppy.

These controls are tenant-owned. There is no platform-wide "correct" threshold; a banking line and a loyalty hotline legitimately sit at different points on the range.

## How the score composes with the risk surface

The composite fraud/risk verdict treats voice biometrics as an **optional pass-through**. When you run a voice check yourself — in an IVR, with an agent, in your own flow — you can feed the outcome into the pre-send risk score as the `voice_biometrics_signal` field, alongside `verify_signal` from Verify Fraud Guard. The composite takes the **worst** present channel score, so a failed biometric check cannot be washed out by an otherwise-clean aggregate. See the [Risk API reference](/api-reference/endpoints/risk) for the scoring bands.

## The auth model

The public API endpoints above authenticate like every other Orbit API call (your API key). Behind them, the inference sidecar speaks a separate, internal-only protocol: HMAC-SHA256 request signatures on an `X-Voice-Biometrics-Sig` header (`t=<unix_seconds>,v1=<hex>`) with a ±60-second replay window. Raw audio never crosses an unsigned boundary, and the signature covers the request body — you cannot replay yesterday's clip against today's endpoint.

## Where the guides link in

* [Verify overview](/verify/overview) — the OTP pillar voice biometrics complements.
* [Verify profiles and fallback chains](/guides/verify-fallback-chains) — channel ordering for OTP; `auto_2fa_on_low_confidence` is the bridge from a weak biometric verdict into these step-up flows.
* [Voice Biometrics API reference](/api-reference/endpoints/voice-biometrics) — every endpoint listed above.
* [Risk API reference](/api-reference/endpoints/risk) — how `voice_biometrics_signal` folds into the composite verdict.

## What this is not

* **Not the CAMARA network signals.** SIM-swap and carrier-side signals come from the network operator; a voiceprint comes from the caller's speech. Both can gate a flow, but they are different evidence types.
* **Not the composite risk score itself.** Voice biometrics produces a verdict per verify call; the risk engine fuses that verdict with other signals only if you pass it through as `voice_biometrics_signal`.
* **Not an OTP code.** There is nothing to intercept or forward — enrollment and verification need an actual human speaking. The challenge phrase exists precisely to keep it that way.
