Skip to main content

Sanctions Screening

Overview​

Sanctions screening is the mandatory compliance process of checking all payment parties β€” individuals, entities, and financial institutions β€” against government-issued and international watchlists. If a match is found, the payment must be blocked, the account may need to be frozen, and the incident reported to the regulator.

Sanctions are geopolitical tools. Governments use them to restrict economic activity with certain countries, regimes, terrorist organisations, weapons proliferators, and corrupt individuals. For banks, processing a sanctioned transaction β€” even unknowingly β€” can result in catastrophic penalties.

Key principle: Sanctions are not optional and not risk-based. If a name is on the list, the payment must stop β€” no exceptions.


Why Sanctions Screening Matters​

Real-World Penalty Examples​

BankYearPenaltyReason
BNP Paribas2014USD 8.97BProcessing transactions for Sudan, Iran, Cuba
Standard Chartered2019USD 1.1BIran, Myanmar, Zimbabwe transaction processing
HSBC2012USD 1.9BMexican drug cartel + sanctions violations
Commerzbank2015USD 1.45BIran, Sudan payments stripped of identifying info
Westpac2020AUD 1.3BAML/CTF breaches including AUSTRAC violations

Consequences of Non-Compliance​

ConsequenceDetails
Massive finesCan exceed the bank's annual profit
Criminal prosecutionSenior executives personally liable
Reputational damageLoss of correspondent banking relationships β€” effectively cuts off international payments
SWIFT disconnectionExclusion from the global interbank network
Banking licence revocationRegulator can shut the bank down
Deferred Prosecution AgreementsBank placed under US government supervision for years

Types of Sanctions​

1. Comprehensive Sanctions (Country-Level)​

Broad prohibition on all economic activity with a country or regime.

Country / RegimeSanctioning BodyScope
IranOFAC (US), EU, UN, DFAT (AU)Near-total ban on transactions
North Korea (DPRK)OFAC, UN, EU, DFATComprehensive embargo
SyriaOFAC, EU, DFATBroad restrictions
CubaOFACUS-specific embargo; others vary
Russia (post-2022)EU, OFAC, DFAT, UKSectoral + targeted
BelarusEU, UK, OFACSenior regime figures + entities
MyanmarOFAC, EU, DFATMilitary junta + entities

⚠️ Extraterritorial Reach of OFAC: Even a non-US bank can be penalised by OFAC if transactions touch the US financial system (USD clearing, US correspondent banks). This makes OFAC screening globally mandatory.

2. Targeted / Individual Sanctions​

Prohibitions on specific named individuals and entities, regardless of their country.

  • Specially Designated Nationals (SDN) β€” OFAC's primary list; includes terrorists, drug traffickers, WMD proliferators, and corrupt oligarchs
  • Consolidated UN List β€” UN-designated individuals and entities
  • EU Consolidated List β€” EU-designated individuals and entities
  • DFAT List (AU) β€” Australia's autonomous sanctions on individuals and entities

3. Sectoral Sanctions​

Restrictions on specific sectors of an economy rather than blanket bans β€” common for Russia sanctions:

Sectoral Sanctions examples (Russia):
β”œβ”€β”€ Energy sector β€” Restrictions on financing for oil projects
β”œβ”€β”€ Defence sector β€” No finance/export of military equipment
β”œβ”€β”€ Finance sector β€” Restrictions on major Russian banks (debt/equity financing)
└── Technology β€” Export controls on dual-use technology

4. Secondary Sanctions​

US secondary sanctions penalise non-US entities that do business with sanctioned parties β€” even if no US person or USD is involved:

Iranian company ────────────────► German company (non-US)
(sanctioned) β”‚
β”‚ US secondary sanctions risk
β–Ό
German company could be cut off
from the US financial system

This is why banks globally β€” not just US banks β€” screen against OFAC lists.


Global Sanctions Lists​

Primary Lists (Must Screen Against)​

ListAuthorityNotes
OFAC SDNUS Treasury Office of Foreign Assets Control~13,000+ entries; most powerful list globally
OFAC Non-SDN / SSIUS TreasurySectoral Sanctions Identifications (SSI) list
UN Security Council ConsolidatedUnited NationsMandatory for all UN member states
EU Consolidated SanctionsEuropean CouncilMust screen for EU-connected transactions
UK OFSI ConsolidatedHM Treasury Office of Financial Sanctions ImplementationPost-Brexit, UK maintains its own list
DFAT ConsolidatedAustralian Dept of Foreign Affairs and TradeAustralia's autonomous sanctions
AUSTRAC GuidanceAUSTRACAML/CTF risk guidance (supplements DFAT)

