Skip to content

Restricted pilot. The API reference is generated from the running API. Successful matches return manual_review until attack detection is validated.

Verify an identity

Verification runs quality checks, PAD and 1:1 matching on a session's frames and returns one decision.

POST/v1/identities/{identity_id}/verify

Send capture_session_id as a form field. A trusted backend may also send the frames here as frames instead of having the app upload them.

response
{
  "id": "ver_01m...",
  "object": "verification",
  "identity_id": "idn_01m...",
  "capture_session_id": "cap_01m...",
  "environment": "live",
  "decision": "manual_review",
  "reason": "restricted_mode",
  "retry_allowed": false,
  "guidance": null,
  "policy": "restricted_pilot",
  "restricted_mode": true,
  "identity": {
    "match": true,
    "similarity": 0.71,
    "threshold": 0.363,
    "score_semantics": "Cosine similarity between embeddings. Not a probability."
  },
  "pad": {
    "status": "passed",
    "score": 0.93,
    "score_semantics": "Raw model output used for screening. Not a probability that the person is real."
  },
  "timings_ms": { "total_ms": 180.4 },
  "model_versions": { "release": "2026-10-pilot-1" },
  "request_id": "req_01m...",
  "created_at": "2026-10-30T10:01:12Z"
}

Bad captures are normal outcomes and return HTTP 200 with a decision. So do expired sessions. Treat non-2xx responses as failures of the request itself.

identity.match answers one question: did the face match? It is true, false, or null when the score is too close to call or wasn't produced. It says nothing about whether the capture was genuine, so read decision and reason first.

Reading results later

GET/v1/verifications/{verification_id}
GET/v1/verifications