POST /identify

Operator bearer token required. multipart/form-data.
string
required
Must be the literal string "true". Missing or "false" is rejected before any dependency is called — the cheapest possible failure path.
file
required
The probe face — no customer identifier of any kind.
Runs a genuine 1:N nearest-neighbor search over the full enrolled population via the HNSW vector index (searchNearest) — not a loop of 1:1 comparisons. Every call is logged to SearchLog regardless of outcome, with a latencyMs breakdown per stage (liveness, embed, search).

POST /identify/{referenceId}/escalate

Operator bearer token required.
200 OK
Sets escalatedAt on the SearchLog row — a real, logged state, not just “the operator tried again.”

POST /verify/self

Consumer bearer token required. multipart/form-data, field image. Scoped to the caller’s own record — a single lookup against their own canonical embedding, not a database-wide search, so it stays responsive even under heavy /identify load.
200 OK — match
200 OK — no match
proofToken is only present on match — short-lived (PROOF_TOKEN_TTL_SECONDS, default 120s), single-use, and required to gate PATCH/DELETE /users/{id} (see Profile).
A high-confidence match also upserts the canonical embedding with this newer capture (the freshness rule from Epic 3, story 15) — the searchable record always reflects the most recent proven appearance, not whichever image was captured first.