You need three things: an API key, the SDK, and 15 minutes. Here’s the complete integration path with code examples in Python, Node, and cURL.

Prerequisites: An API key from your dashboard, an HTTP client, and a JWKS-aware JWT library (any standard one will do). Three endpoints — /enroll, /verify, /delete. Every snippet below works with plain HTTP if you’d rather skip the SDK.

Three endpoints. One SDK. Fifteen minutes. Biometric step-up verification running in your staging environment, ready to go live whenever you are.

1. Install the SDK

Python

pip install lorica-sdk

Node.js

npm install lorica-node

No SDK? Use cURL

Every endpoint works with raw HTTP. No SDK required. The examples below show all three approaches.

2. Enroll a user

Enrollment captures the user’s face and stores an encrypted embedding. This happens once — typically during onboarding or the first time they encounter a high-risk action.

Python

from lorica import LoricaClient
import base64

client = LoricaClient(api_key="lk_demo_REPLACE_WITH_YOUR_KEY")

# Read face image and encode
with open("face.jpg", "rb") as f:
    image_b64 = base64.b64encode(f.read()).decode()

result = client.enroll(
    user_id="usr_8f3a2b1c",
    image=image_b64
)
print(result)
# {"enrolled": true, "user_id": "usr_8f3a2b1c"}

Node.js

const Lorica = require('lorica-node');
const fs = require('fs');

const client = new Lorica({ apiKey: 'lk_demo_REPLACE_WITH_YOUR_KEY' });

const image = fs.readFileSync('face.jpg').toString('base64');

const result = await client.enroll({
    userId: 'usr_8f3a2b1c',
    image: image
});
console.log(result);
// { enrolled: true, userId: 'usr_8f3a2b1c' }

cURL

curl -X POST https://api.loricaapi.com/enroll \
  -H "X-API-Key: lk_demo_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_8f3a2b1c",
    "image": "'$(base64 -w0 face.jpg)'"
  }'

3. Verify a transaction

This is the call that matters. When a user initiates a high-risk action — a withdrawal, a large transfer, a whitelist change — your platform captures a fresh face image and sends it to Lorica with the action context. The response is a signed JWT proving the human authorized that specific action.

Python

# Capture fresh image from webcam or mobile camera
with open("live_capture.jpg", "rb") as f:
    live_image = base64.b64encode(f.read()).decode()

result = client.verify(
    user_id="usr_8f3a2b1c",
    image=live_image,
    action_context="withdraw_50000_usdc",
    liveness_mode="passive"
)

if result["match"]:
    jwt_token = result["jwt"]
    print(f"Verified! Confidence: {result['confidence']}")
    # Proceed with the withdrawal
    # Store the JWT as proof of authorization
else:
    print(f"Rejected: {result['rejection_reason']}")
    # Block the withdrawal
    # Alert the security team

Node.js

const liveImage = fs.readFileSync('live_capture.jpg')
    .toString('base64');

const result = await client.verify({
    userId: 'usr_8f3a2b1c',
    image: liveImage,
    actionContext: 'withdraw_50000_usdc',
    livenessMode: 'passive'
});

if (result.match) {
    console.log(`Verified! Confidence: ${result.confidence}`);
    // Proceed with withdrawal, store JWT
} else {
    console.log(`Rejected: ${result.rejectionReason}`);
    // Block withdrawal, alert security
}

cURL

curl -X POST https://api.loricaapi.com/verify \
  -H "X-API-Key: lk_demo_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_8f3a2b1c",
    "image": "'$(base64 -w0 live_capture.jpg)'"
    "action_context": "withdraw_50000_usdc",
    "liveness_mode": "passive"
  }'

What you get back

A successful verification returns a signed JWT containing everything your auditors need:

{
  "match": true,
  "confidence": 0.94,
  "liveness_score": 0.91,
  "jwt": "eyJhbGciOiJIUzI1NiIs...",
  "verification_id": "ver_a1b2c3d4",
  "decoded_jwt": {
    "user_id": "usr_8f3a2b1c",
    "action_verified": "withdraw_50000_usdc",
    "confidence": 0.94,
    "liveness_score": 0.91,
    "liveness_method": "passive",
    "verified_at": "2026-04-01T14:32:07Z",
    "capture_hash": "a3f8c912...",
    "exp": 1743520627
  }
}

Store the JWT alongside the transaction record. It’s your cryptographic proof that a specific human authorized a specific action at a specific time.

Where to put the call

The Lorica verification call goes between the user clicking “Confirm” and the transaction executing. In code, that looks like:

# Your existing withdrawal flow
def process_withdrawal(user_id, amount, destination):
    # Step 1: Existing checks (balance, limits, etc.)
    validate_withdrawal(user_id, amount, destination)

    # Step 2: Capture face (your frontend sends this)
    face_image = request.json["face_image"]

    # Step 3: Lorica verification (NEW — add this)
    result = lorica_client.verify(
        user_id=user_id,
        image=face_image,
        action_context=f"withdraw_{amount}_{currency}",
        liveness_mode="passive"  # or dual_frame/motion
    )

    if not result["match"]:
        raise VerificationFailed(result["rejection_reason"])

    # Step 4: Execute (existing code)
    execute_withdrawal(user_id, amount, destination)

    # Step 5: Store proof (NEW — add this)
    store_verification_proof(
        transaction_id=txn.id,
        jwt=result["jwt"]
    )

That’s 6 lines of new code. Everything else in your flow stays exactly the same.

Common error codes

  • 401 — Invalid or missing API key. Check the X-API-Key header.
  • 400 — Malformed request. Missing user_id, invalid base64, or unsupported image format.
  • 404 — User not enrolled. Call POST /enroll first.
  • 413 — Image too large. Maximum 5MB.
  • 429 — Rate limited. /verify allows 30 requests/minute.
  • 422 — Face not detected, image too blurry, multiple faces, or quality below threshold.

That’s it

Three endpoints. One SDK. Fifteen minutes. Biometric step-up verification running in your staging environment, ready to go live whenever you are.

If you’d rather not write the integration yourself: I’ll do it for you. Send me access to your staging environment and I’ll have Lorica running on your withdrawal flow in 2 hours. Zero engineering time from your team.

Start now: Express interest — sandbox key delivered immediately. Full docs: loricaapi.com/docs