Skip to main content

KYC Review Process

When condensed flows detect potential sanctions matches, transactions are automatically held for manual compliance review. This document outlines the KYC review and approval process.

Overview

The KYC review process is triggered automatically when:

  • Sanctions List Matches: Names appear on OFAC, EU, UN, or other sanctions lists
  • PEP Matches: Politically Exposed Persons identified
  • Watchlist Hits: High-risk individuals or entities flagged
  • High-Risk Jurisdictions: Transactions involving sanctioned countries
  • Enhanced Screening: Additional risk factors identified

Review Workflow

graph TD
A[Condensed Flow Creates Transaction] --> B{KYC Matches Found?}
B -->|Yes| C[Transaction Status: KYC Beneficiary Pending Review]
B -->|No| D[Transaction Status: Client Info Pending Send]
C --> E[Compliance Team Notified]
E --> F[Manual Review Process]
F --> G{Compliance Decision}
G -->|Approve| H[KYC Approve API Call]
G -->|Reject| I[KYC Reject API Call]
H --> J[Status: Client Info Pending Send]
I --> K[Status: KYC of Beneficiary Rejected]
J --> L[Continue Transaction Flow]
K --> M[Transaction Terminated]

KYC Match Information

When matches are found, the response includes detailed information:

Match Details Structure

{
"kycCheck": {
"hasMatches": true,
"totalMatches": 3,
"beneficiaryMatches": 2,
"originatorMatches": 1,
"topMatch": {
"score": 0.95,
"name": "John Smith",
"riskLevel": "high",
"sources": ["sanctions", "pep"],
"details": {
"birthDate": "1970-01-15",
"nationality": "US",
"matchType": "name_dob_nationality",
"aliases": ["J. Smith", "Johnny Smith"]
}
},
"matches": [
{
"score": 0.95,
"name": "John Smith",
"type": "beneficiary",
"sources": ["sanctions", "pep"],
"entityType": "Person",
"listName": "OFAC SDN List",
"programType": "sanctions"
},
{
"score": 0.87,
"name": "Jane Doe Corp",
"type": "originator",
"sources": ["sanctions"],
"entityType": "Company",
"listName": "EU Consolidated List"
}
],
"metadata": {
"searchCriteria": {
"beneficiaryName": "John Smith",
"beneficiaryDob": "1970-01-15",
"originatorName": "Jane Doe Corp"
},
"apiResponse": {
"queryId": "kyc_check_123456",
"timestamp": "2024-08-07T10:00:00Z",
"provider": "OpenSanctions"
}
}
}
}

Risk Levels

  • High (0.8-1.0): Direct sanctions matches, exact name/DOB matches
  • Medium (0.5-0.79): Close name matches, PEP connections
  • Low (0.0-0.49): Weak matches, common names with partial info

KYC Approval Process

Approve KYC

When compliance review determines the matches are acceptable (false positives, acceptable risk):

Endpoint: POST https://api.trpcontinuum.com/trp/transactions/{transactionId}/kyc-check/approve

Headers:

Content-Type: application/json
Authorization: Bearer {your-token}

Request Body:

{
"note": "KYC matches reviewed and approved by compliance team. False positive identified - different person with same name.",
"reviewedBy": "compliance_officer_001",
"reviewDate": "2024-08-07T14:30:00Z",
"riskAssessment": {
"overallRisk": "low",
"mitigatingFactors": [
"Different date of birth from sanctions list entry",
"Different nationality",
"Customer has clean transaction history",
"Enhanced due diligence completed"
],
"approvalReason": "false_positive_confirmed"
},
"additionalChecks": {
"enhancedDueDiligence": true,
"sourceOfFunds": "verified",
"backgroundCheck": "completed",
"seniorApproval": true
}
}

Response:

{
"success": true,
"data": {
"id": "txn_abc123",
"status": "Client Info Pending Send",
"kycApproval": {
"approvedAt": "2024-08-07T14:30:00Z",
"approvedBy": "compliance_officer_001",
"approvalNote": "KYC matches reviewed and approved...",
"riskLevel": "low"
},
"updatedAt": "2024-08-07T14:30:00Z"
}
}

