Validate a Third-Party Identity Payload
KikoffSoftware Engineer · Technical ScreenLast updated
Implement a pipeline that validates a third-party identity verification response against schema requirements and business rules while returning sanitized failure reason codes.
Validate a Third-Party Identity Payload
Fintech applications routinely ingest identity verification results from external vendors. Before granting an applicant access to credit products, the system must validate the vendor's payload against strict schema expectations and core business rules.
Write a function validate_identity_payload(payload: dict, blocked_codes: set[str]) -> tuple[bool, str] that processes an incoming identity payload and returns a boolean indicating whether the verification passed, along with a standardized reason string.
Schema Requirements
The payload must be a dictionary with the following top-level keys and types:
"status"(str): Must be present."matches"(dict): Must contain four required keys with boolean values:"name","dob","ssn", and"address"."message_codes"(list[str]): A list of vendor-provided status or alert codes.
If the payload is not a dictionary, is missing required keys, or contains invalid types for these fields, return (False, "INVALID_SCHEMA").
Business Rules
Evaluate rules in the following order once the schema is confirmed valid:
- Vendor Status: If
payload["status"] != "COMPLETE", return(False, "STATUS_INCOMPLETE"). - Blocked Codes: If any code in
payload["message_codes"]exists inblocked_codes, return(False, "BLOCKED_CODE"). - Required Matches: All four match fields (
name,dob,ssn,address) inpayload["matches"]must beTrue. If any isFalse, return(False, "MATCH_FAILED"). - Success: If all checks pass, return
(True, "SUCCESS").
Interface
def validate_identity_payload(payload: dict, blocked_codes: set[str]) -> tuple[bool, str]:
pass
Constraints
payloadwill contain at most 50 keys.blocked_codescontains up to 1,000 strings.message_codescontains up to 50 strings.- All string comparisons are case-sensitive.
Examples
Example 1
payload = {
"status": "COMPLETE",
"matches": {
"name": True,
"dob": True,
"ssn": True,
"address": True
},
"message_codes": ["ADDR_CONFIRMED", "PHONE_VERIFIED"]
}
blocked_codes = {"FRAUD_ALERT", "DECEASED"}
# Output: (True, "SUCCESS")
Explanation: Schema is intact, status is complete, no blocked codes are present, and all four matches are True.
Example 2
payload = {
"status": "COMPLETE",
"matches": {
"name": True,
"dob": True,
"ssn": True,
"address": False
},
"message_codes": ["FRAUD_ALERT"]
}
blocked_codes = {"FRAUD_ALERT", "DECEASED"}
# Output: (False, "BLOCKED_CODE")
Explanation: Even though address matching failed, the blocked code rule is evaluated first.
Hints
Hint 1
Separate your validation into distinct phases: schema/type checking, vendor completion checking, security/risk filtering, and attribute matching.
Hint 2
Verify not only that the required keys exist, but also that their nested types (such as booleans for matches and strings for message codes) are correct before inspecting values.
Hint 3
Use a set lookup for blocked code detection to keep the filtering step running in O(K) time, where K is the number of message codes in the payload.
Follow-up questions
- How would you refactor this function to collect and return all failed validation reasons rather than short-circuiting on the first failure?
- How would you support schema versioning if different identity providers returned distinct payload structures?
- How can you ensure sensitive applicant data (PII) is safely masked if you need to log failed validation payloads for debugging?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.