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

# Biometric Templates

> Manage the image-free face biometric templates your application retains after session deletion: list, count, filter, inspect, and purge them via the API.

export const AgentPromptAccordion = ({prompt, title = "AI Agent Integration Prompt"}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = e => {
    e.stopPropagation();
    if (!prompt) return;
    navigator.clipboard.writeText(prompt.trim()).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };
  const agents = ["Claude Code", "Codex", "Cursor", "Devin", "Windsurf", "GitHub Copilot"];
  return <div className="didit-agent-card">
      {}
      <div className="didit-agent-titlebar">
        <div className="didit-agent-dots" aria-hidden="true">
          <span className="didit-agent-dot didit-agent-dot-red"></span>
          <span className="didit-agent-dot didit-agent-dot-yellow"></span>
          <span className="didit-agent-dot didit-agent-dot-green"></span>
        </div>
        <span className="didit-agent-filename">{title}</span>
        <button type="button" className={`didit-agent-copy ${copied ? "didit-agent-copy-copied" : ""}`} onClick={handleCopy} title="Copy prompt to clipboard" aria-label={copied ? "Copied!" : "Copy prompt to clipboard"}>
          {copied ? <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Copied</span>
            </> : <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
                <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
              </svg>
              <span>Copy</span>
            </>}
        </button>
      </div>

      {}
      <pre className="didit-agent-body"><code>{prompt.trim()}</code></pre>

      {}
      <div className="didit-agent-footer">
        <span className="didit-agent-footer-label">Paste into</span>
        <div className="didit-agent-chips">
          {agents.map(name => <span key={name} className="didit-agent-chip">{name}</span>)}
        </div>
      </div>
    </div>;
};

<AgentPromptAccordion
  title="Biometric Templates API Prompt"
  prompt={`Manage the biometric templates my Didit application retains after deleting verification sessions.

What a biometric template is:
When an application opts in (face_retention_policy: "retain_until_user_deleted", or retain_face_embeddings: true on a delete call), deleting a KYC session deletes the session and all of its data but keeps ONE image-free face biometric template anchored to the session's User. The template keeps duplicate-face, multi-account, biometric-authentication, and list matching working for that person. It contains the numeric face template plus retention metadata only — never the face image, liveness video, document data, extracted identity fields, the decision, or the deleted session's id. It is biometric data: not anonymous, not transient, and not deleted with the session. It has a finite expires_at.

Endpoints (base https://verification.didit.me, header x-api-key: YOUR_API_KEY; API keys only — Console user tokens get 403):
- GET  /v3/biometric-templates/            — paginated list (limit/offset). Filters: vendor_data (substring, case-insensitive), vendor_user_uuid, status, source_type, retained_from, retained_to (ISO 8601), ordering (retained_at | -retained_at | expires_at | -expires_at; default -retained_at). Purged templates are not listed.
- GET  /v3/biometric-templates/count/      — {"count": n} with the same filters.
- GET  /v3/biometric-templates/{uuid}/     — one template.
- DELETE /v3/biometric-templates/{uuid}/   — purge one template. 200 {"uuid": "...", "outcome": "purged" | "already_purged"}.
- POST /v3/biometric-templates/delete/     — bulk purge. Body: {"template_uuids": ["..."]} OR {"delete_all": true} plus optional filters (vendor_data, vendor_user_uuid, status, source_type, retained_from, retained_to) that narrow delete_all. 200 {"results": [{"uuid": "...", "outcome": "purged" | "already_purged"}]}.

Template object:
{
"uuid": "<template id>",
"vendor_user_uuid": "<User id>",
"vendor_data": "<the User's current vendor_data, resolved live>",
"source_type": "session_delete" | "automatic_retention" | "backfill",
"provenance_reference": "<opaque UUID, not the deleted session id>",
"retention_policy": "delete_with_session" | "retain_until_user_deleted",
"retention_override": true | false | null,
"retained_at": "<ISO 8601>",
"expires_at": "<ISO 8601>",
"retained_by": "<principal id: application UUID for API keys, Console member id, or service:...>",
"retained_by_type": "API_KEY" | "CONSOLE_USER" | "SYSTEM",
"instruction_class": "operational_session_delete" | "privacy_erasure",
"instruction_source": "api" | "console" | "automatic_retention" | "backfill" | "privacy_erasure" | "explicit_template_purge" | "vendor_user_delete" | "expiry" | "reconciliation" | "migration" | "system",
"instruction_id": "<your instruction_id or a Didit-generated one>",
"held_out_of_use": false,
"status": "pending" | "active" | "expired" | "held_out_of_use" | "purge_pending" | "purge_failed" | "purged",
"purged_at": null | "<ISO 8601>"
}
Only status "active" templates that are not held_out_of_use, not past expires_at, and whose User still exists take part in matching.

Purge points (all remove the template from matching and delete the stored template):
- DELETE /v3/biometric-templates/{uuid}/ or POST /v3/biometric-templates/delete/
- POST /v3/users/delete/ for the owning User
- any session deletion for that User sent with deletion_instruction: "privacy_erasure"
- automatic expiry at expires_at
Switching the application policy back to delete_with_session does NOT purge existing templates — purge them explicitly.

Failure modes:
- 400 — {"template_uuids": ["This field is required unless delete_all is true."]} on bulk purge without a selector; invalid filter values.
- 403 — {"detail": "You do not have permission to perform this action."} (Console user token, or key not allowed).
- 404 — {"detail": "Biometric template not found."} on GET of an unknown or purged template.
- 503 — {"detail": "The biometric-template operation could not finish because an external store is unavailable. The operation is retryable."} The template moves to status purge_failed and is already excluded from matching; repeat the purge.

Every retain and purge attempt, including failures, is recorded on Didit's audit trail with the acting principal, instruction class, instruction_source, instruction_id, and outcome.

For end-to-end Didit integration, paste in the full prompt at /integration/integration-prompt.`}
/>