Reject KYC

When compliance review determines the risk is unacceptable:

Endpoint: POST https://api.trpcontinuum.com/trp/transactions/{transactionId}/kyc-check/reject

Request Body:

{
"note": "KYC matches indicate transaction involves sanctioned individual. Transaction rejected per compliance policy.",
"reviewedBy": "compliance_officer_001",
"reviewDate": "2024-08-07T14:30:00Z",
"rejectionReason": "sanctions_match_confirmed",
"riskAssessment": {
"overallRisk": "high",
"riskFactors": [
"Exact name match on OFAC SDN list",
"Matching date of birth",
"Same nationality as listed entity"
],
"regulatoryRequirement": "OFAC compliance - prohibited transaction"
},
"regulatoryReporting": {
"sarFiling": true,
"reportingDate": "2024-08-07T16:00:00Z",
"reportingOfficer": "compliance_manager_002"
}
}

Response:

{
"success": true,
"data": {
"id": "txn_abc123",
"status": "KYC of Beneficiary Rejected",
"kycRejection": {
"rejectedAt": "2024-08-07T14:30:00Z",
"rejectedBy": "compliance_officer_001",
"rejectionReason": "sanctions_match_confirmed",
"rejectionNote": "KYC matches indicate transaction involves sanctioned individual...",
"regulatoryAction": "Transaction blocked per OFAC requirements"
},
"updatedAt": "2024-08-07T14:30:00Z"
}
}

Review Guidelines

Approval Criteria

Transactions may be approved when:

  • False Positives: Different person with similar name
  • Historical Matches: Person previously sanctioned but delisted
  • Low-Risk PEP: PEP with acceptable risk profile
  • Technical Errors: System matching errors
  • Acceptable Risk: Low-risk matches with proper mitigation

Rejection Criteria

Transactions must be rejected when:

  • Direct Sanctions Matches: Current sanctions list entries
  • High-Confidence PEP: High-risk politically exposed persons
  • Prohibited Jurisdictions: Transactions to/from sanctioned countries
  • Enhanced Sanctions: Secondary sanctions implications
  • Regulatory Requirements: Legal prohibition of transaction

Documentation Requirements

All KYC decisions require:

  • Detailed Analysis: Explanation of match review
  • Supporting Evidence: Documentation of decision rationale
  • Risk Assessment: Formal risk evaluation
  • Approval Authority: Appropriate level of approval
  • Regulatory Compliance: Adherence to applicable regulations

Enhanced Review Scenarios

High-Value Transactions

Transactions above certain thresholds may require:

  • Senior Approval: Manager or director sign-off
  • Extended Review: Additional investigation time
  • Enhanced Documentation: More detailed risk assessment
  • External Consultation: Legal or regulatory advice

Repeat Customers

For customers with previous KYC holds:

  • Historical Review: Analysis of previous decisions
  • Pattern Analysis: Review of transaction patterns
  • Risk Escalation: Potential for enhanced monitoring
  • Relationship Assessment: Overall customer risk profile

Cross-Border Transactions

International transactions may require:

  • Jurisdiction Analysis: Assessment of countries involved
  • Regulatory Compliance: Multiple jurisdiction requirements
  • Enhanced Screening: Additional sanctions list checks
  • Correspondent Banking: VASP relationship verification

Code Examples

JavaScript/Node.js - Approval

const axios = require('axios');

