# Business Entity & UCC Lien Search — KYB Company Lookup (`shelvick/business-entity-lien-search`) Actor

Search official US state business registries (Secretary of State records) by company name — normalized entity records: legal name, ID, type, status, formation date, registered agent, officers — joined to UCC lien filings, in one call. KYB company verification for lending and diligence agents.

- **URL**: https://apify.com/shelvick/business-entity-lien-search.md
- **Developed by:** [Scott Helvick](https://apify.com/shelvick) (community)
- **Categories:** Business, Developer tools, Lead generation
- **Stats:** 4 total users, 2 monthly users, 96.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $17.00 / 1,000 entity record resolveds

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Business Entity & UCC Lien Search

Verify a US company and see the liens against it in one call. Search official
state business registries by company name for the normalized entity record —
legal name, ID, type, status, formation date, registered agent, officers — and
get each entity **joined to its UCC / lien filings**. Built for KYB, lending, and
diligence agents that need to answer *"is this company real, in good standing, and
does it already have liens against its assets?"* without stitching two systems
together.

### What this does

- **Business entity search by company name** across multiple US states in one
  call — the lookup you'd otherwise run on each state's Secretary of State
  business search, returned as a single normalized record per matched entity
  (company-registration lookup / business-entity verification).
- **Entity → UCC lien join.** For covered states, each resolved entity is joined
  to the Uniform Commercial Code (secured-transaction) filings recorded against it
  as debtor — filing number, type, status, filed/lapse dates, secured party
  (lender), and collateral. This is the differentiator: entity search and lien
  search, connected, keyed by the debtor's legal name.
- **Normalized fields per entity:** legal name, state entity/registration ID,
  entity type, registration status (e.g. Good Standing, Active, Forfeited,
  Dissolved), formation/registration date, jurisdiction of formation, registered
  agent, principal / mailing address, and officers where the state publishes them.
- **Multi-state in one request** — pass a company name, optionally scope to a list
  of states, and get one record per matched entity across every covered state.
- **KYB / diligence use cases:** confirm a counterparty is registered and in good
  standing, check whether a borrower's assets are already encumbered before
  lending, enrich a CRM/onboarding record with the legal entity + lien picture,
  screen an acquisition target, or resolve which state(s) a company is registered
  in.
- **Deterministic and agent-callable.** Every result carries a machine-readable
  `status` (`completed` / `no_match` / `not_covered` / `failed`), an explicit
  `lien_coverage` outcome, and structured `field_notes` explaining any field that
  is structurally absent, so an agent can reason about coverage instead of guessing.

### Why the entity → lien join matters

Anyone can look up whether a company is registered. The expensive, manual part of
KYB and lending diligence is the *second* question — are there already liens
against the company's assets? Answering it normally means finding the entity in one
system, then searching a separate UCC/secured-transactions registry by hand,
matching names, and hoping you found the same legal entity.

This Actor does both and connects them. It resolves the entity from the state
business register, then searches that state's UCC filings by the entity's *core*
legal name and attaches only the filings whose debtor name actually matches —
precise, so a lien against a similarly-named company never gets misattributed. One
call returns the entity plus its lien exposure, ready for a risk decision.

### How it compares to standalone registry tools

| | This Actor | Standalone entity-search tools | Single-state UCC scrapers |
|---|---|---|---|
| Entity search by name | Yes, multi-state | Usually yes | No |
| Normalized schema across states | Yes | Varies | N/A |
| UCC / lien filings | **Joined to each entity** | No | Yes, but not linked to an entity |
| One call for entity + liens | **Yes** | No | No |
| Machine-readable status + coverage notes | Yes | Rarely | Rarely |

The design bet: multi-jurisdiction assembly behind one schema, plus the
entity-to-lien join, is worth more to a diligence workflow than any single registry
scraped in isolation.

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `companyName` | string | one of these | — | The company name to search, e.g. `Tesla` or `Acme Holdings LLC`. |
| `companyNames` | array of strings | one of these | `[]` | Multiple company names to verify in one run (batch); each is resolved and billed independently. |
| `states` | array of strings | no | all covered | Two-letter US state codes to scope the entity search. Lien joins cover a subset; the run's `COVERAGE` key-value record is authoritative. |
| `includeLiens` | boolean | no | `true` | Join UCC / lien filings where available. A state we cover for entity search but don't join liens for still returns the full entity record (with `liens_checked=false`, `lien_coverage="no_lien_source"`, and a note) — you still get the entity. Set `false` to skip the lien join entirely. |
| `matchMode` | string | no | `contains` | `contains` (broad — find all entities sharing a name), `exact` (legal name equals the query), or `starts` (name begins with the query). |
| `maxRecordsPerCompany` | integer | no | `25` | Cap on entity records returned (and billed) per company name, across states. Bounds broad-name searches. |

Provide `companyName` and/or `companyNames` — at least one is required.

### Output

One dataset record per matched entity. Example (`completed`, with a lien join):

```json
{
  "query": "Tesla Electric Company",
  "status": "completed",
  "state": "CO",
  "legal_name": "Tesla Electric Company LLC",
  "entity_id": "20141524018",
  "entity_type": "DLLC",
  "entity_status": "Good Standing",
  "formation_date": "2014-08-27",
  "jurisdiction": "CO",
  "registered_agent_name": "Felix Keil",
  "principal_address": "9750 Hilldale Dr, Morrison, CO, 80465",
  "officers": [],
  "liens_checked": true,
  "lien_coverage": "joined",
  "ucc_filings": [
    {
      "filing_number": "20192017103",
      "filing_type": "UCC financing statement",
      "status": "active",
      "filed_date": "2019-03-01",
      "lapse_date": "2024-03-01",
      "secured_party": "US BANK NA",
      "collateral": "All equipment now owned or hereafter acquired",
      "debtor_name": "TESLA ELECTRIC COMPANY LLC"
    }
  ],
  "ucc_summary": { "total": 6, "active": 6 },
  "source": "Colorado Secretary of State (Business Entities)",
  "source_url": "https://www.coloradosos.gov/biz/BusinessEntityCriteriaExt.do",
  "fetched_at": "2026-07-09T14:03:11Z",
  "field_notes": []
}
```

Key fields: `status` (resolution outcome), `entity_status` (registration standing,
verbatim from the state), `liens_checked` (whether a covered lien source was queried),
`lien_coverage` (`joined`, `no_lien_source`, `unavailable`, or `not_requested`),
`ucc_filings` (the join), `ucc_summary` (`{total, active}`), and `field_notes` (why
any field is structurally absent). Entity coverage is broader than lien-join
coverage: an uncovered-for-liens state still returns the entity with
`liens_checked=false` and a coverage note. A run also writes a `COVERAGE` key-value
record listing the authoritative live entity-search and lien-join state sets.

### Example

```bash
curl -X POST "https://api.apify.com/v2/acts/shelvick~business-entity-lien-search/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companyName": "Tesla", "states": ["CO", "CT"], "includeLiens": true}'
```

Returns one record per matched Colorado and Connecticut entity, each with its UCC
lien filings attached.

### Calling from an AI agent

Agents are the primary customer. Three ways to call it:

- **Apify MCP server** (`mcp.apify.com`): expose `shelvick/business-entity-lien-search`
  as a tool; the input schema and per-field descriptions are advertised to the model.

- **Apify Python SDK:**

  ```python
  from apify_client import ApifyClient

  client = ApifyClient("<APIFY_TOKEN>")
  run = client.actor("shelvick/business-entity-lien-search").call(
      run_input={"companyName": "Acme Holdings", "states": ["CO", "CT"], "includeLiens": True}
  )
  for record in client.dataset(run["defaultDatasetId"]).iterate_items():
      print(record["legal_name"], record["entity_status"], record["ucc_summary"])
  ```

- **REST:** `POST /v2/acts/shelvick~business-entity-lien-search/run-sync-get-dataset-items`
  for a synchronous call, or the async `/runs` endpoint plus polling for large batches.

### Pricing

Pay-per-event, billed only on success. Each **completed** entity record is charged
once, after it is pushed to the dataset (push-then-charge) — the charge covers the
registry search, normalization, and the UCC lien join where available.
`no_match`, `not_covered`, and `failed` results are returned but never charged.

Records from the three **extended-coverage entity states** — Montana, California,
and Georgia — bill at a higher extended per-record rate. Those states are searched
only when you explicitly name them in `states`, so the extended rate is never
charged for a state you didn't ask about; the search-everywhere default sticks to
the standard rate.

Pennsylvania, New York, and Iowa entity records remain part of the standard default
search at the standard rate. Their lien joins are extended-coverage: they are
available only when you explicitly name the state in `states` with liens enabled,
and those records bill the extended per-record rate only when the lien join is
delivered.

Broad-name searches are bounded by `maxRecordsPerCompany` and the run's max-charge
cap, and every charge is clamped to your remaining budget. See the **Pricing** tab
on this Store page for the current per-record rates and any active subscriber
discounts.

### Behavior

- **Statuses:** `completed` (entity found + normalized), `no_match` (covered states
  searched, nothing matched — a clear "not found"), `not_covered` (a requested
  state isn't supported yet), `failed` (a covered state's registry could not be
  reached; see `error`). Only `completed` is billed.
- **Graceful degradation:** if one state's registry is briefly unavailable, that
  state yields a `failed` record while the rest of the run completes — a source
  hiccup never fails the whole batch or charges you for it.
- **Latency:** an entity-only lookup returns in a few seconds; a multi-state search
  with the lien join is typically well under a minute. Batches run companies
  concurrently.
- **Coverage:** entity search covers 30 states — 27 in the default fan-out, plus
  Montana, California, and Georgia when explicitly requested. Clean-tier lien joins
  are available for **AK, AL, AR, CO, CT, FL, ID, KY, MS, NM, RI, and WI**.
  Extended-coverage joins are available for **Montana, California, Pennsylvania,
  New York, and Iowa** when explicitly requested. A state without lien-join
  coverage (Georgia included) still returns entity records with `liens_checked=false`,
  `lien_coverage="no_lien_source"`, and a coverage note. The live `COVERAGE`
  key-value record is authoritative per run, and coverage expands over time.
- **Source freshness:** lien data is only as current as each state's published
  index. Florida lien data is indexed from the state's official public UCC data
  files on a periodic refresh cycle, so a very recently filed Florida lien may not
  appear until the next refresh; those files publish filing images rather than
  collateral text. Kentucky's UCC index in particular publishes on roughly a
  two-week lag, so a very recently filed Kentucky lien may not appear yet. Iowa's
  and Rhode Island's lien searches cover active filings plus those lapsed within
  roughly the past year — older lapsed history is not published, so lien totals
  there describe the current picture rather than all history. Rhode Island
  publishes no per-filing lapse date; each filing's `status` is derived from the
  state's own active/lapsed indexes and its filing history instead.
- **Current-only sources:** a few states publish only their *currently registered*
  entities — dissolved and withdrawn ones are absent from the source. For those, a
  `no_match` means no currently registered entity matched the name, not that it never
  existed; the record carries a `field_notes` entry saying so. Iowa reports every
  returned entity as active (its bulk file has no status column); Alaska keeps each
  entity's real standing (e.g. `Good Standing`, `Non-Compliant`) but still omits
  dissolved entities. Florida is the opposite: its register includes inactive and
  dissolved entities with their real status, so an FL record can come back `Inactive`
  — useful when you need to know a counterparty was dissolved rather than never
  registered. Mississippi also includes the full register and preserves state standing
  values such as `Good` and `Dissolved`, but its source does not publish registered-agent
  or officer data.
- **Telemetry:** to improve coverage and reliability, this Actor reports anonymous
  usage metrics and diagnostic events to the developer — run outcome counts, the
  states queried, and, only when something goes wrong, the relevant input fields.
  No account identifiers are collected, and telemetry never affects a run.

### FAQ

- **Which states are covered?** Entity search: 27 states by default, plus MT, CA,
  and GA when named in `states`. The UCC / lien join is currently available for
  AK, AL, AR, CA, CO, CT, FL, ID, KY, MS, MT, NM, and WI — entities from any other state
  return as full entity records without a lien join, clearly flagged
  (`liens_checked=false`, `lien_coverage="no_lien_source"`). The run's `COVERAGE`
  record is the authoritative live list as coverage expands.
- **Why are MT, CA, and GA only searched when I name them?** They are
  extended-coverage states billed at a higher per-record rate (see the Pricing
  tab). Keeping them out of the search-everywhere default means you are never
  charged the extended rate for a state you didn't ask about — naming them in
  `states` is the opt-in.
- **Can I use this for a registered agent lookup?** Yes — every completed record
  carries `registered_agent_name` (and the agent's address where the state
  publishes it), so a registered agent lookup by company name is a single call.
- **What if a company has no liens?** For a lien-covered state, `liens_checked` is
  `true`, `lien_coverage` is `joined`, and `ucc_summary` is `{total: 0, active: 0}` —
  a confident "no liens found," not a gap. If the state lacks a lien join,
  `liens_checked` is `false`, `lien_coverage` is `no_lien_source`, and the entity
  record includes a coverage note instead.
- **How precise is the entity→lien match?** Filings are attached only when the UCC
  debtor's core legal name matches the entity's, so a lien against a
  similarly-named company is not misattributed. Descriptive words (Company, Trust)
  are kept; only legal-form suffixes (LLC, Inc.) are normalized away for matching.
- **Can I verify a list of companies at once?** Yes — pass `companyNames`; each is
  resolved and billed independently.
- **Is this official / real-time?** Data comes from the official state registries
  — Secretary of State / corporations-division records and state open-data
  portals; it is as current as those sources publish.

### What this doesn't do

- **No paywalled or login-gated sources.** It uses only free, public registry data;
  it does not cross any state's paid detail lookup.
- **No consumer / personal-PII lookups.** Business-entity public records only — not
  people search, not skip tracing.
- **No document images or filed PDFs** — structured fields, not scanned filings.
- **Not every state yet.** Uncovered states return `not_covered`; it is not a
  50-state guarantee.
- **Not a monitoring service** — it answers a point-in-time query, it does not watch
  an entity for changes.

Use a dedicated people-search or identity-verification tool for individuals, a
document-retrieval service for filed images/PDFs, and a court-records or
enforcement tool for litigation history — this Actor is for the business-entity
record and its UCC lien exposure.

Data is sourced from public government registries and open-data portals and is
provided for lawful business, compliance, and diligence use; verify against the
official source of record before relying on it for a regulatory decision, and use
it in accordance with the Apify Terms of Service and applicable law.

Design notes: [www.scotthelvick.com/tools/business-entity-lien-search](https://www.scotthelvick.com/tools/business-entity-lien-search)

# Actor input Schema

## `companyName` (type: `string`):

The business / company name to search for, e.g. "Tesla" or "Acme Holdings LLC". Matched against official state business registries. Provide this and/or `companyNames`; at least one is required. Use `matchMode` to control exact vs. partial matching.

## `companyNames` (type: `array`):

Multiple company names to look up in one run (one per line) — for verifying a list of counterparties. Each name is resolved and billed independently. Provide this and/or `companyName`; at least one is required.

## `states` (type: `array`):

Two-letter US state codes to scope the search, e.g. \["CO","CT","NY"]. Empty searches all default-covered entity registries. Entity search covers many states; the UCC / lien join covers a subset of them. Pennsylvania, New York, and Iowa entity records are included in the standard default search, but their extended-coverage lien joins require explicitly naming the state with liens enabled and bill the extended rate only when the join is delivered. When an entity is found in a state that has entity coverage but no lien source, the full entity record is still returned (with liens\_checked=false, lien\_coverage='no\_lien\_source', and a note) — you still get the entity, just no lien join. The run's COVERAGE key-value-store output is the authoritative live list of entity-search and lien-join states.

## `includeLiens` (type: `boolean`):

When true (default), each resolved entity is joined to UCC / lien filings where that capability is available. Set false for an entity-only lookup. Clean-tier lien joins currently cover AK, AL, AR, CO, CT, FL, ID, KY, MS, NM, RI, and WI. Montana, California, Pennsylvania, New York, and Iowa joins are extended-coverage and require explicitly naming the state; Pennsylvania, New York, and Iowa bill the extended rate only when the join is delivered. Entities from other states return without a lien join and are flagged with lien\_coverage='no\_lien\_source'. The run's COVERAGE key-value-store output is the authoritative live list.

## `matchMode` (type: `string`):

How to match the company name against the registry. 'contains' (default) is broadest — good for discovering all entities sharing a name. 'exact' returns only entities whose legal name equals the query. 'starts' matches names beginning with the query.

## `maxRecordsPerCompany` (type: `integer`):

Safety cap on how many entity records are returned (and billed) per company name, across all searched states. Protects broad-name searches (e.g. "Smith") from returning hundreds of entities. Default 25.

## Actor input object example

```json
{
  "companyName": "Tesla",
  "companyNames": [],
  "states": [
    "CO",
    "CT"
  ],
  "includeLiens": true,
  "matchMode": "contains",
  "maxRecordsPerCompany": 25
}
```

# Actor output Schema

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

Normalized business-entity records for this run (one per matched entity, each joined to its UCC lien filings).

# 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 = {
    "companyName": "Tesla",
    "companyNames": [],
    "states": [
        "CO",
        "CT"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("shelvick/business-entity-lien-search").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 = {
    "companyName": "Tesla",
    "companyNames": [],
    "states": [
        "CO",
        "CT",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("shelvick/business-entity-lien-search").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "companyName": "Tesla",
  "companyNames": [],
  "states": [
    "CO",
    "CT"
  ]
}' |
apify call shelvick/business-entity-lien-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=shelvick/business-entity-lien-search",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/xUZKQ16dDFL9qSS5t/builds/y3mhESr52ZrEbpMA6/openapi.json
