Due Diligence & KYC

Verify company existence, ownership, and legitimacy for compliance, onboarding, and risk assessment. The BoldData API provides the data you need for Know Your Customer (KYC) and due diligence workflows.

Use Cases

  • Customer onboarding - Verify business customers during signup
  • Supplier verification - Validate vendors before partnerships
  • Investment due diligence - Research target companies
  • Compliance checks - Meet KYC/AML regulatory requirements
  • Credit risk assessment - Evaluate company stability

What You Can Verify

CheckData PointAPI Field
Company existsFound in databaseSearch results
Registration numberOfficial company IDCompany Registration Number
Physical addressVerified locationAddress 1, City, Country
Years in businessFounded dateFounding Year
Company sizeEmployee countEmployees Total
Legal structureEntity typeBusiness Legal Type
Corporate ownershipParent companyGlobal Headquarter Company Name
Subsidiary statusOwnership flagSubsidiary Code

Try Company Verification

Don't have an API key? Get your API key →

TypeScript Implementation

GET
/api/company/export
// Due Diligence Verification - works in Node.js 18+ and browsers
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://app.companydata.com/api/company';

interface VerificationResult {
  verified: boolean;
  companyId?: string;
  companyName?: string;
  checks: {
    exists: boolean;
    hasRegistration: boolean;
    hasAddress: boolean;
    hasPhone: boolean;
    yearsInBusiness?: number;
    employeeCount?: number;
    legalStatus?: string;
    isSubsidiary: boolean;
    parentCompany?: string;
  };
  rawData?: Record<string, any>;
}