Secondary / Supplementary Lists​

ListSourceUsage
Interpol Red NoticesInterpolWanted persons (not legally binding)
World Bank DebarredWorld BankDebarred entities from WB projects
FATF High-Risk CountriesFATFEnhanced due diligence jurisdictions
Transparency International CPITICorruption Perception Index β€” risk indicator
Internal Bank BlacklistsEach bankInternal watchlists from investigations

SDN List β€” Structure Deep Dive​

The OFAC SDN list entry contains:

SDN Entry Example:
β”œβ”€β”€ Name: ALI HASSAN MOHAMMED
β”œβ”€β”€ Aliases: HASSAN, Ali; MOHAMMED ALI, Hassan
β”œβ”€β”€ Type: Individual
β”œβ”€β”€ Program: SDGT (Specially Designated Global Terrorist)
β”œβ”€β”€ DOB: 01 Jan 1975
β”œβ”€β”€ POB: Yemen
β”œβ”€β”€ Nationality: Yemeni
β”œβ”€β”€ Passport: YE123456 (issued Yemen)
β”œβ”€β”€ Address: Sana'a, Yemen
└── Additional info: Associated with [terrorist org]

Associated entity:
β”œβ”€β”€ Name: AL-HASSAN TRADING CO.
β”œβ”€β”€ Type: Entity
β”œβ”€β”€ Program: SDGT
β”œβ”€β”€ Address: Sana'a, Yemen
└── ID: YE-REG-12345

Banks must screen against all fields β€” name, alias, DOB, address, passport number.


What Must Be Screened​

In Every Payment​

pacs.008 / pain.001 Payment Instruction
β”œβ”€β”€ Debtor
β”‚ β”œβ”€β”€ Name (and all name variants)
β”‚ β”œβ”€β”€ Address / country
β”‚ β”œβ”€β”€ Date of birth (individuals)
β”‚ └── Registration number (entities)
β”œβ”€β”€ Debtor Account (IBAN, account number)
β”œβ”€β”€ Debtor Agent (BIC β†’ country extraction)
β”œβ”€β”€ Instructing Party (if different from debtor)
β”œβ”€β”€ Ultimate Debtor (if present)
β”œβ”€β”€ Intermediary Agent(s) (correspondent banks)
β”œβ”€β”€ Creditor Agent (BIC β†’ country extraction)
β”œβ”€β”€ Creditor
β”‚ β”œβ”€β”€ Name
β”‚ β”œβ”€β”€ Address / country
β”‚ └── Registration number
β”œβ”€β”€ Creditor Account
β”œβ”€β”€ Ultimate Creditor (if present)
└── Remittance Information
└── Scan for entity names embedded in free text

At Customer Onboarding​

  • Full name + aliases
  • Beneficial owners (β‰₯ 25% ownership β€” see UBO rules in AML)
  • Directors and key controllers
  • Connected entities and subsidiaries

On List Updates​

When OFAC/UN/DFAT publish a new list version, every existing customer in the bank must be re-screened against the new entries.


Sanctions Screening Architecture​

