This is intended for technical developer who will implement One Smart Lab’s Rest API Services
Currently, One Smart Lab offers 3 primary access:
- PhotoVerify
- confirm that face in a selfie picture matches the ID
- confirm that the face in the selfie is not spoofed
- VideoVerify
- confirm that face in a selfie video matches the ID
- confirm that the user has spoken a 6 digit number that your app generates and asks the user to repeat
- confirm that the face in the selfie is not spoofed
- SpoofDetect
- confirm that the face in the selfie is not spoofed
Current API version is 1.1.
For apps needing more “industrial strength” verification of the user, we recommend VideoVerify since it uses both deep neural network and behavioral spoof detection. It is much harder to “fool” the AI with a video than a single photo because One Smart Lab AI model is able to pick up subtle nuances in video time series.
/photoverify
URL EndPoint:
- https://api.onesmartlab.com/v1.1/photoverify
POST Parameters:
- id_card – HTTP multipart POST data for ID card that contains the face of the person you are trying to authenticate
- photo – HTTP multipart POST data for image that contains the person’s selfie taken real time
- api_key – your API key
API Call Example
curl:
id_card=/path/to/your/id_card.jpg photo=/path/to/your/selfie_pic.jpg server="https://api.onesmartlab.com/v1.1/photoverify" api_key="YOUR_API_KEY" curl -X POST \ -F "api_key=$api_key" \ -F "id_card=@$id_card" \ -F "photo=@$photo" \ $server
python:
import requests data = { "api_key" : "YOUR_API_KEY" } files = { "id_card" : open('/path/to/your/id_card.jpg', 'rb'), "photo" : open('/path/to/your/selfie_photo.jpg', 'rb') } r = requests.post("https://api.onesmartlab.com/v1.1/photoverify", data=data, files=files) print(r.text)
php:
$url = "https://api.onesmartlab.com/v1.1/photoverify" $data = array( "api_key" => "YOUR_API_KEY", "id_card" => new \CurlFile("/path/to/your/selfie.jpg", 'image/jpeg', 'id_pic.jpg'), "photo" => new \CurlFile("/path/to/your/selfie.jpg", 'image/jpeg', 'selfie.jpg') ); $curl = curl_init(); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); curl_close($curl); print_r($result)
JSON Response:
- if error exists
- {“error” : “SOME_ERROR”}
- if successful:
{ "predictions":{ "duration":"1.10", "end":1534534646.186395, "model_input":{ "audiochallenge":null, "languageCode":null, "video":{ "fps":null, "frames":null, "height":null, "width":null } }, "model_output":{ "audio_challenge_passed":true, "face_distance_avg":0.7475451231002808, "face_sameness":0.0, "largest_face_to_frame_ratio":0.5253456221198156, "non_spoof_detected":1.0, "single_face_in_frames":1.0, "transcription":null }, "model_params":{ "FACE_TO_FRAME_RATIO_MAX":0.7, "THRESHOLD_FACE_SIMILARITY":0.9, "THRESHOLD_L2_DISTANCE":0.9, "THRESHOLD_SPOOF":0.9 }, "start":1534534645.0817783, "verification":{ "breakdown":{ "id_card":{ "face_to_frame_width_ratio":0.0966796875, "not_spoof_confidence":"0.65", "not_spoof_passed":true, "num_faces":1 }, "photo":{ "distance":0.5682702660560608, "face_to_frame_width_ratio":0.4419047619047619, "not_spoof_confidence":"1.00", "not_spoof_passed":true, "num_faces":1 } }, "status":true } }, "success":true }
How to Determine if Self Photo Matches the ID & is NOT Spoofing
Check field – json[“predictions”][“verification”][“status”]
Explanation of the Fields
{ "predictions":{ "duration":"How long the model took to run", "end":"Time model prediction ended, Milliseconds since Unix Epoch", "model_input":{ "audiochallenge":"Should be null since this is photo verification, not video", "languageCode":"Should be null since this is photo verification, not video", "video":{ "fps":"Should be null since this is photo verification, not video", "frames":"Should be null since this is photo verification, not video", "height":"Should be null since this is photo verification, not video", "width":"Should be null since this is photo verification, not video" } }, "model_output":{ "audio_challenge_passed":"Should be True since this is photo verification, not video", "face_distance_avg":"[MODERATION_FIELD] How far the face is from the ID. The closer the face to the ID, the lower this number should be. We currently use THRESHOLD_FACE_SIMILARITY.", "face_sameness":"Should be null or zero since this is photo verification, not video", "largest_face_to_frame_ratio":"[MODERATION_FIELD] How big the face width is relative to the video frame width, in percentage. We currently use FACE_TO_FRAME_RATIO_MAX as acceptable max limit.", "non_spoof_detected":"[MODERATION_FIELD] How likely that the faces found are spoofed. Closer to 1 means more normal. Closer to 0 means more likely to be spoofing", "single_face_in_frames":"Should be 1 since this is photo verification, not video.", "transcription":"Should be null since there is no audio" }, "model_params":{ "FACE_TO_FRAME_RATIO_MAX":"0.7 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_FACE_SIMILARITY":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_L2_DISTANCE":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_SPOOF":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" }, "start":"Time model prediction started, Milliseconds since Unix Epoch" "verification":{ "breakdown":{ "id_card":{ "face_to_frame_width_ratio": "Face to Frame Ratio", "not_spoof_confidence":"Confidence that this is not spoof", "not_spoof_passed":"Whether or not the confidence exceeds threshold", "num_faces":"Number of faces detected" }, "photo":{ "distance":"How far the face is from the photo is from the ID, smaller is bette", "face_to_frame_width_ratio":"Face to Frame Ratio", "not_spoof_confidence":"Confidence that this is not spoof", "not_spoof_passed":"Whether or not the confidence exceeds threshold", "num_faces":"Number of faces detected" } }, "status":"Whether or not face is matched to the ID" } }, "success":"true if everything ran correctly" }
/videoverify
URL EndPoint:
- https://api.onesmartlab.com/v1.1/videoverify
POST Parameters:
- id_card – HTTP multipart POST data for ID card that contains the face of the person you are trying to authenticate
- video – HTTP multipart POST data for video that contains the person’s selfie taken real time
- This video must be valid MP4 video file
- The speaker in the video must clearly show his/her face speaking the 6 digit audiochallenge that your app. See example
- Please view the video guidelines as it contains detailed information on how the video should be taken
- audiochallenge – sequence of 6 digits your app has requested the user to speak in the video
- languageCode (notice the capital “C”) – language that the user has spoken in, such as “en-US” (view the accepted language codes)
- api_key – your API key
API Call Example
curl:
id_card=/path/to/your/id_card.jpg video=/path/to/your/selfie_video.mp4 server="https://api.onesmartlab.com/v1.1/videoverify" audiochallenge="YOUR_6_DIGIT_AUDIOCHALLENGE" languageCode="YOUR_LANGUAGE_CODE" api_key="YOUR_API_KEY" curl -X POST \ -F "api_key=$api_key" \ -F "id_card=@$id_card" \ -F "video=@$video" \ -F "audiochallenge=$audiochallenge" \ -F "languageCode=$languageCode" $server
python:
import requests data = { "audiochallenge" : "YOUR_AUDIO_CHALLENGE", "languageCode" : "YOUR_LANGUAGE_CODE", "api_key" : "YOUR_API_KEY" } files = { "id_card" : open('/path/to/your/id_card.jpg', 'rb'), "video" : open('/path/to/your/selfie_video.mp4', 'rb') } r = requests.post("https://api.onesmartlab.com/v1.1/videoverify", data=data, files=files) print(r.text)
php:
$url = "https://api.onesmartlab.com/v1.1/photoverify" $data = array( "api_key" => "YOUR_API_KEY", "audiochallenge" => "YOUR_AUDIO_CHALLENGE", "languageCode" => "YOUR_LANGUAGE_CODE", "id_card" => new \CurlFile("/path/to/your/selfie.jpg", 'image/jpeg', 'id_pic.jpg'), "video" => new \CurlFile("/path/to/your/selfie_video.mp4", 'video/mp4', 'selfie_video.mp4') ); $curl = curl_init(); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); curl_close($curl); print_r($result)
Response:
- if error exists
- {“error” : “SOME_ERROR”}
- sample successful response:
{ "predictions":{ "duration":"55.86", "end":1534534753.1725538, "model_input":{ "audiochallenge":"123457", "languageCode":"th-TH", "video":{ "fps":30, "frames":105, "height":480, "width":640 } }, "model_output":{ "audio_challenge_passed":true, "face_distance_avg":0.5534744282563527, "face_sameness":0.9904761904761905, "largest_face_to_frame_ratio":0.334375, "non_spoof_detected":1.0, "single_face_in_frames":1.0, "transcription":{ "results":[ { "alternatives":[ { "confidence":0.95064026, "transcript":"1 2 3 4 5 7 " } ] } ] } }, "model_params":{ "FACE_TO_FRAME_RATIO_MAX":0.7, "THRESHOLD_FACE_SIMILARITY":0.9, "THRESHOLD_L2_DISTANCE":0.9, "THRESHOLD_SPOOF":0.9 }, "start":1534534697.3109004, "verification":{ "breakdown":{ "audio_challenge_passed":true, "face_to_frame_width_ratio_passed":true, "not_spoof_passed":true, "video_face_no_change_passed":true, "video_face_to_id_face_passed":true }, "status":true } }, "success":true }
How to Determine if Self Video Matches the ID & isn’t Spoofing
Check field – json[“predictions”][“verification”][“status”]
Explanation of the Fields
{ "predictions":{ "duration":"How long the model took to run", "end":"Time model prediction ended, Milliseconds since Unix Epoch", "model_input":{ "audiochallenge":"sequence of numbers that the user is supposed to say in the video", "languageCode":"language code passed to the model", "video":{ "fps":"Frames per second in video", "frames":"# of frames in video", "height":"Video height", "width":"Video width" } }, "model_output":{ "audio_challenge_passed":"whether or not the user has spoken the sequence of numbers", "face_distance_avg":"[MODERATION_FIELD] How far the face is from the ID. The closer the face to the ID, the lower this number should be. We currently use THRESHOLD_FACE_SIMILARITY.", "face_sameness":"How 'same' the face looks in the entire video. Closer to 1 is better.", "largest_face_to_frame_ratio":"[MODERATION_FIELD] How big the face width is relative to the video frame width, in percentage. We currently use FACE_TO_FRAME_RATIO_MAX as acceptable max limit.", "non_spoof_detected":"[MODERATION_FIELD] How likely that the faces found are spoofed. Closer to 1 means more normal. Closer to 0 means more likely to be spoofing", "single_face_in_frames":"[MODERATION_FIELD] Whether or not we found weird number of faces (i.e. not 1). Closer to 1 is better.", "transcription":{ "results":[ { "alternatives":[ { "confidence":"Transcription confidence level - 1 is better", "transcript":"Transcription from the Audio" } ] } ] } }, "model_params":{ "FACE_TO_FRAME_RATIO_MAX":"0.7 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_FACE_SIMILARITY":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_L2_DISTANCE":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" , "THRESHOLD_SPOOF":"0.9 but YOU CAN SAFELY IGNORE. Internal Value for OneSmartLab team" }, "start":"Time model prediction started, Milliseconds since Unix Epoch"" "verification":{ "breakdown":{ "audio_challenge_passed":"Whether or not the audio in the video transcribes to match the audiochallenge ", "face_to_frame_width_ratio_passed":"Whether or not the face to frame ratio is acceptable", "not_spoof_passed": "whether or not spoofing in the photo /video was detected", "video_face_no_change_passed":"whether or not the photo /video matches the ID", "video_face_to_id_face_passed":"whether or not the face in the photo /video is consistent" }, "status":"True if ALL the breakdown are true. False otherwise." } }, "success":"true if everything ran correctly" }
/spoofdetect
URL EndPoint::
- https://api.onesmartlab.com/v1.1/spoofdetect
POST Parameters:
- photo – HTTP multipart POST data for image that contains the person’s selfie taken real time
- api_key – your API key
API Call Example
photo=/path/to/your/photo.jpg server="https://api.onesmartlab.com/v1.1/spoofdetect" api_key="YOUR_API_KEY" curl -X POST \ -F "api_key=$api_key" \ -F "photo=@$photo" \ $server
python:
import requests data = { "api_key" : "YOUR_API_KEY" } files= { "photo" : open('/path/to/your/photo.jpg', 'rb') } r = requests.post("https://api.onesmartlab.com/v1.1/spoofdetect", data=data, files=files) print(r.text)
php:
$url = "https://api.onesmartlab.com/v1.1/spoofdetect" $data = array( "api_key" => "YOUR_API_KEY", "id_card" => new \CurlFile("/path/to/your/photo.jpg", 'image/jpeg', 'photo.jpg') ); $curl = curl_init(); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); curl_close($curl); print_r($result)
Response:
- if error exists
- {“error” : “SOME_ERROR”}
- sample successful response:
{ "predictions":{ "metadata":{ "face_to_frame_width_ratio":0.9, "face_to_frame_width_ratio_passed":false, "not_spoof_confidence":"1.00", "not_spoof_passed":true, "num_faces":1, "single_face":true }, "verification":{ "breakdown":{ "face_to_frame_width_ratio_passed":false, "not_spoof_passed":true, "single_face":true }, "status":false } }, "success":true }
How to Determine if Selfie Photo is not Spoofed
Check field – json[“predictions”][“verification”][“status”]
Explanation of the Fields
{ "predictions":{ "metadata":{ "face_to_frame_width_ratio": , "num_faces":"Number of faces" }, "verification":{ "breakdown":{ "face_to_frame_width_ratio_passed":"Whether the ratio of width of the face found in the photo to the width of the detected face is acceptable", "not_spoof_passed":"This is non-spoof", "single_face":"Whether single face was detected" }, "status": "True if all parameters in breakdown are true. False otherwise" } }, "success":"true if everything ran correctly" } { "predictions":{ "metadata":{ "face_to_frame_width_ratio":"Ratio of width of the face found in the photo to the width of the detected face", "face_to_frame_width_ratio_passed":"Whether or not the ratio threshold is met", "not_spoof_confidence":"Confidence that its not spoof", "not_spoof_passed":"Whether or not confidence threshold is met, "num_faces":"Number of face", "single_face":"true if only 1 face found" }, "verification":{ "breakdown":{ "face_to_frame_width_ratio_passed":"Whether the ratio of width of the face found in the photo to the width of the detected face is acceptable", "not_spoof_passed":"This is non-spoof", "single_face":"Whether single face was detected" }, "status": "True if all parameters in breakdown are true. False otherwise" } }, "success":"true if everything ran correctly" }