Face Authentication
Authenticate
Checks a captured selfie against the customer’s registered face and returns a match verdict with a confidence score.
Request
Clients can provide image data to the TrustVision API by specifying the ID the image by using upload API, or by sending the image data as base64-encoded text.
| Name | Type | Required | Description |
|---|---|---|---|
cus_user_id | string | Required | User id of customer (max 256) |
faces | []image | Required | Images of the selfie (max 50). Any flash mode (flash, flash_8, flash_16, flash_32, flash_edge, flash_advanced) and passive_v2 need multiple images covering the captured frames — a single still image gives the model nothing to score. |
gesture_faces | []gesture_image | Optional | Array of gestures contain images (max 50) |
videos | []video | Optional | Array of videos selfie (max 50) |
gesture_videos | []gesture_video | Optional | Array of videos gesture (max 50) |
device_id | string | Optional | Device id of user (max 256) |
app_id | string | Optional | App id of customer (max 128) |
lat | float | Optional | Latitude of device |
lng | float | Optional | Longitude of device |
auth_type | string | Optional | Specify different authentication type (or different use-cases) (max 64). Selects the backend cluster setting for this request — controls which checks run (liveness, portrait sanity, face compare). Left unset, the full default FA pipeline runs every check. |
client_transaction_id | string | Optional | Client transaction ID |
selfie_type | string | Optional | Specify the characteristic of authentication type eg. Light, Standard, Edge, Advanced (max 64). Must be set explicitly to match the captured data — sending multiple faces images without setting this to the matching flash value (or passive_v2) means that liveness model never runs against them. |
history_return_count | int | Optional | Number of history authenticate records to return |
history_return_status | string | Optional | Status of history authenticate records to return (success, failure or all) |
metadata | json_object | Optional | Any key-value metadata to store with this login time |
- For parameter type
image, if you useid(resultidis returned from Upload Image API), omit parameterbase64,labelandmetadata. If you usebase64,labelandmetadata, omit parameterid. - For parameter type
video, if you useid(resultidis returned from Upload File API), omit parameterframes,metadata. If you useframes,metadata, omit parameterid.
The
image,gesture_image,video,FrameDataandgesture_videoshapes, and the gesture valuesleft,right,upanddown, are defined once on Common objects & errors.
{
"cus_user_id": string,
"client_transaction_id": string,
"faces": [
{
"id": string,
"base64": string,
"label": string,
"metadata": string_json,
}
],
"gesture_faces":[
{
"gesture": string,
"images": [
{
"id": string,
"base64": string,
"label": string,
"metadata": string_json,
},
{
"id": string,
"base64": string,
"label": string,
"metadata": string_json,
}
],
}
],
"videos": [
{
"id": string,
"metadata": string_json,
"frames": [
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
// other frames
],
},
{
"id": string,
"metadata": string_json,
"frames": [
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
// other frames
],
},
...
],
"gesture_videos": [
{
"gesture": string,
"videos": [
{
"id": string,
"metadata": string_json,
"frames": [
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
{
"base64": string,
"label": string,
"index": int,
"metadata": string_json,
},
// other frames
],
},
... // other videos
]
},
... // other gesture videos
],
"device_id": string,
"app_id": string,
"lat": float,
"lng": float,
"auth_type": string,
"selfie_type": string,
"history_return_count": int,
"history_return_status": string,
"metadata": json_object
}
The selfie_type parameter
selfie_type picks the liveness technique the call runs, which is what separates the Light, Standard, Edge and Advanced tiers named in the parameter table.
selfie_type | Description |
|---|---|
light | Light Authen |
passive | Standard Authen |
passive_v2 | Standard Authen (v2) |
active | Advanced Authen use active liveness (gestures) |
flash | Advanced Authen uses full flash liveness |
flash_8 | Edge Authen uses flash liveness with 8 frames |
flash_16 | Edge Authen uses flash liveness with 16 frames |
flash_32 | Advanced Authen uses flash liveness with 32 frames |
flash_edge | Edge Authen uses flash liveness with minimum time |
flash_advanced | Advanced Authen uses full flash liveness |
The auth_type parameter
auth_type labels the use-case this authentication belongs to; the values below are the common ones, and you can define any authentication type based on your business. Each auth_type maps to a backend cluster setting that decides which checks run for the request — liveness, portrait sanity, face compare — so it is how you scope a request to fewer checks than the full default pipeline; leaving it unset runs every check.
auth_type | Description |
|---|---|
reset_password | Authenticate to reset password flow |
login | Use face to replace text password |
payment | Authenticate payment |
transfer | Authenticate transfer |
transfer_type_A | Authenticate transfer type A |
transfer_type_B | Authenticate transfer type B |
transfer_type_C | Authenticate transfer type C |
transfer_type_D | Authenticate transfer type D |
... | You can define any authentication type based on your business |
Sample request
curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/face_auth \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json' \
-d \
'
{
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"faces": [
{
"id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
},
{
"id": "c5a2a405-f152-4248-b746-3af76b241ef7"
},
{
"id": "5d0345f7-da7c-44e8-bd6c-a8c08c806227"
}
],
"gesture_faces": [
{
"gesture": "left",
"images": [
{
"id": "d849a3ce-d209-4605-99a7-3d369234fd5e"
}
]
},
{
"gesture": "up",
"images": [
{
"id": "551fc06a-14fd-44dc-8838-abe895007c36"
}
]
},
{
"gesture": "right",
"images": [
{
"id": "536d2457-bfc0-4249-85f2-8c4053bdec58"
}
]
}
],
"videos": [
{
"id": "61801fcd-b109-49f7-b871-ae82c2a666cc",
},
{
"id": "1f93d229-7f1c-44f9-a85b-1be4c2d4be41",
}
],
"metadata": {
"key1": {
"key11": "value11",
"key12": "value12"
},
"key2": "value2"
}
}
'
A Flash mode request sends multiple faces — one per captured frame — and sets selfie_type to the matching flash value, instead of the single image a passive request would use:
curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/face_auth \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json' \
-d \
'
{
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"selfie_type": "flash_16",
"auth_type": "login",
"faces": [
{
"id": "b635e407-13e4-403b-8731-80821cfa4922"
},
{
"id": "1cb8712c-56da-4c26-a850-08618248a370"
}
]
}
'
Response
data.auth_check carries the verdict — a result of matched or unmatched, and a score for how likely it is that the two faces match (0-1). A 200 only means the request finished processing: whether the authentication passed is in data.status, which is "success" or "failure", and in auth_check — never in the HTTP status code.
Each entry under histories is a history record, and errors uses the shared error envelope; both are documented once on Common objects & errors.
{
"data": {
"status": string, // "success" or "failure"
"auth_check": {
"score": float, // how likely that face1 and face2 are matched (0-1)
"result": string // "matched", "unmatched"
},
"request_id": string, // return request id to the client and can use request-id to check logs.
"user_metadata": json_object, // return user metadata
"validate_faces_result": {
"sanity_verdict": string, // portrait_sanity check result, if field not exist or value is "", it means portrait_sanity check is not performed
"is_live": bool, // liveness check result, if field not exist or value is null, it means liveness check is not performed
"sanity_check: {...}, // full sanity check response
"liveness_check: {...} // full liveness check response
},
"auth_id": string, // id of this authentication request
"histories": [
{
"id": string, // id of this history
"client_id": string, // client id
"cus_user_id": string, // user id
"face_auth_id": string, // id of selfie image containing user's face
"id_card_face_id": string, // id of id card image containing user's face
"live_face_id": string, // id of input image for this login request
"device_id": string, // device id input for this login request
"app_id": string, // app id input for this login request
"latitude": float, // latitude input for this login request
"longitude": float, // longitude input for this login request
"created_at": string, // time of this login request
"auth_action": string, // "login"
"status": string, // "success" or "failure"
"result": string, // detail result of this login request
"metadata": json_object, // metadata input for this login request
"face_type": string, // type of face used to compare against the input face to authenticate ("selfie", "id_card")
},
... // other history
]
},
"errors": [
{
"code": string,
"message": string,
"detail": {
"field": string, // optional, which parameter is invalid.
... // any other information that can be useful for client
},
},
... // other errors
]
}
The expiry_date of selfie face will be returned in
user_metadatafield asexpiry_date_facein RFC3339 format.
A matched authentication, with two history records, comes back like this:
{
"data": {
"status": "success",
"auth_check": {
"score": 0.9999999862517992,
"result": "matched"
},
"request_id": "cfc7b8d5-f2e2-437b-80e5-d600dfad26e2",
"user_metadata": {
"key1": "value1",
"key2": 2,
"expiry_date_face": "2023-12-27T03:33:06.307977Z",
},
"validate_faces_result": {
"sanity_verdict": "good",
"is_live": true,
"sanity_check": {
"portrait_sanity": {
"score": 1,
"verdict": "good"
},
"request_id": "9f89377f-4bb4-4ecb-884c-f46f1d7d6099",
"status": "success"
},
"liveness_check": {
"images": null,
"is_live": true,
"request_id": "baee3d03-8af4-421b-8968-a0f6172b4df8",
"score": 1,
"status": "success"
}
},
"auth_id": "d4f99f9b-4862-437f-a9c9-608e050d06c6",
"histories": [
{
"id": "f1ca6795-cbd4-4eec-821f-b4ac646db627",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "887249dc-681c-4231-aff9-67734833aca7",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-27T03:33:06.307977Z",
"auth_action": "login",
"status": "success",
"result": "",
"face_type": "selfie"
},
{
"id": "8c23af95-aaa0-4448-bfba-68acce31236e",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-21T07:24:19.829484Z",
"auth_action": "login",
"status": "failure",
"result": "image is not liveness",
"face_type": "id_card"
}
]
}
}
A Flash mode authentication (selfie_type: "flash_16") carries the same verdict shape, with validate_faces_result.liveness_check scoring every faces image individually — the same shape Verify face liveness returns:
{
"data": {
"status": "success",
"auth_check": {
"score": 0.910237543284893,
"result": "matched"
},
"request_id": "3f2a9b3e-1c9d-4a5e-9b7a-2f6d9a1b7e3c",
"validate_faces_result": {
"sanity_verdict": "good",
"is_live": true,
"sanity_check": {
"portrait_sanity": {
"score": 1,
"verdict": "good"
},
"status": "success"
},
"liveness_check": {
"images": [
{
"id": "1cb8712c-56da-4c26-a850-08618248a370",
"is_live": true,
"score": 0.910237543284893
},
{
"id": "b635e407-13e4-403b-8731-80821cfa4922",
"is_live": true,
"score": 0.9999598160466121
}
],
"is_live": true,
"score": 0.910237543284893,
"status": "success"
}
},
"auth_id": "8c8e6a2b-2f9d-4a5e-9b7a-2f6d9a1b7e3c",
"histories": []
}
}
Failure codes
If the data.status is "failure", the "errors" field will tell you why it failed.
| Error code | Description |
|---|---|
image_too_blur | the input image is too blur |
image_too_dark | the input image is too dark |
image_too_bright | the input image is too bright (glare) |
image_has_no_faces | the input image has no faces |
image_non_liveness | the input image is not liveness |
face_auth_user_deactivated | the user is deactivated |
face_auth_user_unregistered | the user is unregistered from face_auth service |
face_auth_user_locked | the user is locked from face_auth service |
Transport, auth and rate-limit errors are the same on every call — see Common objects & errors.