async function approveKycReview(transactionId, reviewDetails) {
try {
const response = await axios.post(
`https://api.trpcontinuum.com/trp/transactions/${transactionId}/kyc-check/approve`,
{
note: reviewDetails.note,
reviewedBy: reviewDetails.officerId,
reviewDate: new Date().toISOString(),
riskAssessment: {
overallRisk: reviewDetails.riskLevel,
mitigatingFactors: reviewDetails.mitigatingFactors,
approvalReason: reviewDetails.reason
},
additionalChecks: {
enhancedDueDiligence: reviewDetails.edd,
sourceOfFunds: reviewDetails.sourceOfFunds,
backgroundCheck: reviewDetails.backgroundCheck,
seniorApproval: reviewDetails.seniorApproval
}
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);

if (response.data.success) {
console.log(`KYC approved for transaction ${transactionId}`);
console.log(`New status: ${response.data.data.status}`);

// Log approval for audit trail
await logKycDecision(transactionId, 'approved', reviewDetails);

// Notify relevant parties
await notifyTransactionParties(transactionId, 'kyc_approved');

return response.data.data;
}
} catch (error) {
console.error('KYC approval failed:', error.response?.data);
throw error;
}
}

// Example usage
const reviewDetails = {
note: "Match reviewed - different person confirmed through enhanced due diligence",
officerId: "compliance_officer_001",
riskLevel: "low",
reason: "false_positive_confirmed",
mitigatingFactors: [
"Different date of birth",
"Clean transaction history",
"Enhanced background check completed"
],
edd: true,
sourceOfFunds: "verified",
backgroundCheck: "completed",
seniorApproval: true
};

await approveKycReview("txn_abc123", reviewDetails);

JavaScript/Node.js - Rejection

async function rejectKycReview(transactionId, reviewDetails) {
try {
const response = await axios.post(
`https://api.trpcontinuum.com/trp/transactions/${transactionId}/kyc-check/reject`,
{
note: reviewDetails.note,
reviewedBy: reviewDetails.officerId,
reviewDate: new Date().toISOString(),
rejectionReason: reviewDetails.reason,
riskAssessment: {
overallRisk: "high",
riskFactors: reviewDetails.riskFactors,
regulatoryRequirement: reviewDetails.regulatoryBasis
},
regulatoryReporting: {
sarFiling: reviewDetails.requiresSAR,
reportingDate: reviewDetails.sarDate,
reportingOfficer: reviewDetails.reportingOfficer
}
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);

if (response.data.success) {
console.log(`KYC rejected for transaction ${transactionId}`);
console.log(`Final status: ${response.data.data.status}`);

// Log rejection for audit trail
await logKycDecision(transactionId, 'rejected', reviewDetails);

// File regulatory reports if required
if (reviewDetails.requiresSAR) {
await fileRegulatoryReport(transactionId, 'SAR', reviewDetails);
}

// Notify relevant parties of rejection
await notifyTransactionParties(transactionId, 'kyc_rejected');

return response.data.data;
}
} catch (error) {
console.error('KYC rejection failed:', error.response?.data);
throw error;
}
}

// Example usage
const rejectionDetails = {
note: "Confirmed match on OFAC SDN list - transaction prohibited",
officerId: "compliance_officer_001",
reason: "sanctions_match_confirmed",
riskFactors: [
"Exact name match on sanctions list",
"Matching date of birth",
"Same nationality"
],
regulatoryBasis: "OFAC compliance requirements",
requiresSAR: true,
sarDate: new Date().toISOString(),
reportingOfficer: "compliance_manager_002"
};

await rejectKycReview("txn_abc123", rejectionDetails);

Python Example

import requests
from datetime import datetime

def approve_kyc_review(transaction_id, review_details):
"""Approve KYC after manual review"""

payload = {
"note": review_details["note"],
"reviewedBy": review_details["officer_id"],
"reviewDate": datetime.now().isoformat(),
"riskAssessment": {
"overallRisk": review_details["risk_level"],
"mitigatingFactors": review_details["mitigating_factors"],
"approvalReason": review_details["reason"]
},
"additionalChecks": {
"enhancedDueDiligence": review_details.get("edd", False),
"sourceOfFunds": review_details.get("source_of_funds", "not_verified"),
"backgroundCheck": review_details.get("background_check", "not_completed"),
"seniorApproval": review_details.get("senior_approval", False)
}
}

response = requests.post(
f'https://api.trpcontinuum.com/trp/transactions/{transaction_id}/kyc-check/approve',
json=payload,
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)

if response.status_code == 200:
data = response.json()
if data['success']:
print(f"✅ KYC approved for transaction {transaction_id}")
print(f"New status: {data['data']['status']}")

# Log for audit trail
log_kyc_decision(transaction_id, 'approved', review_details)
return data['data']
else:
print(f"KYC approval failed: {data.get('message')}")
else:
print(f"HTTP Error: {response.status_code} - {response.text}")

return None

def reject_kyc_review(transaction_id, review_details):
"""Reject KYC after manual review"""

payload = {
"note": review_details["note"],
"reviewedBy": review_details["officer_id"],
"reviewDate": datetime.now().isoformat(),
"rejectionReason": review_details["reason"],
"riskAssessment": {
"overallRisk": "high",
"riskFactors": review_details["risk_factors"],
"regulatoryRequirement": review_details["regulatory_basis"]
},
"regulatoryReporting": {
"sarFiling": review_details.get("requires_sar", False),
"reportingDate": datetime.now().isoformat(),
"reportingOfficer": review_details.get("reporting_officer")
}
}

response = requests.post(
f'https://api.trpcontinuum.com/trp/transactions/{transaction_id}/kyc-check/reject',
json=payload,
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)

if response.status_code == 200:
data = response.json()
if data['success']:
print(f"❌ KYC rejected for transaction {transaction_id}")
print(f"Final status: {data['data']['status']}")

# Log for audit trail
log_kyc_decision(transaction_id, 'rejected', review_details)

# Handle regulatory reporting
if review_details.get("requires_sar"):
file_regulatory_report(transaction_id, review_details)

return data['data']
else:
print(f"KYC rejection failed: {data.get('message')}")
else:
print(f"HTTP Error: {response.status_code} - {response.text}")

return None

def log_kyc_decision(transaction_id, decision, details):
"""Log KYC decision for audit trail"""
print(f"Logging KYC {decision} for transaction {transaction_id}")
# Implementation would log to audit system

def file_regulatory_report(transaction_id, details):
"""File required regulatory reports"""
print(f"Filing regulatory report for transaction {transaction_id}")
# Implementation would file SAR or other required reports

Best Practices

Review Process

  1. Timely Review: Complete reviews within SLA timeframes
  2. Thorough Analysis: Comprehensive evaluation of all matches
  3. Proper Documentation: Detailed reasoning for all decisions
  4. Consistent Standards: Apply uniform review criteria
  5. Regular Training: Keep compliance staff updated on procedures

Risk Management

  1. Risk-Based Approach: Focus resources on highest-risk cases
  2. Escalation Procedures: Clear guidelines for complex cases
  3. Second Reviews: Senior review for high-risk approvals
  4. Pattern Recognition: Identify trends and systemic issues
  5. Continuous Improvement: Regular process enhancement

Regulatory Compliance

  1. Current Sanctions Lists: Use most up-to-date screening data
  2. Jurisdiction Requirements: Comply with all applicable regulations
  3. Reporting Obligations: File required regulatory reports
  4. Record Keeping: Maintain detailed transaction records
  5. Audit Preparedness: Ensure reviewable documentation

Common Errors

Invalid Transaction Status

{
"success": false,
"error": "INVALID_TRANSACTION_STATUS",
"message": "Transaction is not in a status that allows KYC approval/rejection",
"details": {
"currentStatus": "Client Info Pending Send",
"requiredStatus": "KYC Beneficiary Pending Review",
"suggestion": "Only transactions with KYC matches can be approved/rejected"
}
}

Insufficient Approval Authority

{
"success": false,
"error": "INSUFFICIENT_AUTHORITY",
"message": "User does not have authority to approve/reject KYC for this risk level",
"details": {
"userRole": "junior_analyst",
"requiredRole": "senior_compliance_officer",
"riskLevel": "high",
"suggestion": "Escalate to senior compliance officer for approval"
}
}

This comprehensive KYC review process ensures proper compliance oversight while maintaining efficient transaction processing for legitimate transactions.