TrueLens API Reference
Face scan verification and liveness detection. Drop into any signup flow to confirm real humans — without CAPTCHAs.
What is TrueLens?
TrueLens replaces friction-heavy CAPTCHAs with a 5-second webcam liveness check. Your users look at the camera once — TrueLens confirms they're human and returns a signed badge URL you can store against the user record.
- Liveness detection — confirms the person is live (not a photo or replay)
- Bot-proof — headless browsers and automated scripts can't pass a face scan
- Privacy-first — no biometric data stored; only verification status
- Embeddable — drop the hosted verification page into your flow with a redirect
All endpoints accept and return JSON. HTTPS only.
Authentication
Every API request requires an API key passed in the X-API-Key header.
curl -X POST https://truelens-2.polsia.app/api/verify/init \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{}'
const res = await fetch('https://truelens-2.polsia.app/api/verify/init', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'YOUR_API_KEY'
},
body: JSON.stringify({})
});
const data = await res.json();
import requests
response = requests.post(
'https://truelens-2.polsia.app/api/verify/init',
headers={
'Content-Type': 'application/json',
'X-API-Key': 'YOUR_API_KEY'
},
json={}
)
data = response.json()
Quick Start
A full verification takes two API calls:
- Init — create a verification session, get a
verification_id - Redirect — send your user to
/verify?id={verification_id}— they complete the face scan - Complete — call complete with the
verification_idto get the badge URL
# Step 1: Init
curl -X POST https://truelens-2.polsia.app/api/verify/init \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{}'
# → { "verification_id": "abc-123", "expires_at": "...", "is_demo": false }
# Step 2: Redirect user to:
# https://truelens-2.polsia.app/verify?id=abc-123
# Step 3: Complete (after user finishes scan)
curl -X POST https://truelens-2.polsia.app/api/verify/complete \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"verification_id":"abc-123"}'
# → { "success": true, "badge_url": "https://truelens-2.polsia.app/badge/abc-123" }
// Step 1: Init a verification session (from your server)
const init = await fetch('https://truelens-2.polsia.app/api/verify/init', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.TRUELENS_API_KEY },
body: JSON.stringify({})
}).then(r => r.json());
// Step 2: Redirect user to complete the face scan
res.redirect(`https://truelens-2.polsia.app/verify?id=${init.verification_id}`);
// Step 3: After callback — mark verification complete
const result = await fetch('https://truelens-2.polsia.app/api/verify/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.TRUELENS_API_KEY },
body: JSON.stringify({ verification_id: init.verification_id })
}).then(r => r.json());
console.log(result.badge_url); // store on user record
import os, requests
API_KEY = os.environ['TRUELENS_API_KEY']
BASE = 'https://truelens-2.polsia.app'
headers = {'Content-Type': 'application/json', 'X-API-Key': API_KEY}
# Step 1: Init
init = requests.post(f'{BASE}/api/verify/init', headers=headers, json={}).json()
verification_id = init['verification_id']
# Step 2: Redirect user to:
# f"{BASE}/verify?id={verification_id}"
# Step 3: Complete (call after user finishes scan)
result = requests.post(
f'{BASE}/api/verify/complete',
headers=headers,
json={'verification_id': verification_id}
).json()
print(result['badge_url']) # store on user record
Endpoints
Creates a new verification session. Returns a verification_id that you pass to the hosted verification page.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| demo | boolean | optional | Set true to create a demo session (doesn't count against quota). Default: false. |
Response
{
"verification_id": "a1b2c3d4-e5f6-...",
"created_at": "2025-01-15T10:23:45.000Z",
"expires_at": "2026-01-15T10:23:45.000Z",
"is_demo": false
}
| Field | Type | Description |
|---|---|---|
| verification_id | string (UUID) | Unique session ID. Pass as ?id= query param to the verify page. |
| created_at | string (ISO 8601) | Session creation timestamp. |
| expires_at | string (ISO 8601) | Session expiry (12 months from creation). |
| is_demo | boolean | Whether this is a demo session. |
Marks a pending verification as completed. Call this from your backend after the user has passed the liveness check on the hosted page. Returns a badge URL — a publicly-accessible proof-of-human link you can store on the user record.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| verification_id | string | required | The verification_id returned by /init. |
Response
{
"success": true,
"verification_id": "a1b2c3d4-e5f6-...",
"expires_at": "2026-01-15T10:23:45.000Z",
"is_demo": false,
"badge_url": "https://truelens-2.polsia.app/badge/a1b2c3d4-..."
}
| Field | Type | Description |
|---|---|---|
| success | boolean | Always true on a successful complete. |
| badge_url | string (URL) | Public URL to the TrueLens verified badge. Display on profile pages or store on the user record as proof-of-human. |
| expires_at | string (ISO 8601) | Badge validity date. |
Retrieves the current status of a verification session. Useful for polling from a frontend after redirecting the user to the hosted verification page, or for webhook-free integrations where you want to check completion before granting access.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| sessionId | string | required | The verification_id returned by /init. |
Request Headers
| Header | Required | Description |
|---|---|---|
| X-API-Key | required | Your TrueLens API key. |
Response
{
"verification_id": "a1b2c3d4-e5f6-...",
"status": "pending",
"created_at": "2026-01-15T10:20:00.000Z",
"expires_at": null
}
{
"verification_id": "a1b2c3d4-e5f6-...",
"status": "completed",
"created_at": "2026-01-15T10:20:00.000Z",
"expires_at": "2026-01-15T10:23:45.000Z",
"badge_url": "https://truelens-2.polsia.app/badge/a1b2c3d4-..."
}
| Status Value | Meaning |
|---|---|
| pending | User has not yet completed the face scan. |
| completed | Verification passed. badge_url is present. |
| expired | Session timed out before the user completed verification. Create a new session with /init. |
Code Examples
curl https://truelens-2.polsia.app/api/verify/status/a1b2c3d4-e5f6-... \
-H "X-API-Key: YOUR_API_KEY"
const sessionId = 'a1b2c3d4-e5f6-...';
const poll = async () => {
const res = await fetch(
`https://truelens-2.polsia.app/api/verify/status/${sessionId}`,
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await res.json();
if (data.status === 'completed') {
console.log('Verified! Badge URL:', data.badge_url);
} else if (data.status === 'pending') {
setTimeout(poll, 2000); // poll every 2 seconds
} else {
console.log('Session expired. Start a new one.');
}
};
poll();
import requests, time
BASE = 'https://truelens-2.polsia.app'
API_KEY = 'YOUR_API_KEY'
session_id = 'a1b2c3d4-e5f6-...'
while True:
r = requests.get(
f'{BASE}/api/verify/status/{session_id}',
headers={'X-API-Key': API_KEY}
)
data = r.json()
if data['status'] == 'completed':
print('Badge URL:', data['badge_url'])
break
elif data['status'] == 'expired':
print('Session expired. Create a new one.')
break
else:
time.sleep(2) # poll every 2 seconds
Rate Limits & Pricing
TrueLens uses per-account rate limits to ensure fair usage. Limits apply to live API keys — sandbox endpoints are unrestricted.
| Limit | Value | Notes |
|---|---|---|
| Verifications / month | Varies by plan | Starter: 500 / mo. Pro: 5,000 / mo. See pricing. |
| Requests / minute | 60 req / min | Per API key. Burst allowance for short spikes. |
| Concurrent sessions | 100 active | Sessions expire after 10 minutes if not completed. |
Rate Limit Headers
Every response includes these headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per minute allowed for your key. |
| X-RateLimit-Remaining | Requests remaining in the current window. |
| X-RateLimit-Reset | Unix timestamp when the window resets. |
Error Codes
All errors return a JSON body with an error field.
| HTTP Status | Error | Description |
|---|---|---|
| 400 | Missing verification_id | The verification_id field is absent from the request body. |
| 401 | Missing API key | No X-API-Key header was provided. |
| 401 | Invalid API key | The key doesn't match any active account. |
| 403 | Subscription inactive | Your subscription has expired or been cancelled. Renew here → |
| 404 | Verification not found or already completed | The session ID doesn't exist, belongs to a different API key, or was already completed. |
| 500 | Internal server error | Something went wrong on our end. Retry after a moment. If persistent, contact support. |
Example Error Response
{ "error": "Invalid API key" }
Try It — Interactive Sandbox
Hit the live API directly from this page. No API key needed — these sandbox endpoints return realistic demo responses without touching production data.
/api/sandbox/ prefix — safe to call with no auth. Production endpoints require your X-API-Key header.
Ready to integrate?
Get your API key in 2 minutes. Starter plan includes 500 verifications/month.
Get Your API Key →