# Company Due Diligence & KYB: Registry, Liens, OFAC Sanctions (`cpt_engineering/company-due-diligence-check`) Actor

KYB due diligence, one row per company: registry status (6 states), UCC and government liens, OFAC sanctions screening and SAM.gov exclusions. Tested Oct 17, 2026: 3/3 OFAC-listed entities flagged; lien counts matched official CO/CT records. Free if a source fails.

- **URL**: https://apify.com/cpt_engineering/company-due-diligence-check.md
- **Developed by:** [Christopher Tolentino](https://apify.com/cpt_engineering) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $80.00 / 1,000 complete company checks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Company Due Diligence & KYB Check: Registry, UCC Liens, OFAC Sanctions Screening & Federal Exclusions

**One row per company** answering four questions from official government data: *Is the company registered and active? Does it already have UCC liens, and who are its secured lenders? Is its name on a U.S. Treasury OFAC sanctions list? Is it excluded from U.S. federal contracts and programs (SAM.gov)?* Built for **credit, underwriting, KYB and sanctions-screening, vendor-onboarding and equipment-finance teams** that check companies one at a time from their own systems, or re-check a customer portfolio on a schedule.

**Last verified:** 2026-10-16 (daily automated self-test against the live state, OFAC and SAM.gov sources).

### Tested accuracy (Oct 17, 2026, live build, 20 companies across CO, CT, NY, OR, PA, TX)

| | |
|---|---|
| Sanctions | **3 of 3** OFAC-listed entities flagged, including a New York-registered SDN company. A same-name entry established after the company was formed gets a `date_note` |
| UCC lien counts | **Matched the official CO and CT records for 6 of 6 lien debtors** (e.g. 19 of 19 active filings for a brewer with 58 filings on record) |
| Expired or closed liens | **Not counted**: lapsed, terminated and released filings are excluded |
| Amendments | **Not double-counted**: amendments and continuations are attached to the original filing |
| Wrong-company liens | **Not counted**: lien counts use exact-name matches only; similar names are listed separately for review |
| Rows | **One row per input**, with an explicit NOT_FOUND for unregistered names (3 of 3) |
| Speed | **~5.5 s per company** in a batch of 20 (registry, UCC and government liens, OFAC and SAM.gov in one row) |
| Billing | **Free when a source fails** (PARTIAL rows are not charged) |

### What to check in any KYB or lien tool

1. **Expired liens counted as active**: a UCC filing lapses after 5 years unless continued, and can be terminated earlier. "Active" should mean not terminated *and* not lapsed.
2. **Amendments double-counted**: amendments and continuations are separate rows in state data; they belong to the original lien, not on top of it.
3. **Wrong-company matches**: short and common names ("M & C Concrete", "Star Group") easily match another company. Look for a match score, the matched legal name, and similar names kept apart.
4. **Charged for failed rows**: check whether you pay when a state source fails or nothing is found. Every input should get a row that says found, not found or failed.

**Why choose this Actor**
| | |
|---|---|
| Reliability | Every cloud test run succeeded (Oct 16, 2026); timeouts, 429 and 5xx errors retried with exponential backoff; one polite rate limit per state portal; a daily self-test checks the live sources and their column layouts |
| Fair billing | Charged only for **COMPLETE** checks. If any source fails (a state portal, the OFAC lists or the SAM.gov file), the row is marked PARTIAL (or SEARCH_FAILED) and is **free** |
| Sanctions screen | Every company is screened against the **OFAC SDN list and the consolidated non-SDN lists** (U.S. Treasury): match flag, list, matched entity, programs, listed countries, 0-100 score, OFAC record link and the list date used |
| Federal exclusions | Every company is also screened against the **SAM.gov exclusions** daily public extract (debarred or suspended firms): excluding agency, exclusion type, active and termination dates, UEI/CAGE, score and the file date used |
| Registry | 6 official state business registries (CO, CT, NY, OR, PA, TX), fuzzy name match with a 0-100 score |
| Liens | UCC financing statements from the CO, CT and OR filing offices: active lien count, secured parties, newest filing, next lapse date, all-assets lien (CO) |
| Government liens | Separate `government_liens` field: active federal tax (IRS), state tax, municipal, state labor and other statutory liens filed against the company in CO, CT and OR (same state filing-office data), never mixed into the UCC counts |
| Risk flags | SANCTIONS_POTENTIAL_MATCH, SANCTIONS_SIMILAR_NAME, FEDERAL_EXCLUSION_POTENTIAL_MATCH, FEDERAL_EXCLUSION_SIMILAR_NAME, TX_RIGHT_TO_TRANSACT_FORFEITED (and other non-active Texas codes), NOT_FOUND_IN_REGISTRY, REGISTRY_TIED_MATCHES, REGISTRY_STATUS_INACTIVE, FORMED_LAST_12_MONTHS, HAS_ACTIVE_UCC_LIENS, POSSIBLE_RELATED_UCC_FILINGS, HAS_ACTIVE_GOVERNMENT_LIENS, FEDERAL_TAX_LIEN, SANCTIONS_MATCH_ESTABLISHED_AFTER_FORMATION, MULTIPLE_SECURED_PARTIES, ALL_ASSETS_LIEN, NEW_UCC_FILING_LAST_90_DAYS, LIEN_LAPSING_NEXT_180_DAYS |
| Honest coverage | `ucc_coverage` says whether lien results are complete (company formed in CO or CT), recent only (OR) or not covered (other states) |
| Audit trail | Links to the official registry record and to each UCC filing |
| Texas franchise tax | `tx_right_to_transact` from the Texas Comptroller: ACTIVE, ACTIVE_ELIGIBLE_FOR_TERMINATION, FORFEITED, FRANCHISE_TAX_INVOLUNTARILY_ENDED, FRANCHISE_TAX_NOT_ESTABLISHED or FRANCHISE_TAX_ENDED. A Texas entity can show *Active* at the Secretary of State and still have forfeited its right to transact business |
| Compliance | Business data only: no officer, owner or individual-debtor names; individuals on the OFAC and SAM.gov lists are dropped when the lists are loaded and are never screened or returned; government liens only against business debtors (no judgment, child-support, hospital or other liens against people); no phones or emails |
| Accuracy | Registry results are identical to [US Company Lookup & KYB](https://apify.com/cpt_engineering/us-company-lookup-kyb) and lien results to [UCC Lien Filings](https://apify.com/cpt_engineering/ucc-lien-filings) for the same names (same code, same sources) |

### Quick start

```json
{"companies": ["New Belgium Brewing", "Specialty Saw Inc | CT"]}
```

Add ` | ST` after a name when you know the registry state: it is much faster (about 5 s instead of about 30 s for one company).

### Use it from your app (one company per call)

```bash
curl -X POST "https://api.apify.com/v2/acts/cpt_engineering~company-due-diligence-check/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" -d '{"companies": ["Specialty Saw Inc | CT"]}'
```

The Apify MCP server exposes the same call to AI agents.

### Re-check a portfolio on a schedule

1. Save your customer or borrower list as a **task**.
2. Add a **schedule** (e.g. monthly on the 1st).
3. Add a **webhook** on `ACTOR.RUN.SUCCEEDED` to your system, Zapier, Make or n8n, and act on rows whose `risk_flags` changed (e.g. new HAS_ACTIVE_UCC_LIENS, NEW_UCC_FILING_LAST_90_DAYS or REGISTRY_STATUS_INACTIVE).

### Output (one row per company)

| Field | Meaning |
|---|---|
| `check_status` | COMPLETE (charged), PARTIAL (a state source failed; free), SEARCH_FAILED (free) |
| `risk_flags` | List of flags, see above |
| `registry_match_status`, `registry_match_score` | EXACT, STRONG, POSSIBLE or NOT_FOUND, with 0-100 score |
| `state`, `entity_id`, `entity_name`, `entity_type`, `status`, `status_normalized`, `formation_date`, `record_url` | Registered entity |
| `registry_other_matches`, `registry_match_chosen_by_lien_state` | Other registered entities with similar names; true if the equal-score entity in the state where the liens were filed was chosen |
| `ucc_coverage` | COVERED, OR_LAST_MONTH_ONLY, NOT_COVERED_STATE, UNKNOWN_STATE |
| `lien_result`, `active_lien_count`, `secured_parties`, `secured_party_count` | Lien summary; `secured_parties` = lender name + active filings |
| `possible_related_filings`, `possible_related_filing_count` | Filings whose debtor name is only similar to the company's (a typo or extra words, match score 85-94). Listed for review, never counted in `active_lien_count` or the flags. Counts use debtor names equal to the company's after normalizing punctuation, legal form and word order (score 95+). Equivalent legal forms match (Inc = Incorporated = Corp = Corporation = Co; LLC = L.L.C. = Limited Liability Company); when both names carry a legal form and the forms conflict (LLC vs LP vs Inc/Corp vs LLP), the filing is a different entity (score 90, listed here, not counted); the company's form is the one you typed or, if you typed none, the one in its registry record. Government liens follow the same rule |
| `latest_filing_date`, `next_lapse_date`, `all_assets_lien_co` | Newest UCC filing, nearest lapse date, Colorado collateral says "all assets" |
| `filings` | Up to *Max filings listed* filings: state, number, type, dates, status, lender, source link |
| `tx_right_to_transact` | Texas Comptroller right-to-transact status (Texas matches only) |
| `government_liens` | `result` (GOVERNMENT_LIENS_FOUND, NO_ACTIVE_GOVERNMENT_LIENS_FOUND, FAILED), `active_count`, `by_kind` (FEDERAL_TAX, STATE_TAX, MUNICIPAL, STATE_LABOR, OTHER_FEDERAL, OTHER_STATUTORY, STATE_AGENCY), `latest_filing_date`, `liens` \[state, filing_number, lien_kind, creditor, filing_date, lapse_date, status, source link]. Exact company name only (score 95+); ended (released, terminated, lapsed) liens are not counted |
| `sanctions_match`, `sanctions_list_date` | true when a listed entity has the same name (score >= 95); OFAC list date used |
| `sanctions_screen` | `result` (POTENTIAL_MATCH, SIMILAR_NAME for scores 90-94, NO_MATCH, FAILED), `lists`, `list_date`, `matches` \[list, matched_name, primary_name, programs, listed_countries, score, ofac_id, url, listed_established, date_note]. `date_note` is set when OFAC's "Organization Established Date" is later than the company's registry formation date (likely a different entity with the same name; still listed for review) |
| `exclusions_match`, `exclusions_list_date` | true when an excluded firm has the same name (score >= 95); SAM.gov file date used |
| `federal_exclusions` | `result`, `list`, `list_date`, `matches` \[matched_name, classification, excluding_agency, exclusion_type, exclusion_program, active_date, termination_date, uei, cage, state, country, score] |
| `registry_states_failed`, `ucc_states_failed`, `checked_at` | Source errors and check time |

### How the lien search works

Liens are searched under your input name and, when it differs, the registered legal name found in the registry. A UCC-1 is normally filed in the state where the debtor is organized, so a company formed in Texas can have liens in Texas that this Actor cannot see (`UCC_STATE_NOT_COVERED`). Oregon publishes only the previous month's new filings (`UCC_OREGON_RECENT_ONLY`). Connecticut keeps active liens plus those lapsed less than a year; Colorado keeps full history. When several registered companies share the name equally, the one in the state where the liens were filed is chosen.

### How the government lien search works

The same CO, CT and OR filing-office datasets also record liens filed by government agencies. Connecticut: IRS, Department of Revenue Services / State, municipal and Labor liens (active rows only). Colorado: IRS, other federal, other statutory and CHFA liens; a lien is ended when a release or termination is filed or its lapse date has passed, and an IRS lien with no published lapse date is counted as active for 10 years from filing (federal tax liens self-release after about 10 years unless refiled). Oregon: IRS liens, previous month only. Only organization debtors whose name equals the company's (score 95+) are returned; agricultural, hospital, child-support, restitution and personal-judgment liens are never read. Government liens are listed for information and do not change the price.

### How the sanctions and exclusions screen works

- **Lists:** OFAC SDN + consolidated non-SDN lists (SDN.CSV, CONS_PRIM.CSV with aliases from the Sanctions List Service) and the SAM.gov Exclusions Public V2 daily extract. Both are U.S. government public data and need no key.
- **Entities only:** OFAC individuals, vessels and aircraft and SAM.gov individuals and vessels are dropped while loading. SAM.gov cross-reference and comment text is never read.
- **Daily cache:** lists are downloaded at most once a day and cached in a key-value store named `company-check-screening-cache` in your Apify account (about 1.3 MB). Each row shows the list date used. If a download fails, a cached list up to 7 days old is used and a `warning` is added; with no usable list the screen is FAILED and the check is PARTIAL (free).
- **Matching:** your input name and the registered legal name are compared with every entity name and alias. Score >= 95 (same words; legal form, spacing, punctuation or order may differ) = POTENTIAL_MATCH; 90-94 = SIMILAR_NAME; contained-only names ("Star Group" vs "Costar Group") stay at or below 91. Common names we tested (e.g. "Global Trading LLC", "ABC Construction LLC", "First National Bank", "Apple Inc") returned NO_MATCH.
- **Not a determination:** a name match is a lead for review, not a finding that a company is sanctioned or excluded. Confirm with the linked OFAC record (country, programs, addresses) or SAM.gov (UEI, CAGE) before acting. This Actor is not a substitute for your compliance program.

### Pricing

Pay per event, no start fee:

| | No discount | Bronze | Silver | Gold+ |
|---|---|---|---|---|
| COMPLETE check (per company) | **$0.10** | $0.093 | $0.087 | $0.08 |
| PARTIAL or SEARCH_FAILED check (any source failed) | free | free | free | free |

One COMPLETE check includes the registry match, UCC lien summary, OFAC sanctions screen and SAM.gov exclusions screen.

Example: a monthly re-check of 200 customers costs $20.00. Set *Max companies* or a run spend limit (*Max cost per run*) to cap a run; it stops cleanly at the limit.

### Related Actors (same publisher)

- [US Company Lookup & KYB](https://apify.com/cpt_engineering/us-company-lookup-kyb): registry lookup only, for large lists; includes the Texas right-to-transact status.
- [UCC Lien Filings](https://apify.com/cpt_engineering/ucc-lien-filings): full filing rows, a daily new-filings feed and a lapsing-soon list.

### Support

Open an issue on this Actor or email **cpt-datatools@mail.grokbot.com**. We reply to issues and support emails within 1 business day.

### Changelog

- **Oct 17, 2026 (12:30 PM):** *Tested accuracy* speed updated from the 12:11 PM ET re-test on the live build.
- **Oct 17, 2026 (afternoon, speed):** the UCC and government-lien searches now share their name-search requests to each state portal (about 30% fewer requests per company), so a batch is faster with identical results.
- **Oct 17, 2026 (afternoon):** conflicting legal forms are no longer counted: a lien filed against "STAR GROUP LP" is not counted for Star Group LLC (UCC counts and `government_liens`; listed in `possible_related_filings`). Equivalent forms (Inc / Corp / Co, LLC / L.L.C.) still match. The sanctions screen is unchanged (a same-name listed entity with another legal form is still a potential match).
- **Oct 17, 2026 (midday):** added the *Tested accuracy* results (20-company test on the live build) and a buyer's checklist.
- **Oct 17, 2026 (later):** new `government_liens` field (tax, municipal, labor and other government liens in CO, CT, OR; flags HAS_ACTIVE_GOVERNMENT_LIENS, FEDERAL_TAX_LIEN). Sanctions matches now carry `listed_established` and a `date_note` when the listed entity was established after the company was formed (flag SANCTIONS_MATCH_ESTABLISHED_AFTER_FORMATION). Colorado names no longer carry status suffixes such as ", Delinquent November 1, 2010".
- **Oct 17, 2026:** lien counts now use only filings whose debtor name matches the company (score 95+); similar names are listed in `possible_related_filings` and flagged POSSIBLE_RELATED_UCC_FILINGS. Fixed short names such as "M & C Concrete LLC" (registered name with a trailing period; 'starts with' search) and stopped a generic name ("The Concrete Company") from matching a more specific one.
- **Oct 16, 2026 (late night):** v0.2: OFAC sanctions screen (SDN + non-SDN, entities only), SAM.gov federal exclusions screen, Texas `tx_right_to_transact`; launch price $0.10 per COMPLETE check.
- **Oct 16, 2026 (night):** public release; daily automated self-test with source schema-change detection.
- **Oct 16, 2026:** launched: 6 registries + CO/CT/OR UCC, risk flags, coverage field, free PARTIAL rows.

### Limitations

- Not a certified search; use the official state search for legal lien-priority opinions.
- Name matching is fuzzy; review POSSIBLE matches and REGISTRY_TIED_MATCHES.
- Sanctions and exclusions screening is by name only (no address or ID matching) and covers entities only; it does not screen owners, officers or other individuals, and it does not cover non-U.S. lists, the BIS Entity List or adverse media.

### Source data disclaimer

Data from the Colorado Information Marketplace (data.colorado.gov), data.ct.gov, data.ny.gov, data.oregon.gov, data.pa.gov and data.texas.gov. Colorado: "The State of Colorado makes no warranty as to the accuracy of this data." Sanctions data: U.S. Department of the Treasury, Office of Foreign Assets Control (Sanctions List Service). Exclusions data: SAM.gov (U.S. General Services Administration). Not affiliated with or endorsed by any state or federal agency.

# Actor input Schema

## `companies` (type: `array`):

Company names, one per line. Optional state hint after ' | ' to search one registry, e.g. 'Acme Robotics LLC | CO' (faster). One result row per company.

## `registryStates` (type: `array`):

State business registries to search when a company has no state hint. Empty = all six.

## `uccStates` (type: `array`):

State UCC filing offices to search for liens. Empty = all three. A UCC-1 is normally filed in the state where the company is organized, so lien results are complete only for companies formed in CO, CT or OR (see ucc_coverage).

## `minMatchScore` (type: `integer`):

0-100 similarity needed for a registry match and for a UCC debtor match. 100 = same name; 93+ = same words; 85 (default) allows small differences.

## `activeLiensOnly` (type: `boolean`):

true (default): count and list only active financing statements. false: also terminated and lapsed ones (history).

## `maxFilingsListed` (type: `integer`):

How many UCC filings to list in each row's 'filings' array (counts always cover all of them).

## `maxCompanies` (type: `integer`):

Maximum companies checked (and charged) in one run.

## `socrataAppToken` (type: `string`):

Optional free app token from a state open-data portal. Not required.

## Actor input object example

```json
{
  "companies": [
    "New Belgium Brewing",
    "Specialty Saw Inc | CT"
  ],
  "registryStates": [
    "CO",
    "CT",
    "NY",
    "OR",
    "PA",
    "TX"
  ],
  "uccStates": [
    "CO",
    "CT",
    "OR"
  ],
  "minMatchScore": 85,
  "activeLiensOnly": true,
  "maxFilingsListed": 10,
  "maxCompanies": 1000
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "New Belgium Brewing",
        "Specialty Saw Inc | CT"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cpt_engineering/company-due-diligence-check").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "companies": [
        "New Belgium Brewing",
        "Specialty Saw Inc | CT",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cpt_engineering/company-due-diligence-check").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "New Belgium Brewing",
    "Specialty Saw Inc | CT"
  ]
}' |
apify call cpt_engineering/company-due-diligence-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cpt_engineering/company-due-diligence-check"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dCbvRKoPQ6DjVx9su/builds/OZFrQuQxqlm29wV2m/openapi.json
