Development of PEP (Politically Exposed Persons) Verification System
PEP verification is a requirement of FATF R12 and most AML legislations. Politically significant individuals (state officials, government corporation heads, politicians, senior military commanders) are considered high-risk clients due to elevated corruption risk. This does not mean blocking them, but requires Enhanced Due Diligence.
What is PEP
Domestic PEP: senior government official in the country where the client operates.
Foreign PEP: official from another country — typically higher risk.
International organization PEP: leaders of major international organizations (UN, IMF, World Bank).
RCA (Relatives and Close Associates): spouses, children, parents of PEP, business partners.
PEP Data Sources
Commercial providers:
- ComplyAdvantage: 10M+ records, REST API, RCA coverage
- Refinitiv World-Check: largest database, used by banks
- Dow Jones Risk & Compliance: enterprise grade
- Acuris Risk Intelligence
Note: there is no single official government PEP registry. Providers gather data from open sources (government websites, Wikileaks, journalists).
ComplyAdvantage API Integration
class PEPScreeningService {
async screenPerson(params: {
firstName: string;
lastName: string;
dateOfBirth?: string;
nationality?: string;
}): Promise<PEPScreenResult> {
const response = await this.complyAdvantage.search({
search_term: `${params.firstName} ${params.lastName}`,
fuzziness: 0.7,
filters: {
types: ["pep", "pep-class-1", "pep-class-2", "pep-class-3", "pep-class-4"],
},
});
const matches = response.content.data.hits;
if (matches.length === 0) return { isPEP: false, isRCA: false };
// Filter by DOB if provided
const strongMatches = params.dateOfBirth
? matches.filter(m => this.dobMatches(m, params.dateOfBirth!))
: matches;
if (strongMatches.length === 0) {
return { isPEP: false, possibleMatches: matches.slice(0, 3) };
}
const match = strongMatches[0];
return {
isPEP: match.doc.types.some(t => t.startsWith("pep")),
isRCA: match.doc.types.includes("relative-close-associate"),
pepClass: this.extractPEPClass(match.doc.types),
positions: match.doc.fields?.filter(f => f.tag === "position") ?? [],
country: match.doc.fields?.find(f => f.tag === "country_names")?.value,
matchScore: match.score,
entity: match.doc,
};
}
private extractPEPClass(types: string[]): number {
if (types.includes("pep-class-1")) return 1; // Head of state, government ministers
if (types.includes("pep-class-2")) return 2; // Parliament members, senior judiciary
if (types.includes("pep-class-3")) return 3; // Senior military, state-owned enterprise heads
if (types.includes("pep-class-4")) return 4; // Local government, lower-risk positions
return 0;
}
}
PEP Result Processing Logic
async function handlePEPResult(userId: string, result: PEPScreenResult): Promise<void> {
if (!result.isPEP && !result.isRCA) {
await db.setUserRiskFactor(userId, "pep", false);
return;
}
// PEP requires Enhanced Due Diligence
await db.setUserRiskFactor(userId, "pep", true);
await db.updateUserRiskLevel(userId, RiskLevel.HIGH);
const eddRequired: EDDRequirement = {
sourceOfFunds: true,
sourceOfWealth: true,
seniorManagementApproval: result.pepClass <= 2, // class 1-2 requires senior approval
enhancedOngoingMonitoring: true,
annualReview: true,
};
await requestEDD(userId, eddRequired);
await notifyComplianceOfficer(userId, result);
}
Continuous PEP Monitoring
PEP status can appear for an existing customer (appointment to position):
// Weekly rescreening of all active customers
@Cron("0 2 * * 0") // every Sunday at 2:00
async weeklyPEPRescreening() {
const activeCustomers = await db.getActiveCustomers();
for (const customer of activeCustomers) {
const result = await this.pepService.screenPerson(customer);
const previousStatus = customer.pepStatus;
if (result.isPEP && !previousStatus) {
// New PEP — immediate notification
await this.handleNewPEPDetection(customer.id, result);
}
}
}
PEP verification system with ComplyAdvantage integration, EDD workflow, and periodic rescreening — 2-3 weeks development.