By default, deleting a verification session also deletes the face embedding that powered [Face Search 1:N](/core-technology/face-search/overview) and duplicate detection for that session. Applications that need duplicate detection to keep working after session deletion can opt in to **biometric-template retention**. Didit then deletes the session and all of its data as usual and keeps one separately managed, image-free face biometric template anchored to the session's [User](/entities/users/overview).

The Biometric Templates API lets you see exactly which templates your application holds, why, until when, and purge them at any time. Every template is also visible in the Business Console under **Lists → Biometric templates** and on the owning User's profile.

<Warning>
  A retained biometric template is biometric data. It is not anonymous, it is not transient, and it is not deleted with the session. It stays until its scheduled expiry, an earlier applicable-law deadline, User deletion, a privacy-erasure request, or an explicit purge. Enable retention only when your controller instruction and privacy notice cover it.
</Warning>

## How a template is created

| Trigger                                                                                                                                                                                                     | `source_type`         | Where the instruction comes from          |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------------------------- |
| You delete a session on an opted-in application, or send `retain_face_embeddings: true` on [Delete Session](/sessions-api/delete-session) or [Batch Delete Sessions](/management-api/sessions/batch-delete) | `session_delete`      | `instruction_source: api` or `console`    |
| Your application's general [data-retention window](/console/data-retention) expires a session on an opted-in application                                                                                    | `automatic_retention` | `instruction_source: automatic_retention` |
| A Didit-operated backfill you instructed for sessions deleted before you opted in                                                                                                                           | `backfill`            | `instruction_source: backfill`            |

Retention requires a User anchor. A session created without `vendor_data` has no User, so it cannot retain a template; the deletion reports `ineligible_no_vendor_user` and the embedding is deleted with the session.

## What a template contains

| Retained                                                                                                                                                              | Never retained                                                                             |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| The numeric face template used for matching                                                                                                                           | The face image, liveness video, document images, portrait crops, and any other media       |
| A new random template `uuid` and an opaque `provenance_reference`                                                                                                     | The deleted session's id, number, decision, extracted identity fields, or feature payloads |
| The owning User (`vendor_user_uuid`); `vendor_data` is resolved from the User when you read the template, never copied                                                | Blocklist state, prior matches, fraud labels, or cross-organization identity claims        |
| `retained_at`, `expires_at`, `retention_policy`, `retention_override`, `instruction_class`, `instruction_source`, `instruction_id`, `retained_by`, `retained_by_type` | Actor email addresses                                                                      |

