Skip to content

API v1 (deprecated)

v1 and v2 run side by side against the same projects, API tokens, consents, sessions and dashboards. You can move one call at a time — there is no cut-over and no data migration on your side.

1. Choose the identity value

v1 keys an end-user by X-User-Fullname. v2 uses user_id in the request body. Both resolve to the same identity record, so whatever string you send today as X-User-Fullname is the value to send as user_id — enrollments, consents and history carry over untouched.

If you have been sending real names, this is the moment to switch to an opaque ID. Note that changing the value creates a new identity: the user will need to re-enroll and re-consent under the new ID, so migrate the value deliberately (and only if you can re-onboard).

user_id must match ^[A-Za-z0-9._:@-]{1,128}$. A name containing spaces is rejected with 400 invalid_request.

2. Map the endpoints

v1v2Notes
POST /enroll/facePOST /v2/enrollments/faceFile part renamed to face
POST /enroll/voicePOST /v2/enrollments/voiceFile part renamed to voice; phrase moves into request
POST /process-videoPOST /v2/livenessAnti-spoofing only — see step 4
POST /v2/face-verifyFace identity check, split out of process-video
POST /v2/voice-verifyVoice identity check, split out of process-video
POST /match-facesPOST /v2/face-matchimage file part renamed to reference_image
POST /docauth/checkPOST /v2/documents/check
POST /avf/inferPOST /v2/deepfake/checksReturns 201; poll instead of streaming
GET /avf/status/{id}GET /v2/deepfake/checks/{id}Plain JSON read; the v1 SSE stream still exists
POST /sessions/startPOST /v2/sessions
POST /sessions/end/{id}POST /v2/sessions/{id}/end
POST /images / GET /images/{email}PUT / GET /v2/users/{user_id}/reference-imageKeyed by user_id, not email
POST /users/delete/cascadingDELETE /v2/users/{user_id}Console session required, as in v1
GET /v2/users/{user_id}New: enrollment state for a user
/scores/*/v2/scoring-systems/*Console session; managed from the dashboard
/custom-consents/*/v2/consents/*Same semantics
/webhooks/*/v2/webhooks/*Console session, as in v1

/api-consent/*, /api-transactions/*, /api-projects/public/apikeys and the warmup endpoints are unversioned and unchanged — keep calling them as you do today.

3. Move headers into the body

Everything that was an X-* business header is now a field in the JSON request part. The old headers are stripped on v2 routes — sending them has no effect.

v1 headerv2 field
X-User-Fullnamerequest.user_id
X-Session-IDrequest.session_id
X-Action-Triggerrequest.trigger
X-Use-Prefilled-Videorequest.use_session_video (boolean, /v2/face-match only)
X-Inhouse-Docauthrequest.provider: inhouse | idscan
X-Inhouse-MRZrequest.mrz_provider: inhouse | idscan
phrase, vocabulary form fieldsrequest.phrase, request.vocabulary

Authorization, X-Request-Id, X-Client-App, X-Client-Version, X-App-Version, X-Device-Info and X-Geo-Location stay headers.

New in v2: request.services.exclude lets a call skip services that are enabled on the token — e.g. {"services": {"exclude": ["visual_speech_recognition"]}} on /v2/liveness. v1 had no request-side equivalent. (The X-Removed-Services response header is unchanged: it still tells you that consent-gated services were dropped from the call.)

Before (v1):

curl 'https://api.biometrysolutions.com/api-gateway/process-video' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--header 'X-User-Fullname: 8f14e45f' \
--header 'X-Session-ID: 0f9c2a1e' \
--form '[email protected]' \
--form 'phrase=one two three four five six'

After (v2):

curl 'https://api.biometrysolutions.com/api-gateway/v2/liveness' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--form 'request={"user_id":"8f14e45f","session_id":"0f9c2a1e","phrase":"one two three four five six"};type=application/json' \

4. Split one process-video call into several

This is the only behavioural change, and it is deliberate. In v1, one /process-video call ran every service enabled on your token — anti-spoofing and identity — and returned one blended verdict.

In v2:

  • POST /v2/liveness runs Face Liveness Detection, Active Speaker Detection and Visual Speech Recognition.
  • POST /v2/face-verify runs Face Recognition against the enrolled template.
  • POST /v2/voice-verify runs Voice Recognition against the enrolled template.

Each call returns its own decision. If your v1 integration relied on the single blended scoring_result, you now compose the per-call decisions yourself — ending a session does not currently produce a combined verdict.

Pass the same session_id to all of them so the Console still shows one attempt, and use use_session_video on /v2/face-match to avoid re-uploading the video.

5. Update response parsing

v1v2
data["Face Liveness Detection"]data.face_liveness_detection
data["Active Speaker Detection"]data.active_speaker_detection
data["Visual Speech Recognition"]data.visual_speech_recognition
data["Face Recognition"]data.face_recognition
data["Voice Recognition"]data.voice_recognition
scoring_result (string or object)decision.status
scoredecision.score
decision_reasonsdecision.reasons
messagemeta.message
{"error": "text"}{"error": {"code": "…", "message": "…"}, "meta": {"request_id": "…"}}

Scores keep the 0–100 scale and the per-service payloads (code, description, result, score) are unchanged — only the keys and the wrapper move. See the Error catalog for the new codes.

6. What is not in v2 yet

  • No combined session decision. POST /v2/sessions/{id}/end closes the session; it does not score the calls made inside it.
  • use_session_video is honoured only by /v2/face-match. Liveness and the verify endpoints still take an uploaded file.
  • No per-modality unenroll. Removing a single face or voice template means deleting the whole user.

Keep using the v1 endpoint where one of these matters to you; v1 is not going away without an announced deprecation window, Deprecation/Sunset headers and notice on this portal.

Scoring systems

Scoring configuration moved under /v2/scoring-systems with versioned reads.

Operationv1v2
ListGET /api-gateway/scoresGET /api-gateway/v2/scoring-systems
CreatePOST /api-gateway/scoresPOST /api-gateway/v2/scoring-systems
ReadGET /api-gateway/scores/{id}GET /api-gateway/v2/scoring-systems/{id}
UpdatePATCH /api-gateway/scores/{id}PATCH /api-gateway/v2/scoring-systems/{id}
DeleteDELETE /api-gateway/scores/{id}DELETE /api-gateway/v2/scoring-systems/{id}
Read a past versionGET /api-gateway/scores/{id}/{version}GET /api-gateway/v2/scoring-systems/{id}/versions/{version}
Project defaultGET /api-gateway/scores/defaultGET /api-gateway/v2/scoring-systems/default
Create from a presetPOST /api-gateway/scores/default/{project_id}POST /api-gateway/v2/scoring-systems/presets/default
Dry-run against a payloadPOST /api-gateway/scores/test/{scores_id}POST /api-gateway/v2/scoring-systems/{id}/test