Payment Instruction
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SANCTIONS SCREENING ENGINE β”‚
β”‚ β”‚
β”‚ 1. DATA EXTRACTION β”‚
β”‚ Parse all party fields from ISO 20022 message β”‚
β”‚ β”‚
β”‚ 2. NORMALISATION β”‚
β”‚ β”œβ”€β”€ Remove punctuation: "AL-RASHID" β†’ "AL RASHID" β”‚
β”‚ β”œβ”€β”€ Expand abbreviations: "Co." β†’ "Company" β”‚
β”‚ β”œβ”€β”€ Transliterate: Arabic/Cyrillic β†’ Latin β”‚
β”‚ β”œβ”€β”€ Lowercase + trim β”‚
β”‚ └── Split compound names β”‚
β”‚ β”‚
β”‚ 3. MATCHING ENGINE β”‚
β”‚ β”œβ”€β”€ Exact match (account numbers, BICs, LEIs) β”‚
β”‚ β”œβ”€β”€ Fuzzy name match (Jaro-Winkler, Levenshtein) β”‚
β”‚ β”œβ”€β”€ Phonetic match (Soundex, Double Metaphone) β”‚
β”‚ β”œβ”€β”€ Token / n-gram match β”‚
β”‚ β”œβ”€β”€ Alias expansion (check all known aliases) β”‚
β”‚ └── Country code match (for embargoed countries) β”‚
β”‚ β”‚
β”‚ 4. SCORING & THRESHOLDING β”‚
β”‚ β”œβ”€β”€ Score 0–100 per candidate match β”‚
β”‚ β”œβ”€β”€ < threshold β†’ CLEAR β”‚
β”‚ └── β‰₯ threshold β†’ ALERT β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
CLEAR POTENTIAL MATCH
β”‚ β”‚
Process Auto-Hold Payment
Payment Notify Compliance
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
FALSE POSITIVE TRUE MATCH
β”‚ β”‚
Document BLOCK permanently
Release Freeze account
Tune rule File with AUSTRAC/OFAC

Name Matching Algorithms​

Jaro-Winkler Similarity​

Best for short strings (names). Gives extra weight to matches at the start of the string.

// Jaro-Winkler example
double score = jaroWinkler.apply("Mohammed Ali", "Mohammad Ali");
// Returns ~0.944 β€” high confidence match

// Threshold typically set at 0.85 for sanctions
boolean isAlert = score >= 0.85;

Levenshtein Distance​

Counts minimum edits (insert, delete, substitute) to transform one string to another.

int distance = levenshtein.apply("HASSAN", "HASAAN");
// Returns 1 (one substitution) β€” likely a match

Double Metaphone (Phonetic)​

Encodes names by how they sound, not how they're spelled.

String[] codes = metaphone.doubleMetaphone("Mohammed");
// Returns ["MHM", "MMT"] β€” same codes as "Mohamed", "Muhammed"
// Catches transliteration variants

Token Set Ratio​

Handles names in different word order.

// "Ali Hassan Mohammed" vs "Mohammed Ali Hassan"
// Standard fuzzy: low score (different order)
// Token set ratio: high score (same tokens, different order)
double score = tokenSetRatio("Ali Hassan Mohammed", "Mohammed Ali Hassan");
// Returns 1.0 β€” same tokens

Match Threshold Strategy​

ThresholdBehaviourTrade-off
100% (exact only)Minimal false positivesEasily evaded by minor spelling variants
85–90%BalancedIndustry standard for high-volume screening
70–80%More alertsHigh false positive rate; analyst workload ↑
60–70%Very sensitiveUnusable false positive rate

Banks typically run multiple thresholds β€” 85% for auto-hold, 70% for audit log only.


Country Risk and Embargo Screening​

Beyond name matching, the country in a payment must be checked:

public class CountryRiskScreeningService {

public CountryRiskResult screen(String bicOrIban) {
String countryCode = extractCountry(bicOrIban); // e.g., "IR" from BKIRIRIA

if (comprehensiveEmbargo.contains(countryCode)) {
// e.g., IR (Iran), KP (North Korea), SY (Syria)
return CountryRiskResult.block("Comprehensive embargo: " + countryCode);
}

if (sectoralSanctions.contains(countryCode)) {
// e.g., RU (Russia) β€” depends on transaction type
return CountryRiskResult.review("Sectoral sanctions apply: " + countryCode);
}

if (fatfHighRisk.contains(countryCode)) {
// FATF grey/black list countries
return CountryRiskResult.enhancedDueDiligence(countryCode);
}

return CountryRiskResult.clear(countryCode);
}

private String extractCountry(String bic) {
// BIC format: BBBB-CC-LL-BBB (CC = country)
return bic.length() >= 6 ? bic.substring(4, 6).toUpperCase() : "XX";
}
}

High-Risk / Embargoed Country Categories​

CategoryExamplesTreatment
Comprehensive embargoIran, DPRK, Syria, Cuba (US)Block all transactions
Sectoral sanctionsRussia, BelarusBlock based on transaction type/sector
FATF Black ListIran, DPRKEnhanced due diligence + report to regulator
FATF Grey ListPakistan, UAE (past), PhilippinesIncreased monitoring
High-risk DFATCountries on DFAT concern listEnhanced scrutiny

False Positive Management​

