KYC Verification
This guide explains how to implement the KYC (Know Your Customer) verification process for members in your application. KYC verification is required before members can receive commission payouts.
Overview
The MLM Platform supports two KYC providers:
Provider Description Use Case Manual Document upload with admin review Default option, full control over verification Sumsub Automated verification via Sumsub SDK Faster verification, reduced admin workload
The KYC provider is configured at the tenant level. Contact support to switch providers.
KYC Verification Flow
The following flowchart illustrates the complete KYC verification process:
Implementation Guide
Step 1: Start KYC Verification
Begin the KYC process by calling the start endpoint:
POST /api/v1/members/{userId}/kyc/start
Response for Manual KYC:
{
"kycRecordId" : "3c90c3cc-0d44-4b50-8888-8dd25736052a" ,
"provider" : "manual" ,
"status" : "not_started" ,
"uploadUrl" : "https://api.mlm-platform.com/api/v1/members/{userId}/kyc/documents" ,
"requiredDocuments" : [
{
"documentType" : "government_id_front" ,
"label" : "Government ID (Front)" ,
"description" : "Front side of your government-issued ID" ,
"required" : true ,
"acceptedFormats" : [ "image/jpeg" , "image/png" , "application/pdf" ]
},
{
"documentType" : "government_id_back" ,
"label" : "Government ID (Back)" ,
"description" : "Back side of your government-issued ID" ,
"required" : true ,
"acceptedFormats" : [ "image/jpeg" , "image/png" , "application/pdf" ]
},
{
"documentType" : "selfie" ,
"label" : "Selfie with ID" ,
"description" : "A clear photo of yourself holding your ID" ,
"required" : true ,
"acceptedFormats" : [ "image/jpeg" , "image/png" ]
}
],
"message" : "Please upload the required documents to complete verification."
}
Response for Sumsub KYC:
{
"kycRecordId" : "3c90c3cc-0d44-4b50-8888-8dd25736052a" ,
"provider" : "sumsub" ,
"status" : "not_started" ,
"sdkConfig" : {
"accessToken" : "sbx:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expiresAt" : "2024-01-15T12:30:00Z" ,
"flowName" : "basic-kyc-flow" ,
"applicantId" : "65a1b2c3d4e5f6g7h8i9j0"
},
"message" : "Complete verification using the Sumsub widget."
}
Step 2: Upload Documents (Manual KYC)
For manual KYC, upload each required document using a two-step process:
2a. Get a Signed Upload URL
POST /api/v1/members/{userId}/kyc/documents/upload-url
Content-Type: application/json
{
"documentType" : "government_id_front",
"fileName" : "drivers-license-front.jpg",
"mimeType" : "image/jpeg"
}
Response:
{
"uploadUrl" : "https://storage.supabase.co/..." ,
"filePath" : "tenant-123/user-456/government_id_front_abc123.jpg" ,
"expiresInSeconds" : 3600
}
2b. Upload the File
Upload the file directly to the signed URL:
PUT {uploadUrl}
Content-Type: image/jpeg
[binary file data]
2c. Record the Document
After successful upload, record the document metadata:
POST /api/v1/members/{userId}/kyc/documents
Content-Type: application/json
{
"documentType" : "government_id_front",
"fileName" : "drivers-license-front.jpg",
"mimeType" : "image/jpeg",
"fileSize" : 245678,
"filePath" : "tenant-123/user-456/government_id_front_abc123.jpg"
}
Repeat steps 2a-2c for each document in the requiredDocuments array.
Step 3: Check KYC Status
Poll the status endpoint to track verification progress:
GET /api/v1/members/{userId}/kyc
Response:
{
"id" : "3c90c3cc-0d44-4b50-8888-8dd25736052a" ,
"status" : "pending" ,
"provider" : "manual" ,
"documents" : [
{
"id" : "doc-1" ,
"documentType" : "government_id_front" ,
"fileName" : "drivers-license-front.jpg" ,
"status" : "pending" ,
"createdAt" : "2024-01-15T10:00:00Z"
},
{
"id" : "doc-2" ,
"documentType" : "government_id_back" ,
"fileName" : "drivers-license-back.jpg" ,
"status" : "pending" ,
"createdAt" : "2024-01-15T10:01:00Z"
}
],
"createdAt" : "2024-01-15T10:00:00Z"
}
KYC Status Values
Status Description Next Action not_startedKYC record created, no documents uploaded Upload required documents pendingDocuments submitted, awaiting admin review Wait for admin decision approvedKYC verification approved Member can receive payouts rejectedKYC verification rejected Review rejection reason resubmit_requiredAdditional documents or corrections needed Upload corrected documents
Admin Review Process
Administrators review KYC submissions through the Admin Dashboard or API.
List Pending Reviews
GET /api/v1/admin/kyc/pending
View KYC Details
GET /api/v1/admin/kyc/{kycId}
Download Document for Review
GET /api/v1/admin/kyc/documents/{documentId}
Approve KYC
POST /api/v1/admin/kyc/{kycId}/approve
Content-Type: application/json
{
"notes" : "All documents verified successfully"
}
Reject KYC
POST /api/v1/admin/kyc/{kycId}/reject
Content-Type: application/json
{
"reason" : "ID document is expired. Please upload a valid, non-expired ID."
}
Request Resubmission
POST /api/v1/admin/kyc/{kycId}/request-resubmit
Content-Type: application/json
{
"reason" : "Selfie photo is blurry. Please upload a clearer photo.",
"requiredDocuments" : [ "selfie" ]
}
For supported document types, the platform automatically extracts data using OCR:
Document Type Extracted Fields government_id_frontFull name, date of birth, address government_id_backAddress (if present) passportFull name, date of birth, nationality proof_of_addressAddress, document date
Extracted data is available in the admin review interface and can be edited before approval.
Best Practices
Validate Before Upload Check file size and format on the client before uploading to avoid rejected uploads.
Show Progress Display upload progress and status updates to keep members informed.
Handle Errors Gracefully Provide clear error messages when uploads fail or documents are rejected.
Secure File Handling Never store KYC documents on your own servers. Use the signed URLs provided.
Error Handling
Error Code Description Resolution 400Invalid request (missing fields, invalid format) Check request body matches schema 401Unauthorized Verify API key is valid 403Forbidden Ensure user belongs to your tenant 404KYC record or document not found Verify the ID is correct 409KYC already in progress or completed Check current status before starting 413File too large Reduce file size (max 10MB)
Webhooks
Configure webhooks to receive real-time notifications when KYC status changes:
Event Description kyc.submittedMember submitted all required documents kyc.approvedAdmin approved the KYC verification kyc.rejectedAdmin rejected the KYC verification kyc.resubmit_requiredAdmin requested document resubmission
See the Webhooks Guide for configuration details.
Complete Code Example
Here’s a complete example of implementing KYC document upload in JavaScript:
async function uploadKycDocuments ( userId , files ) {
const apiKey = process . env . MLM_API_KEY ;
const baseUrl = 'https://api.mlm-platform.com/api/v1' ;
// Step 1: Start KYC
const startResponse = await fetch (
` ${ baseUrl } /members/ ${ userId } /kyc/start` ,
{
method: 'POST' ,
headers: { 'x-tenant-api-key' : apiKey }
}
);
const { kycRecordId , requiredDocuments } = await startResponse . json ();
// Step 2: Upload each document
for ( const doc of requiredDocuments ) {
const file = files [ doc . documentType ];
if ( ! file ) continue ;
// 2a: Get signed URL
const urlResponse = await fetch (
` ${ baseUrl } /members/ ${ userId } /kyc/documents/upload-url` ,
{
method: 'POST' ,
headers: {
'x-tenant-api-key' : apiKey ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
documentType: doc . documentType ,
fileName: file . name ,
mimeType: file . type
})
}
);
const { uploadUrl , filePath } = await urlResponse . json ();
// 2b: Upload file
await fetch ( uploadUrl , {
method: 'PUT' ,
headers: { 'Content-Type' : file . type },
body: file
});
// 2c: Record document
await fetch (
` ${ baseUrl } /members/ ${ userId } /kyc/documents` ,
{
method: 'POST' ,
headers: {
'x-tenant-api-key' : apiKey ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
documentType: doc . documentType ,
fileName: file . name ,
mimeType: file . type ,
fileSize: file . size ,
filePath
})
}
);
}
return kycRecordId ;
}
Next Steps