# Arizona Mechanics Lien & Lis Pendens Feed (`sullivan-ventures/construction-distress-feed`) Actor

Every new mechanics lien and lis pendens recorded in Maricopa County (Phoenix, AZ) each week, grouped by company with repeat-filer and new-company flags. From the official county recorder. For collections, sureties and lien attorneys. More counties on request.

- **URL**: https://apify.com/sullivan-ventures/construction-distress-feed.md
- **Developed by:** [Michael Sullivan](https://apify.com/sullivan-ventures) (community)
- **Categories:** Lead generation, Business, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$40.00 / 1,000 records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Arizona Mechanics Lien & Lis Pendens Feed

Construction Distress Feed is an Apify Actor by Sullivan Ventures that collects every new mechanics lien and lis pendens recorded with the Maricopa County Recorder (Phoenix, Arizona) each week and groups the records by company, flagging repeat filers and companies new to the feed. It's built for collections firms, credit managers, sureties and construction attorneys.

Each week, get every new **mechanics lien** and **lis pendens** recorded in Maricopa County, Arizona (Phoenix metro). You can also pull **trustee sale notices, judgments and state/federal tax liens**. Every record is grouped by company, and the feed flags the **contractors and suppliers whose claims are stacking up**.

Run it on a schedule (weekly is ideal). Each run remembers what it saw before, so you can tell which companies are **new** this week and which keep showing up.

### Who it's for

- **Collections firms and credit managers.** See which contractors and suppliers are filing liens (they're owed money) and which owners and GCs keep getting liened (they're slow payers).
- **Sureties and bond agents.** A general contractor with liens piling up across several jobs is a warning sign for a bond claim.
- **Construction attorneys.** Lien claimants have a deadline to enforce their liens, and lis pendens filed by subcontractors usually mean lien-foreclosure suits. Fresh records reach you before the dispute hardens.
- **Data resellers and lead platforms.** You get a clean, deduplicated, scheduled JSON or CSV feed straight from the official recorder, with no captcha and no proxy needed.

### What you get

**Dataset (one row per recorded document):**

- `recording_number`, `recording_date`, `doc_type`, `document_code`, `page_count`
- `business_parties`: the companies named on the document
- `contractor_supplier_parties`
- `repeat_company_names`, `has_repeat_company`
- `has_new_company`: a company never seen in your prior runs
- `is_new_record`
- `source_url`: the official recorder API record, so you can check it yourself

**Key-value store outputs:**

- `COMPANIES` (JSON) and `COMPANIES_CSV`, one row per normalized company:
  - `record_count` and `counts_by_type` for the window
  - `repeat_company`, `repeat_in_window`
  - `status_vs_prior_run` (`new`, `repeat`, or `baseline` on the first run)
  - `first_seen`, `prior_total_records`
  - `entity_hint` (`contractor_supplier`, `hoa_association`, `debt_buyer_collector`, `lender_trustee_gov`, `other_business`)
  - `name_variants`
- `SUMMARY`: counts, the top repeat companies, and serial filers that were not flagged

**Company names are normalized.** "RK ELECTRICAL" and "RK ELECTRICAL LLC" become one company.

**Serial filers aren't flagged as repeats by default.** HOAs, debt buyers, lenders, trustees and government agencies file on many records as routine business. They still appear in the output, just without the flag. You can change this with `repeatExcludeHints`.

### Inputs

| Field | Default | Notes |
|---|---|---|
| `lastNDays` | 7 | Window ends yesterday. Used when `startDate` is empty. |
| `startDate` / `endDate` | — | `YYYY-MM-DD`, recording date, inclusive. |
| `docTypes` | mechanics liens, modified mechanics liens, lis pendens | Also: lien releases, trustee sale notices, judgments, state and federal tax liens, performance bonds, notices of completion. |
| `businessOnly` | true | Keeps only records with a business party and **leaves private individuals' names out of the output** (they're counted, not listed). |
| `repeatThreshold` | 2 | Number of records in the window that makes a company a repeat company. |
| `stateStoreName` | `construction-distress-state` | Named key-value store that holds your history. Use a different name per client or market. |
| `updateState` | true | Turn off for one-off backfills. |
| `maxRecords` | 2000 | Safety cap. |
| `requestDelayMs` | 300 | Polite rate limit, one request at a time. |

### Example (Oct 1–7, 2026, default settings)

- 42 mechanics liens and 51 lis pendens came in. 86 had a business party.
- 162 companies were found, and 11 were flagged as repeats.
- Example repeats: a general contractor named on 5 liens in one week, and a plumbing supplier on 4.

### Sample output (one record)

```json
{
  "recording_number": "20260573203",
  "recording_date": "2026-10-01",
  "doc_type": "mechanics_lien",
  "document_code": "MECH LN",
  "business_parties": ["CALPORTLAND", "CARNERO CONTRACTING LLC", "DIOCESAN COUNCIL FOR THE SOCIETY OF SAINT VINCENT DE"],
  "individual_party_count": 0,
  "repeat_company_names": ["CALPORTLAND", "CARNERO CONTRACTING LLC"],
  "has_repeat_company": true,
  "contractor_supplier_parties": ["CALPORTLAND", "CARNERO CONTRACTING LLC"],
  "is_new_record": true,
  "page_count": 8,
  "source_url": "https://publicapi.recorder.maricopa.gov/documents/20260573203"
}
```

Companies CSV (key-value store `COMPANIES_CSV`):

```
company_name,record_count,counts_by_type,repeat_company,entity_hint
CARNERO CONTRACTING LLC,5,mechanics_lien:5,true,contractor_supplier
REECE PLUMBING,4,mechanics_lien:4,true,contractor_supplier
```

