OFAC Sanctions Screening API — Complete Integration Guide for Fintech
OFAC compliance is not optional for fintechs. The Office of Foreign Assets Control enforces U.S. sanctions programs under a strict liability regime — meaning you can be fined even if you did not know a customer was sanctioned. Penalties start at $330,000 per violation and can escalate to $20 million or more for willful infractions. BitPay paid $507,375 for processing transactions with sanctioned regions. BNP Paribas paid $8.9 billion. These are not theoretical risks.
This guide covers everything a fintech engineering team needs to know about OFAC screening: which lists to check, when to screen, how to integrate an API in both Python and Node.js, how to handle matches, and the common mistakes that lead to enforcement actions. If you have already read our introductory OFAC guide, this article goes deeper into the technical integration.
What is OFAC and how does it work?
OFAC is a division of the U.S. Department of the Treasury responsible for administering and enforcing economic sanctions programs. These programs target countries, regimes, terrorists, drug traffickers, weapons proliferators, and other threats to U.S. national security.
OFAC sanctions work by prohibiting U.S. persons and entities from engaging in transactions with designated parties. The term "U.S. persons" is broadly defined: it includes U.S. citizens anywhere in the world, permanent residents, entities organized under U.S. law, and anyone physically present in the United States. Critically, it also extends to any transaction that touches the U.S. financial system — which means any transaction denominated in U.S. dollars, even between two non-U.S. parties, can fall under OFAC jurisdiction.
For fintechs, this means that if you process payments in USD, issue dollar-denominated cards, facilitate cross-border transfers, or serve customers who transact in dollars, you are subject to OFAC regulations. There is no minimum size threshold. A $10 transfer to a sanctioned party carries the same legal liability as a $10 million one.
Which OFAC lists to screen against
OFAC maintains several distinct sanctions lists. Most fintechs focus on the SDN list, but comprehensive compliance requires screening against multiple lists:
Specially Designated Nationals and Blocked Persons List (SDN). This is the primary OFAC list, containing 18,700+ individuals, entities, vessels, and aircraft. If a customer or counterparty appears on the SDN list, you must block the transaction, freeze any assets, and report to OFAC within 10 business days. The SDN list is updated multiple times per week, sometimes daily.
Sectoral Sanctions Identifications List (SSI). This list targets specific sectors of the Russian economy (financial services, energy, defense). Unlike the SDN list where all transactions are blocked, sectoral sanctions impose targeted restrictions — for example, prohibiting new debt or equity financing with listed entities.
Non-SDN Lists. OFAC also maintains several non-SDN lists including the Foreign Sanctions Evaders List (FSE), the Non-SDN Palestinian Legislative Council List, the Non-SDN Chinese Military-Industrial Complex Companies List (NS-CMIC), and the Non-SDN Menu-Based Sanctions List (NS-MBS). Each has different prohibition types and requirements.
Consolidated Sanctions List. OFAC publishes a consolidated file that combines all of the above into a single downloadable dataset. This is what most screening systems ingest as their OFAC data source.
For most fintechs, screening against the full OFAC consolidated list is the right approach. With an API like Verifex, this happens automatically — you do not need to manage individual lists or figure out which prohibition types apply to each.
When to screen: OFAC's own guidance
OFAC has published guidance on when financial institutions should conduct sanctions screening. The key screening triggers are:
1. Customer onboarding. Screen every new customer when they create an account. This is the most critical checkpoint. Do not allow a customer to transact until they have been screened. For KYC flows, screening should happen after identity data is collected but before the account is activated.
2. Transaction processing. Screen counterparties before executing outbound payments, wire transfers, or any value transfer. For payment processors, this means screening the recipient of every transaction. For lending platforms, screen borrowers before disbursement.
3. List updates. When OFAC publishes an updated sanctions list, re-screen your existing customer base against the new entries. A customer who was clean at onboarding may appear on an updated list weeks or months later. OFAC expects you to catch this.
4. Periodic re-screening. Even without a specific list update trigger, re-screen your full customer base on a regular schedule. Weekly or monthly is standard for most fintechs. High-risk businesses like crypto exchanges may screen daily.
5. Customer information changes. If a customer updates their name, address, or other identifying information, re-screen with the new data. Name changes in particular can reveal matches that the original name did not trigger.
API integration: Python
Here is a complete Python integration using the Verifex API. This example covers single screening, batch screening, and error handling:
import os
import requests
from typing import Optional
VERIFEX_API_KEY = os.environ["VERIFEX_API_KEY"]
BASE_URL = "https://api.verifex.dev/v1"
def screen_entity(
name: str,
entity_type: str = "person",
dob: Optional[str] = None,
nationality: Optional[str] = None,
) -> dict:
"""Screen a single entity against OFAC and other sanctions lists."""
payload = {"name": name, "type": entity_type}
if dob:
payload["date_of_birth"] = dob
if nationality:
payload["nationality"] = nationality
response = requests.post(
f"{BASE_URL}/screen",
headers={
"Authorization": f"Bearer {VERIFEX_API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=10,
)
response.raise_for_status()
return response.json()
# --- Single screening ---
result = screen_entity("Vladimir Putin", entity_type="person")
if result["risk_level"] in ("critical", "high"):
print(f"MATCH FOUND: {result['matches'][0]['name']}")
print(f" Source: {result['matches'][0]['source']}")
print(f" Confidence: {result['matches'][0]['confidence']}%")
print(f" Risk level: {result['risk_level']}")
# Block transaction, flag for compliance review
else:
print(f"Clear — risk level: {result['risk_level']}")
# Proceed with onboarding or transactionFor batch re-screening, use the batch endpoint to screen up to 100 entities per request:
def batch_screen(entities: list[dict]) -> list[dict]:
"""Screen up to 100 entities in a single request."""
response = requests.post(
f"{BASE_URL}/screen/batch",
headers={
"Authorization": f"Bearer {VERIFEX_API_KEY}",
"Content-Type": "application/json",
},
json={"entities": entities},
timeout=30,
)
response.raise_for_status()
return response.json()["results"]
# Re-screen all customers from your database
customers = db.get_all_active_customers()
for i in range(0, len(customers), 100):
batch = customers[i : i + 100]
entities = [
{"name": c.name, "type": "person"} for c in batch
]
results = batch_screen(entities)
for customer, result in zip(batch, results):
if result["risk_level"] in ("critical", "high"):
db.flag_for_review(customer.id, result)
print(f"Flagged: {customer.name}")API integration: Node.js
Here is the equivalent integration in Node.js with TypeScript types and proper error handling:
const VERIFEX_API_KEY = process.env.VERIFEX_API_KEY;
const BASE_URL = "https://api.verifex.dev/v1";
interface ScreeningResult {
risk_level: "critical" | "high" | "medium" | "low" | "none";
matches: {
name: string;
source: string;
confidence: number;
entity_type: string;
sanctions_list: string;
}[];
}
async function screenEntity(
name: string,
type: string = "person",
options?: { dob?: string; nationality?: string }
): Promise<ScreeningResult> {
const response = await fetch(`${BASE_URL}/screen`, {
method: "POST",
headers: {
Authorization: `Bearer ${VERIFEX_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name,
type,
...(options?.dob && { date_of_birth: options.dob }),
...(options?.nationality && { nationality: options.nationality }),
}),
});
if (!response.ok) {
throw new Error(`Screening failed: ${response.status}`);
}
return response.json();
}
// --- Express middleware example ---
async function sanctionsScreenMiddleware(req, res, next) {
try {
const result = await screenEntity(req.body.recipient_name);
if (result.risk_level === "critical") {
// Block immediately
return res.status(403).json({
error: "Transaction blocked by sanctions screening",
reference: result.matches[0]?.name,
});
}
if (result.risk_level === "high") {
// Queue for review, do not process yet
await db.queueForReview({
transaction: req.body,
screening: result,
});
return res.status(202).json({
message: "Transaction pending compliance review",
});
}
// Attach result and continue
req.screeningResult = result;
next();
} catch (err) {
// Screening failure should block the transaction
// Never fail open on sanctions screening
console.error("Screening error:", err);
return res.status(503).json({
error: "Unable to complete sanctions screening",
});
}
}Note the error handling pattern in the middleware: never fail open on sanctions screening. If the screening API is unreachable or returns an error, block the transaction and retry. Allowing transactions through when screening is unavailable is a compliance violation.
Why exact matching is not enough: OFAC's own guidance
OFAC has explicitly stated that exact name matching alone is insufficient for compliance. In their published FAQ, OFAC notes that "the use of one or more of the available screening software programs can significantly assist in compliance" and acknowledges that names on the SDN list may be transliterated from non-Latin scripts in multiple ways.
Consider the practical implications. The OFAC SDN list contains entries like "PUTIN, Vladimir Vladimirovich" with several known aliases. But a customer might enter "Wladimir Putin" (German transliteration), "Poutine, Vladimir" (French transliteration), or simply "V. Putin." Exact matching catches none of these.
This is why every serious screening system uses fuzzy matching algorithms. Verifex combines Levenshtein distance, Soundex phonetic matching, and IDF-weighted token matching to catch transliterations, typos, and name variations. For a deeper technical explanation, read our OFAC screening overview.
Handling matches: risk levels, review, and audit
When a screening returns matches, you need a clear protocol for each risk level. Here is a framework that aligns with regulatory expectations:
Critical (90-100% confidence). This is a near-exact or exact match against a sanctions entry. Block the transaction immediately. Freeze any associated assets. Report to your compliance officer within the hour. File a blocking report with OFAC within 10 business days. Document everything — the query, the match, the action taken, and the timestamp.
High (75-89% confidence). Strong match but not definitive. Place the transaction on hold. Escalate to a compliance analyst for manual review within 24 hours. The analyst should check date of birth, nationality, address, and other identifiers against the sanctions entry. If confirmed, treat as critical. If ruled a false positive, document the reasoning and release the hold.
Medium (50-74% confidence). Moderate similarity, often caused by common name patterns. Flag for review but do not block. An analyst should review within the normal review cycle (typically 1-3 business days). For high-volume operations, you may choose to auto-approve medium matches for low-risk customer segments and only review them for high-risk segments.
Low or None (below 50%). No significant match found. Proceed with the transaction. Log the screening result for audit purposes. No manual review required.
Every screening result — whether it finds a match or not — should be logged with a timestamp, the query parameters, the results, and the disposition decision. This audit trail is what you present to regulators during an examination.
Ongoing monitoring: re-screening when OFAC updates
OFAC updates the SDN list multiple times per week, sometimes adding dozens of new entries at once. When new entities are added, every customer in your database needs to be checked against the additions. There are two approaches:
Full re-screening. Re-screen your entire customer base against the complete updated list on a schedule (weekly or monthly). This is the simplest approach and catches any new designations. With Verifex's batch API at $0.006 per screen, a 10,000-customer re-screen costs $60.
Delta screening. Monitor OFAC list changes and only screen your customer base against newly added entries. This is more efficient for large customer bases but requires infrastructure to track list changes. Some providers, including Verifex, offer webhook notifications when lists are updated so you can trigger delta screening automatically.
Whichever approach you use, document your re-screening policy and schedule. Regulators want to see that you have a systematic process, not ad-hoc screening.
Common OFAC compliance mistakes
Based on published OFAC enforcement actions and our conversations with compliance teams, here are the most common mistakes fintechs make:
- Screening only at onboarding. Customers can be added to sanctions lists after they become your customer. Without ongoing re-screening, you will miss newly designated entities.
- Using only exact matching. OFAC explicitly recognizes that names may be transliterated differently. Exact-only matching is not a defensible compliance posture.
- Failing open. If your screening system goes down or returns an error, never process the transaction anyway. Always fail closed — block the transaction until screening succeeds.
- Not screening counterparties. Screening your own customers is necessary but not sufficient. You must also screen the recipients of outbound payments and transfers.
- No audit trail. If you cannot prove you screened a customer, you might as well not have screened them. Every screening must be logged with timestamp, query, results, and disposition.
- Ignoring non-SDN lists. The OFAC SDN list is the most important, but the Sectoral Sanctions and other non-SDN lists also carry compliance obligations. Screen against the consolidated list to cover all programs.
- Manual processes that do not scale. Searching names on the OFAC website works for 10 customers. It does not work for 10,000. Automate from day one.
- Treating screening as a one-time project. Compliance is ongoing. Lists change, regulations evolve, and your customer base grows. Your screening infrastructure needs to be maintained, tested, and audited continuously.
Getting started with OFAC screening
If you are building a fintech product and need to implement OFAC screening, here is the fastest path to production:
- Sign up for a free Verifex API key (100 free screens per month, no credit card required).
- Integrate the screening API into your onboarding flow using the Python or Node.js examples above.
- Add transaction screening for outbound payments.
- Set up batch re-screening on a weekly or monthly schedule.
- Build an internal review workflow for high-confidence matches.
- Document your screening policy and audit trail process.
The Verifex API screens against OFAC SDN, OFAC Consolidated, UN Security Council, EU Consolidated List, UK HM Treasury, and other major sanctions lists in a single call. You can also try our free OFAC search tool to test name matching without writing any code. For regulatory background on your compliance obligations, visit our compliance resources page.
Get started with Verifex
Screen against OFAC, UN, EU & UK sanctions lists in one API call. Free tier available.
Get Free API Key