Vision Score via eKYC Core · Vision Score

Vision Score

POST/v1/vision_score

Scores a customer's trustworthiness and risk profile from their selfie images, returning an overall vision score and a score for each image.

Authentication

Vision Score is called through the eKYC Core API, so it uses that API's HMAC request signing — there is no separate Vision Score credential. See Authentication mechanism for how to construct the signature.

Request

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

Vision Score generates a comprehensive score from facial data, enabling businesses to quickly validate identity, confirm liveness, and enhance fraud prevention during the onboarding process.

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
images[]imageRequiredarray of frontal image object contains properties as described at ImageData. Active liveness: 2-4 images, Passive: 1-3 images.
gesture_images[]gesture_imageOptionalarray of gestures contain images. Active liveness: 3 images, Passive: no gesture image.
videos[]videoOptionalarray of video recording when liveness on SDK. Default 1
metadatadictionaryOptionalthe collected data during liveness checking process
selfie_typestringOptionalSpecify the characteristic of a disabled face or liveness mode eg. disabled eye, passive, active, flash
  • For image, if you use base64, label and metadata, omit parameter id. If you use id (result id is returned from Upload Image API), omit parameter base64, label and metadata.
  • For 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.
  • If you use gesture_images, the images parameter should have at least 2 images and gesture in gesture_images should have at least left or right.

Every entry in images, and every entry in a gesture's own images, is an ImageData object:

JSON
{
    "images": [
        {
            "id": string,
            "base64": string,
            "label": string,
            "metadata": string_json,
        },
        {
            "id": string,
            "base64": string,
            "label": string,
            "metadata": string_json,
        }
    ],
    "gesture_images":[
        {
            "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
            ],
        }
    ],
    "metadata": dictionary
}

Which each video's parameters contains:

NameTypeRequiredDescription
idstringOptionalID of video is returned from API Upload
metadatastring_jsonOptionalkey-value string, key should be string, value should be string, int, float, bool. Example "{\"id\":\"123456789\",\"type\":1}"
frames[]FrameDataOptionallist of video frames to be uploaded

Which FrameData's parameters contains:

NameTypeRequiredDescription
base64stringOptionalbase64 encoded text of image data
labelstringOptionallabel of the image as described at Label table
indexintOptionalthe index of this frame in the video
metadatastring_jsonOptionalkey-value string, key should be string, value should be string, int, float, bool. Example "{\"id\":\"123456789\",\"type\":1}"

Which each gesture_image's parameters contains:

NameTypeRequiredDescription
gesturestringRequiredspecify a gesture value as below table. Example left, right, up or down
images[]imageRequiredan array of images for each gesture

Which gesture parameter contains value:

gestureDescription
leftthe face turns left
rightthe face turns left
upthe face up
downthe face down

The selfie_type parameter

selfie_type names the liveness mode, and for the flash modes how many frames the capture carries.

selfie_typeDescription
passivePassive mode
activeActive mode
flashFlash mode with 32 frames
flash_8Flash mode with 8 frames
flash_16Flash mode with 16 framess
flash_32Flash mode with 32 frames

Sample request

curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/vision_score \
-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 \
'
{
    "images": [
        {
            "id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
        },
        {
            "id": "c5a2a405-f152-4248-b746-3af76b241ef7"
        },
        {
            "id": "5d0345f7-da7c-44e8-bd6c-a8c08c806227"
        }
    ],
    "gesture_images": [
        {
            "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": "433331b5-e1d4-433f-84e6-2260ec6bee92"
        },
        {
            "id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3"
        }
    ]
}
'

Response

data.persona_attributes.vision_score carries the score, a float on a 0-100 range, and each entry in data.images carries a score on the same range — up to 3 images. A 200 only means the request finished processing; data.status is what says whether it succeeded, and it is either "success" or "failure".

The response will be a JSON with following format, in the shared response envelope:

JavaScript
{
    "data": {
        "status": string, "success" or "failure"
        "persona_attributes": {
            "vision_score": float // range (0-100)
        },
        "images": [
            {
                "id": string, // ID of the image
                "score": float // range (0-100)
            },
            ... // up to 3 images
        ],
        "request_id": string // return request id to the client and can use request-id to check logs.
    },
    "errors": [
        {
            "code": string,
            "message": string,
            "detail": {
                "field": string, // optional, which parameter is invalid.
                ... // any other information that can be useful for client
            },
        },
        ... // other errors
    ]
}

A successful scoring comes back like this:

JSON
{
    "data": {
        "details": null,
        "images": [
            {
                "id": "0e33129a-c9ec-4e22-bf53-78d496bb1f37",
                "score": 95
            }
        ],
        "request_id": "93029850-924c-465a-baa6-27d843cbb1ba",
        "status": "success",
        "persona_attributes": {
          "vision_score": 95
        }
    }
}

Failure codes

If the data.status is "failure", the "errors" field will tell you why it failed.

Error codeDescription
image_has_no_facethe input image has no faces

In case of any other errors, the data field will be empty, and the server sends one of following HTTP status code with error code:

HTTP codeError codeDescription
401access_denied_exceptionYou are not authorized to perform the action.
413image_too_large_exceptionThe input image size exceeds the allowed limit (15MB).
415invalid_image_format_exceptionThe provided image format is not supported (JPG/PNG)
400invalid_parameter_exceptionInput parameter violates a constraint.
400request_time_too_skewedThe X-TV-Timestamp header is expired, need a newer one.
404image_not_found_exceptionThe image ID is not found in DB.
408request_timeout_exceptionRequest takes too long to process
429rate_limit_exceptionThe number of requests exceeded your throughput limit.
500internal_server_errorSome unexpected error occurs while processing the request

The codes above are the ones documented for this endpoint. Response errors lists the codes for the eKYC Core surface as a whole — the two lists do not match on every endpoint.