Face Authentication

Authenticate

POST/v1/face_auth

Checks a captured selfie against the customer’s registered face and returns a match verdict with a confidence score.

Request

MethodPOST
Path/v1/face_auth
Content-Typeapplication/json
Auth requiredYes — HMAC signing

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.

NameTypeRequiredDescription
cus_user_idstringRequiredUser id of customer (max 256)
faces[]imageRequiredImages 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_imageOptionalArray of gestures contain images (max 50)
videos[]videoOptionalArray of videos selfie (max 50)
gesture_videos[]gesture_videoOptionalArray of videos gesture (max 50)
device_idstringOptionalDevice id of user (max 256)
app_idstringOptionalApp id of customer (max 128)
latfloatOptionalLatitude of device
lngfloatOptionalLongitude of device
auth_typestringOptionalSpecify 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_idstringOptionalClient transaction ID
selfie_typestringOptionalSpecify 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_countintOptionalNumber of history authenticate records to return
history_return_statusstringOptionalStatus of history authenticate records to return (success, failure or all)
metadatajson_objectOptionalAny key-value metadata to store with this login time
  • For parameter type image, if you use id (result id is returned from Upload Image API), omit parameter base64, label and metadata. If you use base64, label and metadata, omit parameter id.
  • For parameter type video, if you use id (result id is returned from Upload File API), omit parameter frames, metadata. If you use frames, metadata, omit parameter id.

The image, gesture_image, video, FrameData and gesture_video shapes, and the gesture values left, right, up and down, are defined once on Common objects & errors.

JSON
{
    "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_typeDescription
lightLight Authen
passiveStandard Authen
passive_v2Standard Authen (v2)
activeAdvanced Authen use active liveness (gestures)
flashAdvanced Authen uses full flash liveness
flash_8Edge Authen uses flash liveness with 8 frames
flash_16Edge Authen uses flash liveness with 16 frames
flash_32Advanced Authen uses flash liveness with 32 frames
flash_edgeEdge Authen uses flash liveness with minimum time
flash_advancedAdvanced 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_typeDescription
reset_passwordAuthenticate to reset password flow
loginUse face to replace text password
paymentAuthenticate payment
transferAuthenticate transfer
transfer_type_AAuthenticate transfer type A
transfer_type_BAuthenticate transfer type B
transfer_type_CAuthenticate transfer type C
transfer_type_DAuthenticate 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:

Shell
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.

JSON
{
    "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_metadata field as expiry_date_face in RFC3339 format.

A matched authentication, with two history records, comes back like this:

JSON
{
    "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:

JSON
{
    "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 codeDescription
image_too_blurthe input image is too blur
image_too_darkthe input image is too dark
image_too_brightthe input image is too bright (glare)
image_has_no_facesthe input image has no faces
image_non_livenessthe input image is not liveness
face_auth_user_deactivatedthe user is deactivated
face_auth_user_unregisteredthe user is unregistered from face_auth service
face_auth_user_lockedthe user is locked from face_auth service

Transport, auth and rate-limit errors are the same on every call — see Common objects & errors.