async function fetchApi<T>(endpoint: string, params: Record<string, string | number>): Promise<T> {
  const url = new URL(`${BASE_URL}/${endpoint}`);
  Object.entries(params).forEach(([key, value]) => {
    if (value) url.searchParams.append(key, String(value));
  });

  const response = await fetch(url.toString(), {
    headers: { 'x-api-key': API_KEY },
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }

  return response.json();
}

// Verify by company name and country
async function verifyByName(
  companyName: string,
  countryCode?: string
): Promise<VerificationResult> {
  const params: Record<string, string | number> = {
    search: companyName,
    page: 1,
    pageSize: 1,
  };

  if (countryCode) params.countryCode = countryCode;

  const searchResponse = await fetchApi<{ data: { records: any[] } }>('search', params);

  if (!searchResponse.data?.records?.length) {
    return {
      verified: false,
      checks: {
        exists: false,
        hasRegistration: false,
        hasAddress: false,
        hasPhone: false,
        isSubsidiary: false,
      },
    };
  }

  // Get full details
  return verifyById(searchResponse.data.records[0].ID);
}

// Verify by registration number
async function verifyByRegistration(
  registrationNumber: string,
  countryCode: string
): Promise<VerificationResult> {
  const params: Record<string, string | number> = {
    nationalId: registrationNumber,
    countryCode: countryCode,
    page: 1,
    pageSize: 1,
  };

  const searchResponse = await fetchApi<{ data: { records: any[] } }>('search', params);

  if (!searchResponse.data?.records?.length) {
    return {
      verified: false,
      checks: {
        exists: false,
        hasRegistration: false,
        hasAddress: false,
        hasPhone: false,
        isSubsidiary: false,
      },
    };
  }

  return verifyById(searchResponse.data.records[0].ID);
}

// Verify by BoldData ID
async function verifyById(companyId: string): Promise<VerificationResult> {
  const response = await fetchApi<{ data: { records: any[] } }>('export', {
    ID: companyId,
    page: 1,
    pageSize: 1,
  });

  if (!response.data?.records?.length) {
    return {
      verified: false,
      checks: {
        exists: false,
        hasRegistration: false,
        hasAddress: false,
        hasPhone: false,
        isSubsidiary: false,
      },
    };
  }

  const company = response.data.records[0];
  const currentYear = new Date().getFullYear();
  const foundingYear = company['Founding Year'] ? parseInt(company['Founding Year']) : undefined;

  const checks = {
    exists: true,
    hasRegistration: !!company['Company Registration Number'],
    hasAddress: !!(company['Address 1'] && company['City']),
    hasPhone: !!company['Phone Number'],
    yearsInBusiness: foundingYear ? currentYear - foundingYear : undefined,
    employeeCount: company['Employees Total'] ? parseInt(company['Employees Total']) : undefined,
    legalStatus: getLegalStatusText(company['Business Legal Type']),
    isSubsidiary: company['Subsidiary Code'] === '3',
    parentCompany: company['Global Headquarter Company Name'] || undefined,
  };

  // Company is "verified" if it exists and has basic information
  const verified = checks.exists && (checks.hasRegistration || checks.hasAddress);

  return {
    verified,
    companyId: company['ID'],
    companyName: company['Company Name'],
    checks,
    rawData: company,
  };
}

function getLegalStatusText(code: string): string | undefined {
  const statuses: Record<string, string> = {
    '1': 'Proprietorship',
    '2': 'Partnership',
    '3': 'Corporation',
    '7': 'Partnership',
    '8': 'Joint Venture',
    '9': 'Master Limited Partnership',
    '10': 'General Partnership',
    '11': 'Limited Partnership',
    '13': 'Proprietorship',
    '14': 'Limited Liability',
  };
  return statuses[code];
}

// Example usage
async function main() {
  console.log('=== Verification by Name ===');
  const byName = await verifyByName('Philips', 'NL');
  console.log(`Verified: ${byName.verified}`);
  console.log(`Company: ${byName.companyName}`);
  console.log('Checks:', byName.checks);

  console.log('\n=== Verification by Registration ===');
  const byReg = await verifyByRegistration('17085670', 'NL');
  console.log(`Verified: ${byReg.verified}`);
  console.log(`Company: ${byReg.companyName}`);

  console.log('\n=== Verification by ID ===');
  const byId = await verifyById('407809109');
  console.log(`Verified: ${byId.verified}`);
  console.log('Checks:', byId.checks);
}

main();

Verification Workflow

A typical KYC/due diligence workflow:

async function performDueDiligence(input: {
  companyName?: string;
  registrationNumber?: string;
  countryCode?: string;
}): Promise<{
  passed: boolean;
  score: number;
  flags: string[];
  details: VerificationResult;
}> {
  let result: VerificationResult;

  // Try verification by registration number first (most reliable)
  if (input.registrationNumber && input.countryCode) {
    result = await verifyByRegistration(input.registrationNumber, input.countryCode);
  } else if (input.companyName) {
    result = await verifyByName(input.companyName, input.countryCode);
  } else {
    throw new Error('Provide either company name or registration number');
  }

  // Calculate verification score (0-100)
  let score = 0;
  const flags: string[] = [];

  if (result.checks.exists) score += 20;
  else flags.push('Company not found in database');

  if (result.checks.hasRegistration) score += 25;
  else flags.push('No registration number on file');

  if (result.checks.hasAddress) score += 15;
  else flags.push('Incomplete address information');

  if (result.checks.hasPhone) score += 10;

  if (result.checks.yearsInBusiness && result.checks.yearsInBusiness >= 2) {
    score += 15;
  } else {
    flags.push('Company less than 2 years old');
  }

  if (result.checks.employeeCount && result.checks.employeeCount >= 5) {
    score += 15;
  }

  // Determine pass/fail (threshold: 60)
  const passed = score >= 60;

  return { passed, score, flags, details: result };
}

Best Practices

Data Quality

  • Use registration numbers when available - most reliable identifier
  • Include country code - prevents false matches in wrong countries
  • Cross-reference multiple fields - don't rely on a single check

Compliance

  • Log all checks - maintain audit trail for compliance
  • Document decisions - record why verification passed/failed
  • Regular re-verification - company status can change over time
  • Handle edge cases - new companies may have limited data

Risk Assessment

Consider these factors when assessing risk:

FactorLow RiskMedium RiskHigh Risk
Years in business10+ years2-10 years< 2 years
Employee count50+10-50< 10
Registration verifiedYesPartialNo
Physical addressVerifiedUnverifiedMissing
Parent companyKnown entityUnknownShell company indicators

Was this page helpful?