False positives are the biggest operational challenge in sanctions screening. A bank processing millions of payments per day may generate thousands of false alerts daily.

False Positive Rate Benchmarks​

IndustryTypical FP RateTarget
Retail banking95–99% of alerts are false positives< 95%
Correspondent banking90–97%< 90%
Trade finance85–95%< 85%

Reducing False Positives​

Techniques:
β”œβ”€β”€ Whitelisting β€” Known good entities (e.g., "Shell" the oil company vs "Shell" the person)
β”œβ”€β”€ Rule tuning β€” Adjust thresholds per list / name type
β”œβ”€β”€ Context scoring β€” Weight by address, DOB, account number match
β”œβ”€β”€ Entity disambiguation β€” Resolve common names using LEI/registration numbers
β”œβ”€β”€ Suppression rules β€” Suppress alert if same entity already reviewed + cleared
└── Post-review feedback loop β€” Analyst decisions train the model

Analyst Workflow for False Positive Disposition​

Alert Received
β”‚
β–Ό
Analyst Reviews:
β”œβ”€β”€ Does nationality/address/DOB match?
β”œβ”€β”€ Is this a common name? (e.g., "Mohammed Ali" β€” millions worldwide)
β”œβ”€β”€ Additional identifiers available? (passport, LEI, registration)
β”œβ”€β”€ Context: what is the transaction for?
└── Has this entity been cleared before?
β”‚
β”œβ”€β”€ CLEARLY DIFFERENT PERSON β†’ False Positive
β”‚ Document: name, why cleared, analyst ID, timestamp
β”‚ Add to suppression list (if safe to do so)
β”‚
β”œβ”€β”€ UNCERTAIN β†’ Escalate to Senior Analyst
β”‚ Request additional customer information
β”‚ Apply de-risking measures
β”‚
└── CONFIRMED MATCH β†’ True Hit
Escalate to Compliance Manager
Block payment / freeze account
File with AUSTRAC/OFAC

Watchlist Maintenance and List Updates​

Sanctions lists are updated frequently β€” OFAC alone may update the SDN list multiple times per week:

List Update Workflow:
1. New list published by OFAC/UN/EU/DFAT
2. Compliance team notified (automated)
3. New list ingested into screening engine (automated, < 1 hour)
4. Delta screening run against:
β”œβ”€β”€ All existing customers (customer screening)
β”œβ”€β”€ All pending/queued payments
└── Recent transactions (look-back period, e.g., 30 days)
5. New alerts generated for newly added entries
6. Audit log of list version used for each screening event
@Service
public class WatchlistMaintenanceService {

@Scheduled(fixedDelay = 3_600_000) // Every hour
public void checkForListUpdates() {
for (SanctionsList list : SanctionsList.values()) {
String latestVersion = listProvider.getLatestVersion(list);
String currentVersion = listVersionRepository.getCurrent(list);

if (!latestVersion.equals(currentVersion)) {
List<SanctionsEntry> delta = listProvider.getDelta(
list, currentVersion, latestVersion);

// Update local list
listRepository.applyDelta(list, delta);
listVersionRepository.update(list, latestVersion);

// Re-screen impacted customers
screeningJobQueue.submit(new DeltaScreeningJob(delta));

auditLog.info("Sanctions list updated: {} from {} to {}",
list, currentVersion, latestVersion);
}
}
}
}

Sanctions Evasion Red Flags​

Banks must be alert to attempts to circumvent sanctions controls:

Red FlagDescription
StrippingRemoving identifying information from SWIFT MT messages (e.g., removing Iranian bank BIC)
Name misspellingDeliberate typos to avoid fuzzy matching (e.g., "Khaminei" for "Khamenei")
Shell company routingUsing non-sanctioned shell companies owned by sanctioned individuals
Third-country routingRouting payments through a non-sanctioned jurisdiction to obscure origin/destination
Proxy ownershipSanctioned individual owns < 50% but controls the entity through nominees
Mixed jurisdictionLegitimate entity registered in a sanctioned country (e.g., a branch in Iran)
PayID maskingUsing a phone number or email PayID to hide account details
Correspondent layeringUsing chains of correspondent banks to obscure the sanctioned party

Payment Stripping (Historical SWIFT MT)​

Original MT103:
:52A: BKIRIRIA ← Iranian bank BIC
:59: /IR987654321 John Smith

