How to Pair OFAC Sanctions Screening with SOS Entity Verification API
For compliance teams, fintechs, lenders, and any business onboarding commercial clients, two questions must be answered before a relationship begins: Is this business real and in good standing? and Is this business — or anyone behind it — on a sanctions list? Answering either question in isolation leaves a dangerous gap. A company can be a legitimately registered LLC in Delaware while still appearing on the OFAC Specially Designated Nationals (SDN) list. Conversely, a business can clear sanctions screening but turn out to be a dissolved shell with a fabricated EIN. A robust OFAC screening entity verification API workflow closes both gaps simultaneously, and that is exactly what this guide walks you through.
Why This Combination Is Non-Negotiable Under U.S. Law
Three overlapping regulatory frameworks demand that you verify both identity and sanctions status before onboarding a business client.
Bank Secrecy Act (BSA) and Customer Due Diligence (CDD)
The BSA, enforced by FinCEN, requires covered financial institutions to establish and maintain written Customer Due Diligence programs. The 2016 CDD Final Rule added a fourth pillar to AML programs: understanding the nature and purpose of customer relationships and identifying the beneficial owners of legal entity customers. Simply having a business name and EIN is not sufficient — you must confirm the entity actually exists as a legal person in its state of formation.
FinCEN Beneficial Ownership Information (BOI)
The Corporate Transparency Act (CTA) and FinCEN's BOI reporting rules require most U.S. companies to disclose their beneficial owners. For compliance teams consuming this data, Secretary of State records provide the foundational anchor: formation date, registered agent, entity type, and current status. If the SOS record does not match what a customer claims, red flags must be escalated before any OFAC check even runs.
OFAC Sanctions Screening Obligations
OFAC regulations apply to virtually all U.S. persons and entities, not just banks. If you onboard a business that is owned or controlled by an SDN, you are exposed to civil and potentially criminal liability. OFAC's 50 Percent Rule also means that any entity 50% or more owned by a blocked person is itself blocked — even if that entity's name does not appear directly on the SDN list. This is precisely why you cannot skip entity verification: you need accurate ownership data to apply the 50 Percent Rule correctly.
The Two-Layer Verification Model
The most defensible compliance architecture uses two sequential layers:
- Layer 1 — SOS Entity Verification: Confirm the business exists, is active, and matches the customer's stated details (name, state, formation date, registered agent).
- Layer 2 — OFAC Sanctions Screening: Screen the verified entity name, any DBAs, beneficial owners, and the registered agent against OFAC's SDN list, the Consolidated Sanctions List, and relevant secondary lists (e.g., CAATSA, OFSI).
Running Layer 2 before Layer 1 is inefficient and unreliable — you would be screening names that may not correspond to real, active legal entities. Running Layer 1 without Layer 2 is a compliance failure. Together, they form a defensible, auditable KYB workflow.
Start Verifying Entities from $0.10 per Lookup
Live lookups from $0.10, as low as $0.0314 with volume. Pay as you go.
Create Free AccountUsing the OpenSOSData API for Layer 1
OpenSOSData provides a single REST API endpoint that covers all 50 U.S. states, Washington D.C., Puerto Rico, and the U.S. Virgin Islands — over 34 million business entities. It returns entity name, type, ID, status, formation date, registered agent, and registered agent address. Pricing is pay-as-you-go: live lookups start at $0.10 (as low as $0.0314 at volume) and cached lookups start at $0.01 (as low as $0.00314 at volume).
Full documentation is available at opensosdata.com/docs/. You can create an account at app.opensosdata.com.
Python Example: SOS Lookup + OFAC Screening Pipeline
The example below demonstrates a complete two-layer pipeline. It uses the OpenSOSData API for entity verification and a placeholder function representing your OFAC screening provider (e.g., Comply Advantage, Sanctions.io, or a direct OFAC SDN API integration).
import requests
import json
# ── Configuration ─────────────────────────────────────────────
SOS_API_URL = "https://api.opensosdata.com/v1/lookup"
SOS_API_KEY = "YOUR_OPENSOSDATA_API_KEY"
# Replace this URL/key with your actual OFAC screening provider
OFAC_SCREEN_URL = "https://your-ofac-provider.example.com/screen"
OFAC_API_KEY = "YOUR_OFAC_API_KEY"
def layer1_sos_lookup(entity_name: str, state: str) -> dict:
"""
Layer 1: Verify the business entity exists and is active
using the OpenSOSData Secretary of State API.
cache_preference='live_only' ensures fresh state data.
"""
headers = {
"x-api-key": SOS_API_KEY,
"Content-Type": "application/json",
}
payload = {
"entity_name": entity_name,
"state": state, # Two-letter state code, e.g. "DE"
"cache_preference": "live_only" # Options: live_only | cache_first | cache_only
}
response = requests.post(SOS_API_URL, headers=headers, json=payload, timeout=30)
response.raise_for_status()
return response.json()
def layer2_ofac_screen(names_to_screen: list[str]) -> dict:
"""
Layer 2: Screen verified entity name, DBAs, and beneficial
owners against the OFAC SDN and Consolidated Sanctions lists.
Replace this stub with your real OFAC provider's SDK/API.
"""
headers = {
"x-api-key": OFAC_API_KEY,
"Content-Type": "application/json",
}
payload = {"names": names_to_screen}
response = requests.post(OFAC_SCREEN_URL, headers=headers, json=payload, timeout=30)
response.raise_for_status()
return response.json()
def run_kyb_pipeline(entity_name: str, state: str, beneficial_owners: list[str]):
"""
Full KYB pipeline:
1. SOS entity verification
2. OFAC sanctions screening on verified names
"""
print(f"\n{'='*55}")
print(f"Starting KYB pipeline for: {entity_name} ({state})")
print(f"{'='*55}")
# ── Layer 1: SOS Verification ──────────────────────────────
print("\n[Layer 1] Querying Secretary of State records...")
sos_result = layer1_sos_lookup(entity_name, state)
entity = sos_result.get("entity", {})
status = entity.get("status", "").lower()
print(f" Entity Name : {entity.get('name')}")
print(f" Entity Type : {entity.get('type')}")
print(f" State ID : {entity.get('id')}")
print(f" Status : {entity.get('status')}")
print(f" Formed On : {entity.get('formation_date')}")
print(f" Reg. Agent : {entity.get('registered_agent')}")
print(f" Agent Address : {entity.get('registered_agent_address')}")
# Hard stop if the entity is not active
if status != "active":
print(f"\n ❌ FAIL — Entity is not active (status: '{status}'). Onboarding halted.")
return {"pass": False, "reason": f"Entity status is '{status}'"}
print(" ✅ Entity is active. Proceeding to OFAC screening.")
# ── Layer 2: OFAC Screening ────────────────────────────────
# Compile all names: verified entity name + any beneficial owners
verified_name = entity.get("name", entity_name)
names_to_check = [verified_name] + beneficial_owners
print(f"\n[Layer 2] Screening {len(names_to_check)} name(s) against OFAC lists...")
ofac_result = layer2_ofac_screen(names_to_check)
hits = ofac_result.get("hits", [])
if hits:
print(f" ❌ FAIL — {len(hits)} OFAC match(es) found:")
for hit in hits:
print(f" • {hit.get('matched_name')} — List: {hit.get('list')}")
return {"pass": False, "reason": "OFAC match detected", "hits": hits}
print(" ✅ No OFAC matches found.")
print("\n[Result] ✅ KYB PASSED — Entity verified and sanctions-clear.")
return {
"pass": True,
"entity": entity,
"ofac_result": ofac_result
}
# ── Run the pipeline ───────────────────────────────────────────
if __name__ == "__main__":
result = run_kyb_pipeline(
entity_name = "Acme Trading LLC",
state = "DE",
beneficial_owners = ["Jane Doe", "John Smith"] # From your customer intake form
)
print("\nFinal result:")
print(json.dumps(result, indent=2))
Comparison: SOS-Only vs. OFAC-Only vs. Combined Workflow
| Verification Approach | Confirms Entity Exists | Confirms Active Status | Screens SDN List | Supports BOI / CDD | Regulatory Coverage |
|---|---|---|---|---|---|
| SOS Lookup Only | ✅ | ✅ | ❌ | Partial | Incomplete |
| OFAC Screening Only | ❌ | ❌ | ✅ | ❌ | Incomplete |
| SOS + OFAC Combined | ✅ | ✅ | ✅ | ✅ | Full KYB coverage |
Best Practices for Production Deployments
Use cache_preference Strategically
For initial onboarding decisions, always use cache_preference: live_only to pull fresh Secretary of State data. For periodic re-verification (e.g., annual reviews), cache_first reduces cost significantly — cached lookups are as low as $0.00314 at volume — while still refreshing data when the cache is stale.
Screen All Associated Names
Do not limit OFAC screening to the legal entity name alone. Screen the registered agent, any disclosed beneficial owners, controlling persons, and known DBAs. The 50 Percent Rule means that an unlisted subsidiary of a blocked entity is itself blocked.
Maintain an Audit Trail
Log the full SOS API response (including the entity ID, status, and formation date) alongside your OFAC screening results and timestamp. Regulators expect documented evidence that checks were performed and when.
Automate Ongoing Monitoring
Entity status can change. A business that was active at onboarding can be administratively dissolved six months later. Schedule periodic SOS re-verification, and run OFAC re-screening whenever beneficial ownership changes are reported by the customer or detected through BOI filings.
Frequently Asked Questions
Does OFAC screening replace Secretary of State entity verification?
No. OFAC screening tells you whether a name appears on a sanctions list; it cannot confirm whether a business entity actually exists, is currently active, or is properly registered in its home state. Secretary of State verification through an API like OpenSOSData is the only reliable way to confirm legal existence and standing.
Which U.S. states does OpenSOSData cover?
OpenSOSData covers all 50 U.S. states, Washington D.C., Puerto Rico, and the U.S. Virgin Islands — a database of more than 34 million business entities. See the full coverage details in the API documentation.
What does cache_preference: live_only mean, and when should I use it?
Setting cache_preference to live_only instructs the OpenSOSData API to pull a fresh record directly from the Secretary of State source rather than returning a cached result. Use this for initial onboarding decisions where data freshness is critical. For periodic monitoring or bulk pre-screening, cache_first or cache_only reduce costs while still providing accurate data for most use cases.
What is the OFAC 50 Percent Rule and why does it affect my KYB process?
Under the OFAC 50 Percent Rule, any entity that is 50% or more owned — directly or indirectly — by one or more Specially Designated Nationals (SDNs) is itself considered blocked, even if that entity is not named on the SDN list. This means you must verify beneficial ownership and screen those owners, not just the legal entity name. SOS data helps establish the registered identity of the entity, while your OFAC provider screens all associated individuals.
How much does OpenSOSData cost for a typical KYB workflow?
OpenSOSData charges on a pay-as-you-go basis with no subscription required. Live lookups (fresh from the Secretary of State) start at $0.10 per query and drop as low as $0.0314 at high volume. Cached lookups start at $0.01 and can be as low as $0.00314 at volume. For most KYB workflows combining live onboarding checks with cached periodic reviews, the blended cost per entity is a fraction of a dollar. Sign up to see current volume pricing tiers.
Am I required to re-screen existing customers against OFAC and SOS records?
Yes. FinCEN's CDD Rule and OFAC guidance both contemplate ongoing monitoring, not just point-in-time onboarding checks. Entity status can change (dissolution, revocation), and OFAC lists are updated frequently. Best practice is to re-run SOS verification at least annually and to re-run OFAC screening whenever there is a triggering event such as a change in ownership, a large transaction, or an OFAC list update.
Can I use OpenSOSData without a long-term contract?
Yes. OpenSOSData operates on a fully pay-as-you-go model with no monthly minimum, no annual contract, and no setup fee. You pay only for the lookups you perform. Create a free account at app.opensosdata.com to get started immediately.
Conclusion
A compliant KYB program in the United States requires both dimensions of verification: confirming a business entity is real and active through Secretary of State records, and confirming it is not subject to OFAC sanctions. Neither check alone satisfies BSA/CDD obligations or protects your organization from regulatory and reputational risk. By integrating the OpenSOSData OFAC screening entity verification API into a two-layer pipeline, compliance teams can automate this process, maintain defensible audit trails, and onboard business clients with confidence — at a cost that scales with volume rather than against it. Start building your workflow today at opensosdata.com/docs/.