Product Case Study
AI-Powered Document Verification for Merchant Onboarding
I led the design and rollout of an AI-driven document-verification workflow for partner KYC. It cut manual verification effort by 60% and tightened fraud and RBI compliance controls.
Problem Statement
Shop-photo verification during retailer onboarding was only manually reviewed 33% of the time. The rest auto-approved. That auto-approve path was gameable: a retailer could keep retrying until a submission slipped through, undermining the KYC and fraud controls the photo step existed for.
The Verification Model
We moved shop-photo review from a mostly manual spot-check to an automated decision engine built on an internal ML tool, trained on two years of the company's own manual shop-photo verification calls. It scores every submission against a fixed rule set before a human ever sees it.
| Check | Field | Required | Rule | Rejects with |
|---|---|---|---|---|
| Liveness (outside) | liveness.image1 | Yes | Must be a live, real-time capture | “Please click the outside shop photo again in real time.” |
| Liveness (inside) | liveness.image2 | Yes | Must be a live, real-time capture | “Please click the inside shop photo again in real time.” |
| Is a shop | isShop | Yes | Image must depict a shop | “The uploaded photo does not appear to be of a shop.” |
| Shop front visible | shopFrontPresent | Yes | Front must be clearly shown | “Shop front is not clearly visible.” |
| Shop inside visible | shopInsidePresent | Yes | Inside must be clearly shown | “Shop inside area is not clearly visible.” |
| Inside image valid | shopInsideValid | Yes | Passes the internal ML tool's validity check | “Inside shop photo is not valid.” |
| Shop open | shopOpen | Yes | Shop must be operational at capture time | “Shop appears to be closed.” |
| Shop type | shopType | Yes | Must be a permanent structure | “This shop setup is not eligible for onboarding.” |
| Inside/outside match | interImageNobMatch | Yes | Both photos must belong to the same shop | “Inside and outside shop photos do not appear to belong to the same shop.” |
| Inventory present | inventory.inventoryPresent | Yes | Stock must be visible to validate an active business | “Shop inventory is not clearly visible.” |
| Business category | categories[*].mcc | Yes | Detected category must match an Aadhaar Pay–allowed MCC | “This business category is currently not eligible for onboarding.” |
| Shopkeeper face visible | shopkeeper.*.shopkeeperPresent | Yes | Applicant's face visible in at least one photo | “Shopkeeper/applicant face is not clearly visible.” |
| Face match | findFace.faceFound / matchScore | Yes | Detected face must match ID photo above a confidence threshold | “Face verification could not be completed or face match score is low.” |
| Matched face crop | findFace.matchingFaceCrop | Yes | A usable face crop must be generated | “Matched face crop is not available.” |
| Age check | idAgeRange.low/high | Used for CAF | Confirms applicant is an eligible adult; ambiguous cases route for review | “The applicant may be below eligible age.” |
| Name match | nameMatch.match | No | Captured shop name should match the entered name | “Shop name could not be matched with the entered shop name.” |
| Name match score | nameMatch.matchScore | No | Must clear a configurable confidence threshold | “Shop name match is low.” |
| Face review flag | findFace.toBeReviewed | No | Face check should not be auto-flagged for manual review | “Face validation requires review.” |
| Matched image | findFace.foundIn | No | Identifies whether the face was found in the front or inside photo | “Face could not be mapped to shop front or inside photo.” |
| Banner present | banner.bannerPresent | No | Supporting signal, not a hard gate | “Shop board/banner is not clearly visible.” |
| Banner type | banner.bannerType | No | Permanent signage preferred | “Temporary banner/signage detected.” |
| Contact number | shopContactNumbers.valid | No | Supporting field if captured | “Shop contact number could not be validated.” |
| GST | shopGstNumber.valid | No | Optional, not required for small shops | “GST details could not be validated.” |
Rollout
The rollout was phased by circle, not switched on nationally. It went live in 3 circles in September, then expanded pan-India by December. That gave room to tune thresholds, especially the name-match score, against real rejection patterns before scaling further.
Outcome
Manual verification effort dropped 60%, and the retry-until-approved loophole in the old spot-check process closed for good. Rejected photos still route to a human reviewer. The model isn't a black-box gate, it's a triage layer that clears the obvious cases and escalates the rest. Fraud controls and RBI KYC compliance both got stronger as a result.