Stripped MT103 sent to US correspondent:
:52A: (field removed)
:59: John Smith

US correspondent bank sees no Iranian connection β†’ processes
β†’ Bank later fined for knowing about the stripping

ISO 20022 makes stripping much harder β€” structured XML fields are harder to remove without breaking validation.


Correspondent Banking and De-Risking​

Banks are reducing their correspondent banking relationships to avoid sanctions exposure β€” known as de-risking:

Bank A (small, high-risk jurisdiction)
β”‚
β”‚ Applies for USD correspondent account
β”‚
β–Ό
Major US Bank (potential correspondent)
β”‚
β”‚ Assesses:
β”œβ”€β”€ Does Bank A have robust sanctions controls?
β”œβ”€β”€ Is Bank A's home jurisdiction high-risk?
β”œβ”€β”€ What are Bank A's customers like?
└── Is the compliance cost worth the revenue?
β”‚
β–Ό
If risk too high β†’ De-risk: decline the relationship

This de-risking trend creates financial exclusion for smaller/developing-country banks β€” a global policy challenge.


Regulatory Reporting β€” True Sanctions Hit​

When a confirmed sanctions hit is found:

Immediate Actions (Within Hours)​

  1. Block the payment permanently
  2. Freeze the customer's account (if the customer is sanctioned)
  3. Escalate to Compliance Manager and Legal
  4. Do NOT tip off the customer β€” this is a criminal offence

Regulatory Reporting​

JurisdictionAuthorityReportDeadline
AustraliaAUSTRAC + DFATSMR / Freezing noticeImmediately / ASAP
USOFACOFAC ReportWithin 10 business days
UKOFSI (HM Treasury)Freezing / asset reportWithin 14 days
EUNational FIUPer member state rulesVaries

Record Keeping​

  • All screening events must be logged (payment ID, parties screened, list version, score, decision)
  • Minimum retention: 7 years in Australia
  • Records must be producible on demand for regulatory examination

Sanctions vs AML vs Fraud​

DimensionSanctionsAML/CTFFraud
PurposeBlock geopolitically prohibited entitiesDetect financial crime patternsPrevent monetary loss
Legal obligationMandatory β€” no risk-based discretionMandatory β€” risk-based approachRisk management
Lists usedGovernment watchlists (OFAC, UN, DFAT)Internal TM rules, FATF guidanceInternal blacklists, fraud networks
Can tip off customer?❌ Criminal offence❌ Criminal offenceβœ… Yes (contact to verify)
Report toAUSTRAC, OFAC, OFSI, DFATAUSTRAC (SMR)Internal only
ReviewerCompliance officerAML analystFraud analyst
Threshold approachZero toleranceRisk-basedRisk-based
False positivesHigh volume β€” need analyst triageModerateHigh β€” automated clearing common

Java Spring β€” Full Screening Implementation​

