Liveness Detection API Reference
This is the complete endpoint specification for the Liveness Detection (anti-spoofing) API (Liveness Check API). If you are using the API for the first time, please read the Quickstart Guide first.
Basic Information
| Item | Value |
|---|---|
| API base URL | https://liveness.api.pas-ta.io |
| Customer dashboard | https://liveness.api.pas-ta.io/console/dashboard |
| Content type | application/json |
| Character encoding | UTF-8 |
| API version (URL path) | v1 |
Authentication
This API supports two authentication methods.
| Target | Method | Purpose |
|---|---|---|
Detection API (/v1/*) |
X-API-Key header |
Send detection requests from the Customer’s servers or applications |
Customer dashboard (/console/*) |
Cookie session (browser only) | Manage your account, keys, and plan on the dashboard screens (not intended for direct programmatic calls) |
For a detection request, include the API key obtained from the dashboard (a string beginning with lc_) in the X-API-Key header.
X-API-Key: lc_abc12xxxxxxxxxxxxxxxxxxxxxxxx
The
/console/*endpoints are a screen-only backend authenticated with HttpOnly cookies issued when you log in to the dashboard. They are not designed to be called directly from your programs. See Customer Dashboard for what you can do on the dashboard.
Common Response Structure
All endpoints except /v1/health return a common structure consisting of metadata and data (or error).
On success:
{
"metadata": {
"date": "2026-05-04T12:34:56.789Z",
"ver": "1.0.1",
"customer_id": "550e8400-e29b-41d4-a716-446655440000",
"remaining_calls": 3850,
"over_limit_calls": 0,
"status": "success"
},
"data": { }
}
On error:
{
"metadata": { "...": "...", "status": "error" },
"error": {
"code": "invalid_image",
"message": "No face was detected"
}
}
metadata Fields
| Field | Type | Description |
|---|---|---|
date |
string | Response generation timestamp (ISO 8601, UTC, millisecond precision) |
ver |
string | The applied API version (semantic version, e.g., "1.0.1") |
customer_id |
string | null | Customer UUID (null when authentication fails) |
remaining_calls |
integer | null | Remaining credits for the current month (never goes below 0; clipped at 0) |
over_limit_calls |
integer | null | Number of overage calls for the current month (always 0 on the free plan or when the hard cap is ON) |
status |
string | "success" or "error" |
The monthly boundary is based on UTC. The current-month tally begins at 00:00:00 UTC on the 1st of each month, and credits expire at 23:59:59 UTC at the end of the month (consistent with the AWS Marketplace billing-month boundary).
Billing (Call Counting)
Only successful responses (status: "success") of POST /v1/check/liveness consume your monthly credits (i.e., are counted as calls). Everything else is free.
| Endpoint | Billing |
|---|---|
POST /v1/check/liveness — successful response |
Consumes 1 call (billable) |
POST /v1/check/liveness — error response (4xx / 5xx) |
Free (not counted) |
GET /v1/usage |
Free |
GET /v1/health |
Free |
/console/* (all dashboard-related) |
Free |
Error responses such as
invalid_image,429, and5xxare not counted toward your monthly calls. Only successful responses that return a detection result are billable.
Detection API (/v1/*)
POST /v1/check/liveness — Liveness Detection
Send a Base64-encoded face image to determine whether it is a photo or a spoofing attack.
Authentication: X-API-Key header required
Billing: Only successful responses consume 1 call (error responses are not counted)
Request
{
"image": "<Base64-encoded image>",
"image_format": "jpeg"
}
| Field | Type | Required | Description |
|---|---|---|---|
image |
string | ○ | Base64-encoded image data (maximum 10 MB) |
image_format |
string | ○ | "jpeg" or "png" |
Response (200 OK)
{
"metadata": {
"date": "2026-05-04T12:34:56.789Z",
"ver": "1.0.1",
"customer_id": "550e8400-e29b-41d4-a716-446655440000",
"remaining_calls": 3850,
"over_limit_calls": 0,
"status": "success"
},
"data": {
"isFakeFace": false,
"isFakeLikelihood": 0.987,
"isValidFace": true,
"faceBrightness": 142.3,
"faceRectArea": {"x": 120, "y": 80, "width": 200, "height": 200},
"vFaceRect": [
{"x": 120, "y": 80, "width": 200, "height": 200}
],
"msg": "",
"latency_ms": 120
}
}
data field |
Type | Description |
|---|---|---|
isFakeFace |
boolean | true = suspected photo or spoofing; false = live subject. Becomes true when isFakeLikelihood exceeds the default threshold of 0.15 |
isFakeLikelihood |
float | Spoofing likelihood (detection score from 0.0 to 1.0) |
isValidFace |
boolean | Whether the face can be treated as a valid detection target |
faceBrightness |
float | Average brightness of the face region |
faceRectArea |
object | The adopted face rectangle {x, y, width, height} |
vFaceRect |
array | List of all detected face rectangles |
msg |
string | Supplementary message |
latency_ms |
integer | Inference latency (milliseconds) |
How to interpret the Processing Result:
isFakeFaceis a reference verdict that becomestruewhenisFakeLikelihoodexceeds the default threshold of 0.15 (the threshold may change as detection accuracy improves; changes will be announced in the Changelog). For stricter operation, evaluateisFakeLikelihood(0.0–1.0) against a threshold on the Customer’s side. By adjusting the threshold to suit your use case, you can optimize the balance between false positives and false negatives.
Errors
| HTTP | error.code |
Condition |
|---|---|---|
| 400 | invalid_request |
Validation error in the request body |
| 400 | invalid_image |
Image decode failure or no face detected |
| 401 | invalid_api_key |
Invalid, deactivated, or expired key |
| 429 | quota_exceeded |
Limit reached and in API-stop mode (free plan, or a paid plan with the hard cap ON) |
| 500 | internal_error |
Internal server error |
| 503 | service_unavailable |
Temporary service unavailability |
GET /v1/usage — Check Current-Month Usage
Authentication: X-API-Key header required
Billing: Free (not counted toward your monthly calls)
Response (200 OK)
{
"metadata": { "...": "...", "status": "success" },
"data": {
"year_month": "2026-05",
"total_calls": 1150,
"monthly_limit": 5000,
"remaining_calls": 3850,
"over_limit_calls": 0,
"plan": "standard",
"hard_cap_enabled": false
}
}
data field |
Description |
|---|---|
year_month |
Target year and month (YYYY-MM, UTC-based) |
total_calls |
Cumulative number of calls for the current month |
monthly_limit |
Monthly credit count (plan limit) |
remaining_calls |
Remaining credit count |
over_limit_calls |
Number of overage calls (always 0 when the hard cap is ON or on the free plan) |
plan |
The plan currently in effect |
hard_cap_enabled |
Whether the hard cap setting is ON/OFF |
GET /v1/health — Health Check
Authentication: Not required (no metadata is included)
Billing: Free (not counted toward your monthly calls)
{"status": "ok"}
In cases such as a DB connection failure, it returns 503 with {"status": "error", "message": "database unavailable"}.
Customer Dashboard
Account, API key, and plan settings are managed through the customer dashboard (https://liveness.api.pas-ta.io/console/dashboard). All dashboard operations are free (not counted toward your monthly calls).
The
/console/*endpoints used internally by the dashboard are a screen-only backend (cookie-session authenticated). They are not designed to be called directly from your programs and may change without notice. For programmatic integration, use the Detection API (/v1/*) withX-API-Keyauthentication.
Sign-in and Security
- Sign-in: Email address + password, plus two-factor authentication (TOTP), which is mandatory for all accounts. On your first sign-in, scan the QR code with an authenticator app (Google Authenticator, Authy, 1Password, etc.).
- Password reset: Use “Forgot your password?” on the sign-in page and reset with the 6-digit code sent to your registered email address.
API Key Management
Each account is issued two keys, Primary and Secondary. Both work identically; keeping one as a backup enables zero-downtime rotation.
- The list shows only the leading prefix of each key (
lc_abc12…). The full key is displayed only once, at the moment it is issued (account activation or regeneration). Store it in a secure location such as a password manager. - Regenerate: Immediately invalidates the target key and issues a new one. The new key is shown once, on the spot.
- Example rotation flow: The Primary is compromised → switch to the Secondary to keep the service running → replace the key in your code → regenerate the Primary → regenerate the Secondary a few days later.
Plan, Usage, and Hard Cap
- Plan / Usage: Shows your current plan, monthly limit, and current-month usage (also available programmatically via
GET /v1/usage). - Hard cap toggle: Switch it with the button in the Plan section. ON = the API stops (
429) when the limit is reached and no overage charges are incurred. OFF (default) = detection continues beyond the limit and the overage is metered. Thefreeplan is always ON.
Plan Changes and Cancellation
Plan changes and cancellation are handled through your AWS Marketplace subscription management. Upgrades take effect immediately. Downgrades and cancellations take effect at the contract renewal timing (mid-term cancellation is not available). Please contact us if you have any questions.
Error Code List
| HTTP | error.code |
Condition |
|---|---|---|
| 400 | invalid_image |
Face detection failure or corrupted image |
| 400 | invalid_request |
Request validation error |
| 401 | invalid_api_key |
Invalid, deactivated, or expired key |
| 403 | forbidden |
Failure to verify the authentication credentials |
| 404 | not_found |
Resource does not exist (scheduled change, key ID, etc.) |
| 429 | quota_exceeded |
Monthly call limit exceeded (in API-stop mode) |
| 500 | internal_error |
Internal server error |
| 503 | service_unavailable |
DB connection failure or temporary unavailability |
About rate limiting: In addition to the monthly credit limit per plan, there is overall throttling (
429) for fair use. This is not an individual guarantee of instantaneous rate. If you require stable high throughput, please contact us.
Sample Code
Examples of calling POST /v1/check/liveness from each language.
curl
# Pass the body via stdin (recommended). macOS: base64 -i / Linux: base64 -w0
{ printf '{"image": "'; base64 -i face.jpg | tr -d '\n'; printf '", "image_format": "jpeg"}'; } \
| curl -X POST https://liveness.api.pas-ta.io/v1/check/liveness \
-H "X-API-Key: lc_abc12xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
--data-binary @-
Why stdin? Expanding the Base64 string directly into a command-line argument, as in
-d "{\"image\": \"$(base64 -i face.jpg)\", ...}", hits the shell’s argument-length limit (ARG_MAX) once the image exceeds a few hundred KB, and the command fails withargument list too longbefore it even runs. The stdin approach works up to the API’s 10 MB limit.tr -d '\n'is required to strip the trailing newline from the Base64 output (it would otherwise break the JSON).
Python
import base64
import requests
with open("face.jpg", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode("ascii")
resp = requests.post(
"https://liveness.api.pas-ta.io/v1/check/liveness",
headers={"X-API-Key": "lc_abc12xxxxxxxxxxxxxxxxxxxxxxxx"},
json={"image": image_b64, "image_format": "jpeg"},
timeout=30,
)
resp.raise_for_status()
result = resp.json()["data"]
print("fake?", result["isFakeFace"], "likelihood:", result["isFakeLikelihood"])
Node.js
import { readFileSync } from "node:fs";
const imageB64 = readFileSync("face.jpg").toString("base64");
const resp = await fetch("https://liveness.api.pas-ta.io/v1/check/liveness", {
method: "POST",
headers: {
"X-API-Key": "lc_abc12xxxxxxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({ image: imageB64, image_format: "jpeg" }),
});
const { data } = await resp.json();
console.log("fake?", data.isFakeFace, "likelihood:", data.isFakeLikelihood);
Plans and Usage Limits
About pricing: The table below shows AWS Marketplace public prices (USD). Private Offers are available for customers in Japan. Please contact us if interested.
| Plan | Monthly calls | Monthly fee | Overage unit price / call |
|---|---|---|---|
| Starter | 1,000 | $180 | $0.18 |
| Standard | 5,000 | $750 | $0.15 |
| Professional | 10,000 | $1,200 | $0.12 |
| Business | 30,000 | $2,400 | $0.08 |
| Enterprise | 100,000+ (custom) | $5,000+ | $0.05 |
- Credit system: At the start of each month, credits equal to the monthly call count are granted and expire at the end of that month (no carryover to the next month).
- Overage metering (default): Usage beyond the limit is billed on a metered basis at the overage unit price.
- Hard cap (optional, ON): When the limit is reached, the API is stopped (
429) and no overage charges are incurred. You can toggle this from the dashboard. - Plan changes: Upgrades take effect immediately; downgrades and cancellations take effect the next month / at the end of the month.
- Enterprise: The limit is set on a custom basis under an individual contract (private offer).
- Billing: Only successful detection responses are counted (see Billing (Call Counting)).
Versioning
You can check the API version in the response’s metadata.ver (semantic version, e.g., 1.0.1).
| Change level | Example | Handling |
|---|---|---|
| Major (breaking change) | Response structure change, field removal, type change | Introduce a new URL path (/v1/ → /v2/) |
| Minor (backward compatible) | Field addition, new endpoint addition | Keep the URL path; update the minor of ver |
| Revision (internal change) | Bug fix, performance improvement | Keep the URL path; update the revision of ver |
- Even after introducing
/v2/, we will operate/v1/in parallel for the time being (a deprecation notice will be given at least 6 months in advance). - For the change history, please see the Changelog.