API
Workflows
The configuration a session runs: steps, thresholds, countries and the decision mode.
A workflow is JSON stored with the app and edited in the console's workflow builder, which validates it as you type. Each session takes a snapshot when it is created, so editing a workflow never changes a session in flight. Edits increment the workflow's version and are audited.
{
"steps": {
"document": { "enabled": true, "allowed_types": ["passport","id_card","driving_licence","residence_permit","aadhaar","pan","voter_id"], "allowed_countries": [], "reject_expired": true, "max_attempts": 3 },
"liveness": { "enabled": true, "challenges": 3, "max_attempts": 3 },
"face_match": { "enabled": true, "threshold": 0.363, "review_threshold": 0.30 },
"aadhaar": { "enabled": false, "methods": ["secure_qr","offline_xml"], "max_xml_age_days": 3, "require_signature": true },
"pan": { "enabled": false, "require_card_image": false },
"email": { "enabled": false },
"aml": { "enabled": true, "lists": ["ofac_sdn","un_consolidated"], "match_threshold": 0.90, "review_threshold": 0.82 },
"age": { "enabled": false, "min_age": 18 },
"duplicate": { "enabled": true, "face_threshold": 0.55, "scope": "app" }
},
"decision": { "auto_decline": true },
"redirect_url": null
}Every setting
| Key | Default | Effect |
|---|---|---|
document.allowed_types | all seven | Which of passport, id_card, driving_licence, residence_permit, aadhaar, pan, voter_id the person may choose |
document.allowed_countries | [] (any) | ISO 3166-1 alpha-3 issuers accepted |
document.reject_expired | true | An expired document fails instead of passing with a warning |
liveness.challenges | 3 | Challenges per attempt, 1 to 4 |
face_match.threshold / review_threshold | 0.363 / 0.30 | Cosine similarity to pass / to go to review |
aadhaar.methods | both | secure_qr, offline_xml |
aadhaar.max_xml_age_days | 3 | Oldest Offline XML accepted |
aadhaar.require_signature | true | An invalid signature fails the step; without UIDAI certificates installed it goes to review (aadhaar_signature_unverified) |
pan.require_card_image | false | Ask for a photo of the PAN card as well as the number |
aml.lists | both | ofac_sdn, un_consolidated |
aml.match_threshold / review_threshold | 0.90 / 0.82 | Name score for a strong / any potential match; both go to review |
age.min_age | 18 | Minimum age in whole years |
duplicate.face_threshold | 0.55 | Face similarity counted as the same person |
decision.auto_decline | true | false sends failures to review instead of declining |
redirect_url | null | Default return URL when a session has no callback_url |
*.max_attempts | 3 | Tries per user step |
Validation
liveness.challengesmust be 1 to 4.face_match.review_thresholdmust be at mostface_match.threshold, andaml.review_thresholdat mostaml.match_threshold.- Countries are ISO 3166-1 alpha-3 codes; an empty list accepts any issuer.
- Aadhaar, PAN and voter ID are always issued by
IND. redirect_urlmust be an absolute http(s) URL.
Recipes
India: Aadhaar, PAN and a selfie
{ "steps": {
"document": { "enabled": false },
"aadhaar": { "enabled": true, "methods": ["secure_qr", "offline_xml"] },
"pan": { "enabled": true, "require_card_image": true },
"liveness": { "enabled": true, "challenges": 3 },
"face_match":{ "enabled": true },
"aml": { "enabled": true }
} }Face match then compares the selfie with the photo inside the UIDAI-signed artefact.
Age gate only
{ "steps": {
"document": { "enabled": true, "allowed_types": ["passport", "id_card", "driving_licence"] },
"liveness": { "enabled": true, "challenges": 2 },
"age": { "enabled": true, "min_age": 21 },
"aml": { "enabled": false }
} }Cautious: no automatic declines
{ "decision": { "auto_decline": false } }Every failure goes to the review queue with its reason, which suits low volumes or a new market while you learn your traffic.
Choosing thresholds
Each scored check has a pass threshold and a lower review threshold; scores between them go to a person. Widening the band sends more sessions to review and fewer to automatic decisions. Tune it on your own traffic, and note that thresholds are stored exactly as you type them.