Challenge-response liveness detection that requires the user to perform specific actions (turn head, blink, smile) to prove they are a real, live person. This is stronger than passive liveness and is recommended for high-security onboarding flows.
Create a session — the server returns a session_id and a list of challenges
Submit frames — send camera frames as the user performs each challenge
Check results — each frame submission returns whether the challenge passed
Session completes — after all challenges pass, the session is marked as completed with a final is_live verdict
Challenge Instruction TURN_LEFTTurn your head to the left TURN_RIGHTTurn your head to the right LOOK_UPLook upward LOOK_DOWNLook downward BLINKBlink your eyes SMILESmile OPEN_MOUTHOpen your mouth
Challenges are randomly selected when a session is created. The number of challenges is configurable (default: 3).
POST /api/v1/liveness/sessions
Parameter Type Required Description num_challengesint No Number of challenges (default: 3) timeout_secondsfloat No Seconds per challenge (default: 5.0)
curl -X POST " http://localhost:8000/api/v1/liveness/sessions?num_challenges=3&timeout_seconds=5.0 " \
"session_id" : " a1b2c3d4-e5f6-7890-abcd-ef1234567890 " ,
{ "type" : " TURN_LEFT " , "instruction" : " Turn your head to the left " , "timeout_seconds" : 5.0 },
{ "type" : " BLINK " , "instruction" : " Blink your eyes " , "timeout_seconds" : 5.0 },
{ "type" : " SMILE " , "instruction" : " Smile " , "timeout_seconds" : 5.0 }
POST /api/v1/liveness/sessions/{session_id}/frame
Parameter Type Required Description imagefile Yes Camera frame (JPEG, PNG)
curl -X POST http://localhost:8000/api/v1/liveness/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/frame \
"session_id" : " a1b2c3d4-e5f6-7890-abcd-ef1234567890 " ,
"challenge_type" : " TURN_LEFT " ,
"challenges_remaining" : 2 ,
"session_complete" : false ,
When the final challenge passes, session_complete becomes true and is_live contains the final verdict:
"session_id" : " a1b2c3d4-e5f6-7890-abcd-ef1234567890 " ,
"challenge_type" : " SMILE " ,
"challenges_remaining" : 0 ,
"session_complete" : true ,
GET /api/v1/liveness/sessions/{session_id}
curl http://localhost:8000/api/v1/liveness/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
"session_id" : " a1b2c3d4-e5f6-7890-abcd-ef1234567890 " ,
{ "type" : " TURN_LEFT " , "instruction" : " Turn your head to the left " , "timeout_seconds" : 5.0 },
{ "type" : " BLINK " , "instruction" : " Blink your eyes " , "timeout_seconds" : 5.0 },
{ "type" : " SMILE " , "instruction" : " Smile " , "timeout_seconds" : 5.0 }
DELETE /api/v1/liveness/sessions/{session_id}
curl -X DELETE http://localhost:8000/api/v1/liveness/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
"cancelled" : " a1b2c3d4-e5f6-7890-abcd-ef1234567890 "
State Description pendingSession created, no frames submitted yet in_progressAt least one frame submitted, challenges remaining completedAll challenges passed, is_live verdict available failedA challenge timed out or failed definitively expiredSession exceeded its TTL
Field Type Description session_idstringSession identifier challenge_typestring|nullCurrent challenge type passedboolWhether the current challenge passed confidencefloatConfidence score 0-1 challenges_remainingintNumber of challenges left session_completebooltrue when all challenges are doneis_livebool|nullFinal liveness verdict (only set when complete) statestringCurrent session state
Submit frames at 5-10 FPS for smooth challenge detection
Show the challenge instruction to the user in your UI before capturing
Handle expired and failed states gracefully — create a new session to retry
Set timeout_seconds based on your UX; 5 seconds works well for most users
Use 3 challenges for standard security, 5 for high-security flows
Combine with face comparison to ensure the same person completes the session