@Service
@Slf4j
public class SanctionsScreeningService {

private final WatchlistRepository watchlistRepository;
private final NameNormalisationService normaliser;
private final MatchingEngine matchingEngine;
private final PaymentHoldService holdService;
private final ComplianceAlertService alertService;
private final ScreeningAuditRepository auditRepository;
private final CountryRiskService countryRiskService;

@Value("${screening.fuzzy.threshold:0.85}")
private double fuzzyThreshold;

@Value("${screening.exact.account-numbers:true}")
private boolean screenAccountNumbers;

public ScreeningResult screen(PaymentInstruction instruction) {
List<ScreeningSubject> subjects = extractAllSubjects(instruction);
List<ScreeningAlert> alerts = new ArrayList<>();

for (ScreeningSubject subject : subjects) {

// 1. Country-level check (fast β€” before name matching)
if (subject.hasCountry()) {
CountryRiskResult countryRisk =
countryRiskService.screen(subject.getCountry());
if (countryRisk.isBlocked()) {
return escalateHit(instruction, subject, countryRisk.getReason());
}
}

// 2. Account number / BIC exact match
if (screenAccountNumbers && subject.hasAccountIdentifier()) {
List<WatchlistMatch> exactMatches =
watchlistRepository.findExactByIdentifier(
subject.getAccountIdentifier());
if (!exactMatches.isEmpty()) {
return escalateHit(instruction, subject,
"Exact account/BIC match: " + subject.getAccountIdentifier());
}
}

// 3. Fuzzy name matching
String normalisedName = normaliser.normalise(subject.getName());
List<WatchlistCandidate> candidates =
watchlistRepository.findCandidates(normalisedName);

for (WatchlistCandidate candidate : candidates) {
double score = matchingEngine.score(normalisedName,
candidate.getNormalisedName());

if (score >= fuzzyThreshold) {
alerts.add(ScreeningAlert.builder()
.subject(subject)
.candidate(candidate)
.score(score)
.matchType(MatchType.FUZZY_NAME)
.build());
}
}
}

// Audit every screening event
auditRepository.save(ScreeningAuditRecord.builder()
.paymentId(instruction.getId())
.subjectsScreened(subjects.size())
.alertCount(alerts.size())
.listVersions(watchlistRepository.getCurrentVersions())
.screenedAt(Instant.now())
.result(alerts.isEmpty() ? "CLEAR" : "ALERT")
.build());

if (alerts.isEmpty()) {
return ScreeningResult.clear(instruction.getId());
}

// Hold payment and notify compliance
holdService.hold(instruction.getId(), HoldReason.SANCTION_ALERT);
alertService.raiseAlerts(alerts);

log.warn("Sanctions alert on payment {}: {} alerts raised",
instruction.getId(), alerts.size());

return ScreeningResult.potentialMatch(instruction.getId(), alerts);
}

private ScreeningResult escalateHit(PaymentInstruction instruction,
ScreeningSubject subject, String reason) {
holdService.holdPermanently(instruction.getId(), HoldReason.CONFIRMED_SANCTION);
alertService.raiseConfirmedHit(instruction, subject, reason);
log.error("CONFIRMED SANCTIONS HIT on payment {}: {}",
instruction.getId(), reason);
return ScreeningResult.confirmedMatch(instruction.getId(), reason);
}

private List<ScreeningSubject> extractAllSubjects(PaymentInstruction instruction) {
List<ScreeningSubject> subjects = new ArrayList<>();

// Parties
subjects.add(ScreeningSubject.fromParty(instruction.getDebtor(),
SubjectRole.DEBTOR));
subjects.add(ScreeningSubject.fromParty(instruction.getCreditor(),
SubjectRole.CREDITOR));

// Agents / BICs
subjects.add(ScreeningSubject.fromBic(instruction.getDebtorAgentBic(),
SubjectRole.DEBTOR_AGENT));
subjects.add(ScreeningSubject.fromBic(instruction.getCreditorAgentBic(),
SubjectRole.CREDITOR_AGENT));

// Optional parties
if (instruction.hasUltimateDebtor()) {
subjects.add(ScreeningSubject.fromParty(instruction.getUltimateDebtor(),
SubjectRole.ULTIMATE_DEBTOR));
}
if (instruction.hasUltimateCreditor()) {
subjects.add(ScreeningSubject.fromParty(instruction.getUltimateCreditor(),
SubjectRole.ULTIMATE_CREDITOR));
}

// Intermediary agents
instruction.getIntermediaryAgents().forEach(agent ->
subjects.add(ScreeningSubject.fromBic(agent.getBic(),
SubjectRole.INTERMEDIARY_AGENT)));

return subjects.stream()
.filter(ScreeningSubject::isScreenable)
.collect(toList());
}
}

Screening in the Payment Lifecycle​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SCREENING TOUCHPOINTS β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
Onboarding ──►│ 1. KYC onboarding screen β”‚
β”‚ (customer + UBOs + directors) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
Outbound ──►│ 2. Pre-payment screen β”‚
Payment β”‚ (all parties in pain.001) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
Inbound ──►│ 3. Inbound payment screen β”‚
Payment β”‚ (all parties in pacs.008) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
Scheduled ──►│ 4. Periodic re-screen β”‚
Batch β”‚ (existing customer base) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
List Update──►│ 5. Delta screen on list change β”‚
β”‚ (re-screen against new entries) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  • aml_kyc.md β€” Runs alongside sanctions; different purpose and lists
  • fraud.md β€” Third compliance check in the same pipeline
  • outbound.md β€” Sanctions check before payment is submitted
  • inbound.md β€” Sanctions check on received pacs.008
  • fis.md β€” FI-level (BIC/country) sanctions screening
  • payment_exceptions.md β€” Sanctions holds as exceptions
  • swift.md β€” SWIFT gpi and sanctions compliance