### Pricing

**Pay per result: $0.04 per record** (one dataset row = one recorded document). No start fee. The company list (`COMPANIES` / `COMPANIES_CSV`) and `SUMMARY` are included free.

- A typical week in Maricopa County (mechanics liens + lis pendens, businesses only) is about 80 to 100 records, so roughly **$3 to $4 per week**.
- Set a **maximum cost per run** in the run options to cap spend. The feed then outputs only as many records as fit, repeat-company records first.
- Plus standard Apify platform usage, which is tiny (a weekly run takes under a minute at 256 MB).

### Data limits (read before buying)

- **No lien amounts, property addresses or parcel numbers yet.** The recorder's public index only lists names, dates, document type and page count. Those other details are printed on the recorded document image.
- **Party roles aren't given.** The index lists every name on the document without saying who is the claimant and who is the owner. `entity_hint` helps tell contractors and suppliers apart from owners, lenders and HOAs.
- **The business and individual split uses rules.** Some edge cases will be wrong, such as a person's name with no company words or a company name with no suffix.
- **Coverage is Maricopa County, AZ only for now.** Records post to the index with a lag of about 1 to 2 days.
- **The source is the Maricopa County Recorder's public API.** If its format changes, **the run fails with a clear "SCHEMA CHANGE DETECTED" error** instead of quietly returning bad data.

### FAQ

#### How do I find mechanics liens filed in Maricopa County?

Run this Actor weekly. It reads the Maricopa County Recorder's public index and returns each new mechanics lien and lis pendens with the recording date, document number and named businesses. In the Oct 1-7, 2026 test week that was 42 mechanics liens and 51 lis pendens.

#### Which contractors have multiple liens against them?

The feed groups records by company and flags repeat names. In the Oct 1-7, 2026 test it found 162 companies and flagged 11 as repeats, including a general contractor named on 5 liens in one week. That's an early warning sign for sureties and credit managers.

#### What does a lis pendens mean in construction?

A lis pendens is a public notice that a lawsuit affects a property. In construction, subcontractors often file one when they sue to foreclose a mechanics lien, so a fresh lis pendens usually means a payment dispute has gone to court.

#### How much does it cost?

$0.04 per record plus Apify platform usage. A typical Maricopa County week (mechanics liens and lis pendens, businesses only) is about 80 to 100 records, so roughly $3 to $4 a week. The company list and summary are included free.

#### Does it cover other counties or states?

Today it covers Maricopa County, Arizona (Phoenix metro) only. Other US county recorders publish lien indexes in different ways, and we add them on request when the records are public and allowed for reuse. Coverage: we confirm data availability for your county before you run it; ask in the Issues tab.

### Responsible use

These are public records. If you're a lawyer using them for outreach, your state's advertising and solicitation rules apply (for example, Arizona ER 7.3 and Nevada RPC 7.3). Don't use this data for tenant, employment or credit screening (FCRA).

# Actor input Schema

## `lastNDays` (type: `integer`):

Used when Start date is empty. Window ends yesterday (records post with a 1-2 day lag).

## `startDate` (type: `string`):

Recording date, inclusive. Overrides Last N days.

## `endDate` (type: `string`):

Recording date, inclusive. Defaults to yesterday.

## `docTypes` (type: `array`):

Default = construction-related (mechanics liens, modified mechanics liens, lis pendens).

## `businessOnly` (type: `boolean`):

Keep only records with at least one business party, and leave individual people's names out of the output.

## `excludeIntermediaries` (type: `boolean`):

Banks, servicers, trustees, government, HOAs and debt buyers file on many records by design. They are still listed (with entity_hint) but not flagged as repeat companies unless you change the list below.

## `repeatExcludeHints` (type: `array`):

Only used when the switch above is on.

## `repeatThreshold` (type: `integer`):

A company is a repeat company when it appears on at least this many records in the window.

## `stateStoreName` (type: `string`):

Named key-value store that remembers companies and records between runs (for new vs repeat).

## `updateState` (type: `boolean`):

Turn off for one-off backfills you don't want counted as a prior run.

## `maxRecords` (type: `integer`):

Safety cap across all document types.

## `requestDelayMs` (type: `integer`):

Polite rate limit. One request at a time.

## Actor input object example

```json
{
  "lastNDays": 7,
  "docTypes": [
    "mechanics_lien",
    "modified_mechanics_lien",
    "lis_pendens"
  ],
  "businessOnly": true,
  "excludeIntermediaries": true,
  "repeatExcludeHints": [
    "lender_trustee_gov",
    "hoa_association",
    "debt_buyer_collector"
  ],
  "repeatThreshold": 2,
  "stateStoreName": "construction-distress-state",
  "updateState": true,
  "maxRecords": 2000,
  "requestDelayMs": 300
}
```

# Actor output Schema

## `records` (type: `string`):

One row per recorded document: recording number and date, document type, business parties, repeat/new company flags, source URL.

## `companies` (type: `string`):

One row per normalized company: record count by type, repeat flags, new vs prior run, entity hint.

## `companiesCsv` (type: `string`):

Same company list as CSV.

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

Counts per document type, top repeat companies, serial filers not flagged, data limits.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("sullivan-ventures/construction-distress-feed").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("sullivan-ventures/construction-distress-feed").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 '{}' |
apify call sullivan-ventures/construction-distress-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sullivan-ventures/construction-distress-feed"
        }
    }
}
```

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/Oa5exUsFlu3nqGPz3/builds/M9v59nxxayDHmLE7G/openapi.json
