curl --request POST \
--url https://api.spoofsense.ai/v1/liveness_detection \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"data": "<string>",
"image_url": "<string>",
"threshold": 0.5,
"thresholds": {},
"min_face_check": true
}
'import requests
url = "https://api.spoofsense.ai/v1/liveness_detection"
payload = {
"data": "<string>",
"image_url": "<string>",
"threshold": 0.5,
"thresholds": {},
"min_face_check": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
data: '<string>',
image_url: '<string>',
threshold: 0.5,
thresholds: {},
min_face_check: true
})
};
fetch('https://api.spoofsense.ai/v1/liveness_detection', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.spoofsense.ai/v1/liveness_detection",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => '<string>',
'image_url' => '<string>',
'threshold' => 0.5,
'thresholds' => [
],
'min_face_check' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.spoofsense.ai/v1/liveness_detection"
payload := strings.NewReader("{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.spoofsense.ai/v1/liveness_detection")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.spoofsense.ai/v1/liveness_detection")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}"
response = http.request(request)
puts response.read_body{
"product": "face_liveness",
"decision": "real",
"genuine_score": 0.9333,
"threshold": 0.5,
"spoof_type": null,
"latency_ms": 190,
"credits_remaining": 1240,
"session_id": "d2f8c1e4a90b4f0f8f1f2a3b4c5d6e7f",
"request_id": "9b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e"
}{
"error": {
"code": "BAD_REQUEST",
"message": "Provide 'data' (base64) or 'image_url'"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing, invalid, or revoked API key"
}
}{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits"
}
}{
"error": {
"code": "IMAGE_TOO_LARGE",
"message": "Image too large (max 10 MB)"
}
}{
"error": {
"code": "FACE_NOT_DETECTED",
"message": "No face found in the image"
}
}{
"error": {
"code": "UPSTREAM_ERROR",
"message": "Inference service unavailable"
}
}Face liveness check
Checks whether the face in the image is a live capture rather than a presentation attack (printed photo, screen replay, mask). Costs 1 credit.
curl --request POST \
--url https://api.spoofsense.ai/v1/liveness_detection \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"data": "<string>",
"image_url": "<string>",
"threshold": 0.5,
"thresholds": {},
"min_face_check": true
}
'import requests
url = "https://api.spoofsense.ai/v1/liveness_detection"
payload = {
"data": "<string>",
"image_url": "<string>",
"threshold": 0.5,
"thresholds": {},
"min_face_check": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
data: '<string>',
image_url: '<string>',
threshold: 0.5,
thresholds: {},
min_face_check: true
})
};
fetch('https://api.spoofsense.ai/v1/liveness_detection', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.spoofsense.ai/v1/liveness_detection",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => '<string>',
'image_url' => '<string>',
'threshold' => 0.5,
'thresholds' => [
],
'min_face_check' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.spoofsense.ai/v1/liveness_detection"
payload := strings.NewReader("{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.spoofsense.ai/v1/liveness_detection")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.spoofsense.ai/v1/liveness_detection")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": \"<string>\",\n \"image_url\": \"<string>\",\n \"threshold\": 0.5,\n \"thresholds\": {},\n \"min_face_check\": true\n}"
response = http.request(request)
puts response.read_body{
"product": "face_liveness",
"decision": "real",
"genuine_score": 0.9333,
"threshold": 0.5,
"spoof_type": null,
"latency_ms": 190,
"credits_remaining": 1240,
"session_id": "d2f8c1e4a90b4f0f8f1f2a3b4c5d6e7f",
"request_id": "9b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e"
}{
"error": {
"code": "BAD_REQUEST",
"message": "Provide 'data' (base64) or 'image_url'"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing, invalid, or revoked API key"
}
}{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits"
}
}{
"error": {
"code": "IMAGE_TOO_LARGE",
"message": "Image too large (max 10 MB)"
}
}{
"error": {
"code": "FACE_NOT_DETECTED",
"message": "No face found in the image"
}
}{
"error": {
"code": "UPSTREAM_ERROR",
"message": "Inference service unavailable"
}
}Authorizations
Your secret key (sk_live_…), server-side only. Also accepted as an x-api-key header.
Body
The image, in any supported form. Max 10 MB. EXIF orientation is applied automatically. The detected face's bounding box must be at least 224×224 pixels, or the call returns 422 FACE_TOO_SMALL — pass min_face_check: false to skip that gate.
Base64-encoded image, or a full data URL. Alias: image.
http(s) URL we fetch server-side (10 s timeout). Alias: url. Provide either data or image_url.
Optional per-request decision threshold. Defaults to your org setting (0.5 unless changed).
0 <= x <= 1Unified only: per-product thresholds, e.g. {"face_liveness": 0.6, "deepfake": 0.4}.
Show child attributes
Show child attributes
Set to false to disable the 224×224 minimum-face-size gate (422 FACE_TOO_SMALL) for this request. Small faces are upscaled before scoring, so accuracy degrades on faces well under 224 px — use only if your capture flow can't guarantee close-up faces. A face must still be detectable.
Response
Scored check
face_liveness, deepfake genuine_score > threshold
real, spoof Calibrated score in [0,1].
The threshold actually applied (request override, org setting, or 0.5).
Always null for current models.
Model inference time.
Balance after this call.
Id of the logged detection session (visible in the console).
Quote this when contacting support.