Templates are tenant-scoped and used only on your instruction inside your application: duplicate-face and multi-account detection, [Biometric Authentication](/core-technology/biometric-auth/overview), and your own face lists. They are never used for model training, analytics, cross-organization matching, [Networks](/console/networks) shared signals, or Didit's independent fraud processing.

## Template object

```json theme={null}
{
  "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
  "vendor_user_uuid": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f",
  "vendor_data": "user-42",
  "source_type": "session_delete",
  "provenance_reference": "6b1e8d2f-4a3c-4f9e-8c7d-1a2b3c4d5e6f",
  "retention_policy": "retain_until_user_deleted",
  "retention_override": null,
  "retained_at": "2026-08-28T10:15:42.318402Z",
  "expires_at": "2027-08-28T10:15:42.318402Z",
  "retained_by": "3c9e2b1f-7d4a-4e8b-9c1d-5f6a7b8c9d0e",
  "retained_by_type": "API_KEY",
  "instruction_class": "operational_session_delete",
  "instruction_source": "api",
  "instruction_id": "post-approval-cleanup-2026-08",
  "held_out_of_use": false,
  "status": "active",
  "purged_at": null
}
```

| Field                  | Type             | Description                                                                                                                                                                                  |
| ---------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uuid`                 | UUID             | Template id. Randomly generated; not derived from the deleted session or its face.                                                                                                           |
| `vendor_user_uuid`     | UUID             | The owning User.                                                                                                                                                                             |
| `vendor_data`          | string or null   | The User's current `vendor_data`, resolved when you read the template.                                                                                                                       |
| `source_type`          | enum             | `session_delete`, `automatic_retention`, or `backfill`.                                                                                                                                      |
| `provenance_reference` | UUID             | Opaque reference that ties the template to its audit trail. It is not the deleted session's id and cannot be resolved to it through the API.                                                 |
| `retention_policy`     | enum             | The application policy at retention time: `delete_with_session` or `retain_until_user_deleted`.                                                                                              |
| `retention_override`   | boolean or null  | The `retain_face_embeddings` value sent on the deletion, or `null` when the policy applied.                                                                                                  |
| `retained_at`          | datetime         | When the template was created.                                                                                                                                                               |
| `expires_at`           | datetime         | When the template expires and is purged automatically. Always set.                                                                                                                           |
| `retained_by`          | string           | Principal that gave the instruction: the application id for API keys, the Console member id for Console actions, or a `service:` identifier for automatic retention. Never an email address. |
| `retained_by_type`     | enum             | `API_KEY`, `CONSOLE_USER`, or `SYSTEM`.                                                                                                                                                      |
| `instruction_class`    | enum             | `operational_session_delete` or `privacy_erasure`.                                                                                                                                           |
| `instruction_source`   | enum             | `api`, `console`, `automatic_retention`, `backfill`, `privacy_erasure`, `explicit_template_purge`, `vendor_user_delete`, `expiry`, `reconciliation`, `migration`, or `system`.               |
| `instruction_id`       | string           | The `instruction_id` you sent on the deletion, or a Didit-generated id when you omitted it.                                                                                                  |
| `held_out_of_use`      | boolean          | `true` only while a legal hold applies. A held template is excluded from all matching. See [Legal holds](#legal-holds).                                                                      |
| `status`               | enum             | Lifecycle status, see below.                                                                                                                                                                 |
| `purged_at`            | datetime or null | When the template was purged.                                                                                                                                                                |

### Status

| `status`          | Meaning                                                                                                                                          | In matching?                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| `pending`         | The template is being created. If the deletion that created it returned `503`, repeat the deletion to finish it.                                 | No                                                                 |
| `active`          | The template takes part in matching until `expires_at`.                                                                                          | Yes, unless `held_out_of_use` is `true` or `expires_at` has passed |
| `expired`         | `expires_at` has passed and the automatic purge is in progress.                                                                                  | No                                                                 |
| `held_out_of_use` | A legal hold applies.                                                                                                                            | No                                                                 |
| `purge_pending`   | A purge is in progress.                                                                                                                          | No                                                                 |
| `purge_failed`    | A purge could not finish because a biometric store was unavailable. Repeat the purge; the template stays excluded from matching in the meantime. | No                                                                 |
| `purged`          | The template is deleted. Only visible on the purge response as `already_purged`; purged templates are not listed and return `404` on detail.     | No                                                                 |

## How templates are used in matching

An `active` template takes part in exactly the same matching as a live session face: automatic duplicate detection during new sessions, the standalone [Face Search API](/standalone-apis/face-search), [Biometric Authentication](/core-technology/biometric-auth/overview), and your face lists. A hit on a retained template is reported with `source: "retained_template"`, the owning User's `vendor_user_id` and `vendor_data`, and the `biometric_template_id`. It never carries a session id, a match image, identity details, or a status, because the session that produced the face no longer exists. See [Face Search report](/core-technology/face-search/report-face-search).

A retained template is never blocklisted. If the deleted session's face was on a face blocklist, that blocklist entry keeps its own independent biometric entry and its own lifecycle: removing the list entry deletes the blocklist entry, and purging the template does not touch the list.

## Purge points

All of the following remove the template from matching and delete the stored template:

| Purge point     | How                                                                                                                                                                                                                                   |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Explicit purge  | [`DELETE /v3/biometric-templates/{uuid}/`](/management-api/biometric-templates/purge) or [`POST /v3/biometric-templates/delete/`](/management-api/biometric-templates/batch-purge), or **Lists → Biometric templates** in the Console |
| User deletion   | [`POST /v3/users/delete/`](/management-api/users/delete) purges every template anchored to the User before the User is deleted                                                                                                        |
| Privacy erasure | Any deletion of a session of that User sent with `deletion_instruction: "privacy_erasure"` purges every template anchored to the User, regardless of the application policy                                                           |
| Expiry          | Didit purges the template automatically once `expires_at` passes                                                                                                                                                                      |

Switching the application policy back to `delete_with_session` stops new templates from being created but does **not** purge existing ones. Purge them explicitly.

Purges delete the stored template first and only then mark the template purged, so a purge that returns `503` leaves the template in `purge_failed`, already excluded from matching, and safe to repeat. A repeated purge of an already purged template returns `already_purged`.

## Audit trail

Every retain and purge attempt, including failures and ineligible outcomes, is recorded with the acting principal (`retained_by` / purging principal and type), `instruction_class`, `instruction_source`, `instruction_id`, `provenance_reference`, and the outcome. Send your own `instruction_id` on deletions so you can correlate Didit's audit trail with your erasure log. Audit entries never contain images, vectors, identity fields, or email addresses.

## Legal holds

A legal hold is an exception, never a retention mode. Didit does not place holds on its own initiative; a hold can only follow a documented instruction under your Data Processing Agreement or a binding order from a competent authority. While a hold applies the template is marked `held_out_of_use`: it is excluded from every kind of matching and from routine recovery, and it is never searchable. There is no API to create or lift holds. Contact your Didit representative if you receive an order that affects retained templates.

## Permissions and authentication

The Biometric Templates endpoints accept application API keys only (`x-api-key`). Business Console user tokens are rejected with `403`. Console users manage templates through **Lists → Biometric templates** with their `lists` permissions.

## Endpoints

| Endpoint                                                                                | Method | Purpose                       |
| --------------------------------------------------------------------------------------- | ------ | ----------------------------- |
| [`/v3/biometric-templates/`](/management-api/biometric-templates/list)                  | GET    | Paginated list with filters   |
| [`/v3/biometric-templates/count/`](/management-api/biometric-templates/count)           | GET    | Count with the same filters   |
| [`/v3/biometric-templates/{template_uuid}/`](/management-api/biometric-templates/get)   | GET    | One template                  |
| [`/v3/biometric-templates/{template_uuid}/`](/management-api/biometric-templates/purge) | DELETE | Purge one template            |
| [`/v3/biometric-templates/delete/`](/management-api/biometric-templates/batch-purge)    | POST   | Purge by id list or by filter |

## Related

* [Delete Session](/sessions-api/delete-session)
* [Batch Delete Sessions](/management-api/sessions/batch-delete)
* [Data retention](/console/data-retention#biometric-template-retention)
* [Faces and biometrics](/entities/users/faces-and-biometrics)
