Verify Any US Business Entity in Python (Code Examples)
Whether you're building a KYB onboarding flow, automating compliance checks, or simply trying to confirm that a vendor actually exists as a registered legal entity, the ability to verify business entity Python code is a critical skill for US-based developers and compliance engineers. Manually searching Secretary of State portals across 50 states is slow, inconsistent, and impossible to scale. The good news: a single REST API call can now return authoritative state-level registration data for any US business entity in milliseconds.
This guide walks you through the regulatory context that makes business entity verification non-negotiable, then gives you working Python code against the OpenSOSData API so you can go from zero to verified in minutes.
Why Business Entity Verification Matters in the United States
US financial institutions, fintechs, and any company onboarding business clients face a layered set of federal obligations that all start with a single question: Is this a real, legally registered business?
FinCEN Beneficial Ownership (BOI) Rules
The Corporate Transparency Act (CTA), enforced by FinCEN, requires most US companies to file Beneficial Ownership Information (BOI) reports. Before you can even collect BOI data from a business customer, you need to confirm the entity is legitimately registered. An entity that does not appear in any Secretary of State database is a major red flag — and potentially a shell used for fraud or sanctions evasion.
Bank Secrecy Act (BSA) Compliance
Under BSA rules, covered financial institutions must implement Customer Due Diligence (CDD) programs. The CDD Rule (31 CFR § 1010.230) explicitly requires verifying the identity of legal entity customers and identifying their beneficial owners. Secretary of State data is the foundational first step: confirm the entity name, status, formation date, and registered agent before layering on OFAC screening or UBO collection.
KYB Onboarding Velocity
Beyond regulation, there's a business reason: slow KYB kills conversions. Automated entity verification via API compresses what used to take days of manual research into a sub-second lookup, allowing your onboarding funnel to remain friction-free while staying compliant.
What the OpenSOSData API Returns
The OpenSOSData API covers all 50 US states plus Washington D.C., Puerto Rico, and the US Virgin Islands — over 34 million entities in total. A single lookup returns:
- Entity name — exact legal name as filed with the state
- Entity type — LLC, Corporation, LP, etc.
- Entity ID — the state-assigned registration number
- Status — Active, Inactive, Dissolved, Revoked, etc.
- Formation date — date of registration with the state
- Registered agent name and address — the legally designated contact
Pricing is pay-as-you-go with no monthly minimums. Live lookups (fresh data pulled directly from state sources) cost $0.10 each, dropping to as low as $0.0314 at volume. Cached lookups cost $0.01 each, or as low as $0.00314 at volume. For high-frequency batch processing, cached lookups offer a dramatic cost advantage.
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 AccountSetting Up Your Python Environment
You'll need Python 3.7+ and the popular requests library. Install it if you haven't already:
# Install the requests library
pip install requests
Get your API key by signing up at app.opensosdata.com. The key goes in the Authorization header as a Bearer token.
Python Code Examples
Example 1: Basic Live Lookup
This example performs a live lookup against the California Secretary of State for a business named "Acme Tech LLC". Use live_only when your compliance workflow requires the most current state data — for example, during initial onboarding.
import requests
import json
# ── Configuration ──────────────────────────────────────────────
API_URL = "https://api.opensosdata.com/v1/lookup"
API_KEY = "your_api_key_here" # Replace with your actual key
# ── Request payload ────────────────────────────────────────────
payload = {
"entity_name": "Acme Tech LLC", # Legal business name to search
"state": "CA", # Two-letter state code
"cache_preference": "live_only" # Always fetch fresh data from the state
}
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
# ── Make the API call ──────────────────────────────────────────
response = requests.post(API_URL, headers=headers, json=payload)
# ── Handle the response ────────────────────────────────────────
if response.status_code == 200:
data = response.json()
print("Entity Name: ", data.get("entity_name"))
print("Entity Type: ", data.get("entity_type"))
print("State Entity ID: ", data.get("entity_id"))
print("Status: ", data.get("status"))
print("Formation Date: ", data.get("formation_date"))
print("Registered Agent: ", data.get("registered_agent_name"))
print("Agent Address: ", data.get("registered_agent_address"))
else:
print(f"Error {response.status_code}: {response.text}")
Example 2: Cached Lookup for Batch Verification
When running nightly batch jobs or enriching large vendor lists, use cache_first to reduce cost significantly. The API returns cached data when available and falls back to a live fetch otherwise.
import requests
API_URL = "https://api.opensosdata.com/v1/lookup"
API_KEY = "your_api_key_here"
def verify_entity(entity_name: str, state: str, live: bool = False) -> dict:
"""
Verify a US business entity via OpenSOSData.
Args:
entity_name: Legal name of the business entity.
state: Two-letter US state code (e.g., "DE", "NY").
live: If True, forces a fresh state-source lookup ($0.10).
If False, uses cache when available ($0.01).
Returns:
Dictionary containing entity details, or error info.
"""
cache_pref = "live_only" if live else "cache_first"
payload = {
"entity_name": entity_name,
"state": state,
"cache_preference": cache_pref
}
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
resp = requests.post(API_URL, headers=headers, json=payload, timeout=15)
if resp.status_code == 200:
return resp.json()
else:
# Return a structured error so batch jobs don't crash
return {"error": resp.status_code, "detail": resp.text}
# ── Batch example: verify multiple vendors ─────────────────────
vendors = [
{"name": "Global Imports LLC", "state": "DE"},
{"name": "Sunrise Consulting Inc", "state": "TX"},
{"name": "Pacific Freight Corp", "state": "WA"},
]
for vendor in vendors:
result = verify_entity(vendor["name"], vendor["state"])
if "error" in result:
print(f"[FAILED] {vendor['name']} — {result['detail']}")
elif result.get("status", "").lower() != "active":
# Flag inactive or dissolved entities for compliance review
print(f"[REVIEW] {vendor['name']} — Status: {result.get('status')}")
else:
print(f"[OK] {vendor['name']} — Active since {result.get('formation_date')}")
Example 3: Delaware LLC Deep Verification
Delaware is the incorporation capital of the United States — over 60% of Fortune 500 companies are registered there. This snippet is tailored for KYB workflows where Delaware entities are especially common.
import requests
API_URL = "https://api.opensosdata.com/v1/lookup"
API_KEY = "your_api_key_here"
def verify_delaware_entity(entity_name: str) -> None:
"""
Perform a live KYB check for a Delaware-registered entity.
Uses live_only to ensure status is current before onboarding.
"""
payload = {
"entity_name": entity_name,
"state": "DE",
"cache_preference": "live_only" # Live required for onboarding decisions
}
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
resp = requests.post(API_URL, headers=headers, json=payload, timeout=15)
if resp.status_code != 200:
raise RuntimeError(f"Lookup failed: {resp.status_code} — {resp.text}")
entity = resp.json()
# Print a formatted compliance summary
print("=" * 50)
print("KYB Entity Verification Summary")
print("=" * 50)
print(f"Legal Name : {entity.get('entity_name')}")
print(f"Entity Type : {entity.get('entity_type')}")
print(f"State ID : {entity.get('entity_id')}")
print(f"Jurisdiction : Delaware (DE)")
print(f"Status : {entity.get('status')}")
print(f"Formed : {entity.get('formation_date')}")
print(f"Registered Agent : {entity.get('registered_agent_name')}")
print(f"Agent Address : {entity.get('registered_agent_address')}")
# Simple active-status gate
if entity.get("status", "").lower() == "active":
print("\n✅ Entity is ACTIVE — cleared for next KYB stage.")
else:
print("\n⚠️ Entity is NOT ACTIVE — escalate to compliance team.")
verify_delaware_entity("Blackstone Holdings LLC")
Live vs. Cached vs. Cache-Only: Choosing the Right Mode
| cache_preference | Data Source | Cost (standard) | Best For |
|---|---|---|---|
live_only |
Secretary of State (real-time) | $0.10 / lookup | Initial KYB onboarding, compliance decisions |
cache_first |
Cache if available, else live | $0.01–$0.10 | Batch enrichment, periodic monitoring |
cache_only |
OpenSOSData cache only | $0.01 / lookup | High-volume data pipelines, analytics |
Integrating Entity Verification into a KYB Pipeline
A production KYB flow typically looks like this:
- Collect — gather business name, state of formation, and EIN from the applicant.
- Verify entity — call OpenSOSData with
live_onlyto confirm legal name, status, and registered agent. - Screen — run the entity name and beneficial owners through OFAC / sanctions databases.
- Collect BOI — gather beneficial ownership information as required by FinCEN's CTA rules.
- Decision — approve, flag for review, or reject based on risk scoring.
Step 2 is where OpenSOSData fits — it's the authoritative, programmatic replacement for manual state portal searches. Review the full API reference at opensosdata.com/docs/.
Frequently Asked Questions
What states does the OpenSOSData API cover?
The API covers all 50 US states, Washington D.C., Puerto Rico, and the US Virgin Islands — a database of more than 34 million registered business entities. You specify the state using its two-letter postal code in the state field of the POST request.
How much does a live business entity lookup cost?
Standard live lookups cost $0.10 per lookup. At higher volumes, the price drops to as low as $0.0314 per lookup. Cached lookups start at $0.01 and fall to $0.00314 at volume. There are no monthly minimums — pricing is purely pay-as-you-go.
What is the difference between live_only and cache_first?
live_only always fetches fresh data directly from the Secretary of State's source, ensuring you see the current registration status. cache_first returns a cached result when one is available (at $0.01) and falls back to a live fetch if not. For initial onboarding and binding compliance decisions, use live_only. For bulk batch jobs or periodic monitoring, cache_first significantly reduces cost.
Is Secretary of State data sufficient for full KYB compliance?
State registration data is the foundational layer of KYB — it confirms legal existence, status, and registered agent. However, a complete KYB program also requires OFAC/sanctions screening, beneficial ownership (BOI) collection under the Corporate Transparency Act, and risk-based due diligence. Think of entity verification as step one in a multi-step pipeline.
Can I use this API to monitor existing business relationships?
Yes. You can schedule periodic cache_first or live_only lookups on entities already in your portfolio to detect status changes — such as a vendor becoming dissolved, revoked, or administratively suspended. This is a common pattern in ongoing vendor due diligence and third-party risk management programs.
Does the API require a long-term contract?
No. OpenSOSData operates on a pay-as-you-go model with no monthly minimums or long-term commitments. You pay only for the lookups you run. Volume discounts are applied automatically as your usage scales. Sign up at app.opensosdata.com to get started.
What happens if a business entity is not found?
If the entity cannot be located in the specified state's records, the API returns a not-found response rather than fabricating data. This outcome itself is compliance-significant: an entity that cannot be verified in the Secretary of State database should be flagged for manual review or rejection in your KYB workflow.