Complete KYB Verification Workflow
gu1βs KYB workflow automates the entire business verification process from initial data collection to ongoing monitoring. This guide walks through each step with technical implementation details.Workflow Overview
Step 1: Initial Data Collection
What to Collect
Gather basic business information from your application form:- Company Name: Legal name and trade name
- Registration Number: Government-issued business registration
- Tax ID: EIN (US), CNPJ (Brazil), RFC (Mexico), etc.
- Incorporation Date: When the business was formed
- Country: Jurisdiction of incorporation
- Business Address: Registered office location
- Industry: Type of business activity
- Expected Transaction Volume: Monthly/annual estimates
Example Application Form
const businessApplication = {
legalName: "Tech Solutions Sociedade AnΓ΄nima",
tradeName: "Tech Solutions",
registrationNumber: "12.345.678/0001-90",
taxId: "12.345.678/0001-90",
incorporationDate: "2020-06-15",
country: "BR",
address: {
street: "Av. Paulista, 1000",
city: "SΓ£o Paulo",
state: "SP",
postalCode: "01310-100"
},
industry: "Software Development",
website: "https://techsolutions.com.br",
expectedMonthlyVolume: 250000,
businessDescription: "B2B SaaS platform for enterprise clients"
};
Step 2: Create Business Entity
Use the Entities API to create a company entity in gu1:curl -X POST http://api.gu1.ai/entities \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "company",
"externalId": "business_12345",
"name": "Tech Solutions Sociedade AnΓ΄nima",
"taxId": "12.345.678/0001-90",
"countryCode": "BR",
"entityData": {
"company": {
"legalName": "Tech Solutions Sociedade AnΓ΄nima",
"tradeName": "Tech Solutions",
"incorporationDate": "2020-06-15",
"industry": "Software Development",
"employeeCount": 50,
"revenue": 5000000
}
},
"attributes": {
"registrationNumber": "12.345.678/0001-90",
"website": "https://techsolutions.com.br",
"registeredAddress": "Av. Paulista, 1000, SΓ£o Paulo",
"expectedMonthlyVolume": 250000,
"applicationDate": "2024-10-03T10:00:00Z"
}
}'
async function createBusinessEntity(applicationData) {
const response = await fetch('http://api.gu1.ai/entities', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'company',
externalId: applicationData.businessId,
name: applicationData.legalName,
taxId: applicationData.taxId,
countryCode: applicationData.country,
entityData: {
company: {
legalName: applicationData.legalName,
tradeName: applicationData.tradeName,
incorporationDate: applicationData.incorporationDate,
industry: applicationData.industry,
employeeCount: applicationData.employeeCount,
revenue: applicationData.estimatedRevenue
}
},
attributes: {
registrationNumber: applicationData.registrationNumber,
website: applicationData.website,
registeredAddress: applicationData.address,
expectedMonthlyVolume: applicationData.expectedVolume,
applicationDate: new Date().toISOString()
}
})
});
const result = await response.json();
return result.entity;
}
import requests
def create_business_entity(application_data):
response = requests.post(
'http://api.gu1.ai/entities',
headers={
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
},
json={
'type': 'company',
'externalId': application_data['business_id'],
'name': application_data['legal_name'],
'taxId': application_data['tax_id'],
'countryCode': application_data['country'],
'entityData': {
'company': {
'legalName': application_data['legal_name'],
'tradeName': application_data['trade_name'],
'incorporationDate': application_data['incorporation_date'],
'industry': application_data['industry'],
'employeeCount': application_data.get('employee_count'),
'revenue': application_data.get('estimated_revenue')
}
},
'attributes': {
'registrationNumber': application_data['registration_number'],
'website': application_data.get('website'),
'registeredAddress': application_data['address'],
'expectedMonthlyVolume': application_data['expected_volume'],
'applicationDate': datetime.now().isoformat()
}
}
)
return response.json()['entity']
{
"success": true,
"entity": {
"id": "660e9511-f39c-52e5-b827-557766551111",
"externalId": "business_12345",
"type": "company",
"name": "Tech Solutions Sociedade AnΓ΄nima",
"riskScore": 0,
"status": "under_review",
"createdAt": "2024-10-03T10:00:00Z"
}
}
Step 3: Document Upload & Verification
Upload required business documents for verification:Required Documents
- Articles of Incorporation - Founding document
- Business License - Government-issued operating permit
- Tax Certificate - Proof of tax registration
- Proof of Address - Utility bill or bank statement
- Beneficial Ownership Declaration - UBO information
Upload Documents
async function uploadBusinessDocuments(entityId, documents) {
const documentUploads = [];
for (const doc of documents) {
const formData = new FormData();
formData.append('file', doc.file);
formData.append('documentType', doc.type);
formData.append('entityId', entityId);
const response = await fetch('http://api.gu1.ai/documents', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`
},
body: formData
});
documentUploads.push(await response.json());
}
return documentUploads;
}
// Usage
const documents = [
{ file: articlesOfIncorporation, type: 'articles_of_incorporation' },
{ file: businessLicense, type: 'business_license' },
{ file: taxCertificate, type: 'tax_certificate' },
{ file: proofOfAddress, type: 'proof_of_address' }
];
const uploadedDocs = await uploadBusinessDocuments(entityId, documents);
Step 4: AI Analysis & Risk Assessment
Request AI-powered analysis of the business entity:async function requestAIAnalysis(entityId) {
const response = await fetch(
`http://api.gu1.ai/entities/${entityId}/ai-analysis`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
analysisType: 'kyb_verification',
includeDocuments: true,
checkSanctions: true,
checkAdverseMedia: true
})
}
);
return await response.json();
}
{
"analysisId": "analysis_abc123",
"entityId": "660e9511-f39c-52e5-b827-557766551111",
"riskScore": 35,
"riskLevel": "medium",
"findings": {
"documentVerification": {
"status": "verified",
"confidence": 0.95,
"articlesOfIncorporation": "valid",
"businessLicense": "valid",
"taxCertificate": "valid"
},
"businessLegitimacy": {
"status": "verified",
"registrationVerified": true,
"taxIdValid": true,
"addressConfirmed": true
},
"sanctionsScreening": {
"status": "clear",
"listsChecked": ["OFAC", "UN", "EU", "UK"],
"matches": []
},
"adverseMedia": {
"status": "minor_flags",
"findings": [
{
"source": "news_article",
"date": "2023-05-15",
"summary": "Small tax dispute resolved",
"severity": "low"
}
]
},
"riskFactors": [
{
"factor": "new_business",
"impact": 20,
"description": "Company incorporated less than 5 years ago"
},
{
"factor": "high_growth_industry",
"impact": 15,
"description": "Software industry has elevated fraud risk"
},
{
"factor": "clean_compliance_history",
"impact": -10,
"description": "No regulatory violations found"
}
]
},
"recommendation": "approve_with_monitoring",
"nextSteps": [
"Verify beneficial ownership",
"Set transaction monitoring thresholds",
"Schedule 6-month review"
]
}
Step 5: Risk-Based Decision
Based on the risk score, route to appropriate workflow:async function processKYBDecision(analysisResult) {
const { riskScore, riskLevel, recommendation } = analysisResult;
if (riskScore < 30) {
// Low Risk - Auto-approve
return await autoApprove(analysisResult.entityId);
} else if (riskScore < 70) {
// Medium Risk - Enhanced Due Diligence
return await enhancedDueDiligence(analysisResult.entityId);
} else {
// High Risk - Manual Review Required
return await flagForManualReview(analysisResult.entityId, analysisResult.findings);
}
}
async function autoApprove(entityId) {
// Update entity status to approved
await fetch(`http://api.gu1.ai/entities/${entityId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
attributes: {
kybStatus: 'approved',
approvedAt: new Date().toISOString(),
approvedBy: 'automated_system',
reviewNotes: 'Low risk - auto-approved'
}
})
});
// Send approval notification
await sendApprovalEmail(entityId);
// Enable monitoring
await enableOngoingMonitoring(entityId);
return { status: 'approved', action: 'auto_approved' };
}
async function enhancedDueDiligence(entityId) {
// Request additional information
await requestAdditionalDocs(entityId, [
'financial_statements',
'ownership_structure',
'source_of_funds'
]);
// Update status
await updateEntityStatus(entityId, 'enhanced_due_diligence');
return { status: 'pending', action: 'edd_required' };
}
async function flagForManualReview(entityId, findings) {
// Create review task
await createReviewTask({
entityId,
priority: 'high',
assignTo: 'compliance_team',
findings,
dueDate: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
});
return { status: 'manual_review', action: 'flagged_for_review' };
}
Step 6: Beneficial Ownership Verification
Identify and verify Ultimate Beneficial Owners (UBOs):async function verifyBeneficialOwners(entityId, owners) {
const verifiedOwners = [];
for (const owner of owners) {
// Create person entity for each UBO
const uboEntity = await fetch('http://api.gu1.ai/entities', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'person',
externalId: `ubo_${owner.id}`,
name: `${owner.firstName} ${owner.lastName}`,
countryCode: owner.nationality,
entityData: {
person: {
firstName: owner.firstName,
lastName: owner.lastName,
dateOfBirth: owner.dateOfBirth,
nationality: owner.nationality
}
},
attributes: {
ownershipPercentage: owner.ownership,
isPEP: owner.isPEP,
relationshipToCompany: 'beneficial_owner'
}
})
});
const ubo = await uboEntity.json();
// Run KYC checks on UBO
const kycResult = await runKYCCheck(ubo.entity.id);
// Create relationship between company and UBO
await createRelationship({
fromEntityId: entityId,
toEntityId: ubo.entity.id,
relationshipType: 'beneficial_owner',
ownershipPercentage: owner.ownership
});
verifiedOwners.push({
...ubo.entity,
kycStatus: kycResult.status,
riskScore: kycResult.riskScore
});
}
return verifiedOwners;
}
Step 7: Setup Ongoing Monitoring
Enable continuous monitoring for approved businesses:async function setupOngoingMonitoring(entityId) {
// Configure monitoring rules
await fetch('http://api.gu1.ai/rules', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: `KYB Monitoring - ${entityId}`,
entityId: entityId,
rules: [
{
type: 'sanctions_screening',
frequency: 'daily',
action: 'alert_compliance_team'
},
{
type: 'adverse_media',
frequency: 'weekly',
action: 'create_review_task'
},
{
type: 'ownership_changes',
frequency: 'realtime',
action: 'trigger_reverification'
},
{
type: 'transaction_anomalies',
threshold: 'high',
action: 'flag_for_review'
}
]
})
});
// Setup webhook notifications
await configureWebhook({
entityId,
events: [
'sanctions_match',
'adverse_media_found',
'ownership_change',
'transaction_anomaly'
],
url: 'https://your-app.com/webhooks/kyb-alerts'
});
}
Step 8: Status Updates & Notifications
Keep the business informed throughout the process:async function sendStatusUpdate(entityId, status, details) {
// Get entity details
const entity = await getEntity(entityId);
// Send email notification
await sendEmail({
to: entity.attributes.contactEmail,
subject: `KYB Verification Update - ${status}`,
template: 'kyb_status_update',
data: {
companyName: entity.name,
status: status,
details: details,
nextSteps: getNextSteps(status),
dashboardUrl: `https://app.gu1.ai/onboarding/${entityId}`
}
});
// Send webhook to your system
await sendWebhook({
event: 'kyb_status_changed',
entityId: entityId,
status: status,
timestamp: new Date().toISOString(),
details: details
});
}
// Status update examples
await sendStatusUpdate(entityId, 'documents_received', {
message: 'We have received your documents and are processing them.'
});
await sendStatusUpdate(entityId, 'approved', {
message: 'Your business has been verified and approved!',
approvalDate: new Date().toISOString()
});
await sendStatusUpdate(entityId, 'additional_info_required', {
message: 'We need additional information to complete your verification.',
requiredDocuments: ['financial_statements', 'ownership_structure']
});
Complete Workflow Implementation
Hereβs a complete function that orchestrates the entire KYB workflow:async function executeKYBWorkflow(applicationData) {
try {
// Step 1 & 2: Create entity
console.log('Creating business entity...');
const entity = await createBusinessEntity(applicationData);
// Step 3: Upload documents
console.log('Uploading verification documents...');
await uploadBusinessDocuments(entity.id, applicationData.documents);
// Step 4: Request AI analysis
console.log('Running AI analysis...');
const analysis = await requestAIAnalysis(entity.id);
// Step 5: Make risk-based decision
console.log('Processing KYB decision...');
const decision = await processKYBDecision(analysis);
if (decision.status === 'approved') {
// Step 6: Verify UBOs (for approved entities)
console.log('Verifying beneficial owners...');
await verifyBeneficialOwners(entity.id, applicationData.beneficialOwners);
// Step 7: Setup monitoring
console.log('Setting up ongoing monitoring...');
await setupOngoingMonitoring(entity.id);
}
// Step 8: Send status update
console.log('Sending status notification...');
await sendStatusUpdate(entity.id, decision.status, analysis.findings);
return {
success: true,
entityId: entity.id,
status: decision.status,
riskScore: analysis.riskScore,
decision: decision
};
} catch (error) {
console.error('KYB workflow error:', error);
return {
success: false,
error: error.message
};
}
}
Timeline Estimates
| Risk Level | Automated Processing | With Manual Review | Traditional Process |
|---|---|---|---|
| Low Risk | 2-5 minutes | 30 minutes | 2-3 days |
| Medium Risk | 15-30 minutes | 2-4 hours | 3-5 days |
| High Risk | 30-60 minutes | 1-2 days | 5-10 days |
Next Steps
Data Requirements
See detailed data fields needed for KYB
Complete Example
Full working code implementation
API Reference
Entity creation API documentation
Webhooks
Setup real-time notifications