API REFERENCE
JWT Structure
The Lorica JWT is the auditable artifact returned by /v1/verify.
It is HMAC-SHA256 signed with the per-tenant signing secret. Validate it
locally on every verify response.
Header
{
"alg": "HS256",
"typ": "JWT"
} Payload — claim list
| Claim | Type | Description |
|---|---|---|
iss | string | Always "lorica.api" |
sub | string | Your user_id from the verify request |
act | string | The action class from the verify request |
amt | string | Optional. Action amount as decimal string |
asset | string | Optional. Asset symbol |
live | string | Liveness mode used: passive, dual_frame, or active |
match | boolean | Whether the live face matched the enrolled embedding above threshold |
score | number | Confidence score, 0.0–1.0 |
iat | number | Issued-at, Unix seconds |
exp | number | Expiry, Unix seconds. Always iat + 60 |
verification_id | string | Server-side verification record ID, also returned in response body |
Signature
The signature is HMAC-SHA256 of base64url(header) + "." + base64url(payload)
using your per-tenant signing secret. The default base64url-encoded signature is 43
characters; the visible 40-character "..." truncation in the dashboard and demo is
a display convention, not a length limit.
Validate locally
# Python
import jwt
import os
claims = jwt.decode(
response["jwt"],
os.environ["LORICA_SIGNING_SECRET"],
algorithms=["HS256"],
issuer="lorica.api",
)
if not claims["match"] or claims["score"] < 0.9:
raise PermissionError("verification failed") // Node
import jwt from 'jsonwebtoken';
const claims = jwt.verify(
response.jwt,
process.env.LORICA_SIGNING_SECRET,
{ algorithms: ['HS256'], issuer: 'lorica.api' }
);
if (!claims.match || claims.score < 0.9) {
throw new Error('verification failed');
} Audit note
Store the JWT alongside the transaction or action record. The JWT plus your
per-tenant signing secret is the proof an underwriter or regulator validates
if a transaction is later disputed. Without the JWT, the verification
happened — but you can't prove it after the fact.