Warddocs
Cookbooks

KYC onboarding

A fintech runs its own onboarding screens and wants one call that says verified or not, and why. This recipe uses the KYC capability with the Python SDK; the JavaScript SDK has the same methods in camelCase.

from ward import Ward
client = Ward()

def start(applicant):
    e = client.kyc.send_code("email", applicant["email"], locale="en")
    p = client.kyc.send_code("sms", applicant["phone"], locale="en")
    return {"email": e.challenge_id, "phone": p.challenge_id}        # keep in the onboarding session

def confirm(challenges, email_code, sms_code):
    ok_e = client.kyc.confirm_code(challenges["email"], email_code).verified
    ok_p = client.kyc.confirm_code(challenges["phone"], sms_code).verified
    return ok_e and ok_p

def decide(applicant, challenges):
    r = client.kyc.verify(applicant, email_challenge_id=challenges["email"],
                          phone_challenge_id=challenges["phone"], locale="en",
                          external_ref=applicant["id"])
    if r.status == "VERIFIED":
        open_account(applicant, verification_id=r.verification_id)
    elif r.status == "REVIEW":
        queue_for_compliance(r.verification_id, [x["detail"] for x in r.reasons])
        tell_applicant("We're reviewing your application.")
    else:
        tell_applicant(r.reason)       # user_message: safe to show
    return r

Handling reasons in the UI

Map the reasons the applicant can fix to the field that needs fixing (field: email, phone, document) and show user_message next to it:

Reason UI action
EMAIL_DOMAIN_TYPO Pre-fill the suggested address
EMAIL_DISPOSABLE, EMAIL_ROLE_ACCOUNT Ask for a personal email
PHONE_VOIP, PHONE_NOT_PERSONAL, PHONE_NOT_SMS_CAPABLE Ask for a mobile number
*_NOT_CONFIRMED Resend the code
SANCTIONS_*, PEP_MATCH, CONTACT_* Show the generic message only; route to compliance

Close the loop

Months later, when an account turns out fraudulent or clean, report it:

client.kyc.outcome(r.verification_id, "synthetic_identity")

Outcomes build your account's contact history and train its contact-risk model.