Lien Search: API Quickstart

Step-by-step guide to implementing Baselayer Lien Search via API.

This guide walks through the full lien search implementation: submitting a search, retrieving results, and downloading lien documents.

Before starting, review Lien Search: Basics for an overview of how the product works, and Liens, Judgments, and Public Records for lien terminology.


Prerequisites

  • An active Baselayer API key
  • A completed Business Search: you will need either the business_id or business_search_id from that result
  • Familiarity with Baselayer's Business Search API: see Business Search: API Basics if needed

Base URL & Authentication

Base URL:

Production:  https://api.baselayer.com

Authentication: All requests require an API key in the X-API-Key header:

X-API-Key: YOUR_API_KEY

Step 1: Submit the Lien Search

POST /lien_searches accepts three request variants depending on what identifiers you have available. Choose the one that fits your integration.


Option A: Search by business_id

Use the business_id from a previous Baselayer Business Search. The search targets the domestic state of the business unless search_states is specified.

curl --request POST \
  --url https://api.baselayer.com/lien_searches \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "business_id": "f7688172-2e5f-400b-9e3f-8d2f93eabd79"
  }'

To search specific states instead of the domestic state:

curl --request POST \
  --url https://api.baselayer.com/lien_searches \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "business_id": "f7688172-2e5f-400b-9e3f-8d2f93eabd79",
    "search_states": ["CA", "FL"]
  }'

Option B: Search by business_search_id with additional_search_entities

Use the id from a Business Search response. This variant supports additional_search_entities, which lets you search for linked individuals or alternate business names in the same API call - without making separate requests.

This is the recommended approach when your workflow requires lien coverage for business officers, guarantors, or beneficial owners alongside the primary business.

curl --request POST \
  --url https://api.baselayer.com/lien_searches \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "business_search_id": "1504f313-9721-4006-b813-82faf6c6f02d",
    "additional_search_entities": [
      {
        "name": "Jane Smith",
        "type": "Person",
        "search_states": ["DE"]
      },
      {
        "name": "Smith Holdings LLC",
        "type": "Business",
        "search_states": ["DE", "CA"]
      }
    ]
  }'

additional_search_entities fields:

FieldRequiredDescription
nameYesName of the individual or business to search
typeYes"Person" or "Business"
search_statesYesArray of two-letter state codes to search for this entity

Note: search_states is required for each entity in additional_search_entities. The main business will still default to its domestic state unless you override it with a top-level search_states field.

For full guidance on when and how to use additional_search_entities, see Lien Search: Best Practices.


Option C: Search by person_id

Use a person_id from an existing Baselayer person record. search_states is required for person-based searches.

curl --request POST \
  --url https://api.baselayer.com/lien_searches \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "person_id": "f9458925-bea9-4551-9913-31c21658d3d7",
    "search_states": ["DE", "NJ"]
  }'

For a full guide on searching individuals, see Lien Search for Individuals.


Execution Mode

Lien searches support both synchronous and asynchronous execution. Results are returned directly in the response body on synchronous requests. For async execution, consume results via webhooks (LiensSearch.completed) or by polling /lien_searches/{lien_search_request_id}. See Synchronous & Asynchronous Request Execution for setup guidance.


Step 2: Retrieve Results

Synchronous (default): Results are returned directly in the POST response body. Skip ahead to Step 3 — Parse the Response.

Asynchronous: Consume results via the LiensSearch.completed webhook or poll /lien_searches/{lien_search_request_id}/status until state is COMPLETED, then retrieve the full result with GET /lien_searches/{lien_search_request_id}. See Synchronous & Asynchronous Request Execution for full guidance.


Step 3: Parse the Response

The core content of a completed search is the filings array.

Example response:

{
  "id": "5442a0ec-4172-47fa-8001-a2d62fc99f44",
  "state": "COMPLETED",
  "business_id": "f7688172-2e5f-400b-9e3f-8d2f93eabd79",
  "business_search_id": "1504f313-9721-4006-b813-82faf6c6f02d",
  "searched_states": ["DE"],
  "last_updated_at": "2024-06-01",
  "search_entities": [
    {
      "name": "Acme Logistics Inc",
      "normalized_name": "acme logistics inc",
      "type": "Business",
      "search_states": ["DE"]
    },
    {
      "name": "Jane Smith",
      "normalized_name": "jane smith",
      "type": "Person",
      "search_states": ["DE"]
    }
  ],
  "filings": [
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000001",
      "state": "DE",
      "filing_number": "2019-0045321-1",
      "filing_type": "consensual.ucc",
      "filing_date": "2019-03-12",
      "lapse_date": "2029-03-12",
      "status": "active",
      "number_of_pages": 3,
      "document_filename": "2019-0045321-1.pdf",
      "match_level": "EXACT",
      "search_entity_name": "Acme Logistics Inc",
      "search_entity_type": "Business",
      "last_updated_at": "2024-06-01",
      "parties": [
        { "role": "Secured Party", "name": "First National Bank", "type": "Secured Party" },
        { "role": "Debtor", "name": "Acme Logistics Inc", "type": "Debtor" }
      ],
      "collateral_statements": [
        { "text": "All assets", "sort_order": 0 }
      ],
      "amendments": [
        {
          "filing_number": "2024-0045321-2",
          "filing_type": "continuation",
          "filing_date": "2024-01-15",
          "number_of_pages": 1
        }
      ]
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000002",
      "state": "DE",
      "filing_number": "2023-0091234-1",
      "filing_type": "tax.federal_irs",
      "filing_date": "2023-07-20",
      "lapse_date": null,
      "status": "active",
      "number_of_pages": null,
      "document_filename": null,
      "match_level": "EXACT",
      "search_entity_name": "Acme Logistics Inc",
      "search_entity_type": "Business",
      "last_updated_at": "2024-06-01",
      "parties": [
        { "role": "Secured Party", "name": "Internal Revenue Service", "type": "Secured Party" },
        { "role": "Debtor", "name": "Acme Logistics Inc", "type": "Debtor" }
      ],
      "collateral_statements": [],
      "amendments": []
    }
  ]
}

Key fields to evaluate on each filing:

FieldWhat to check
filing_typeNormalized type, use this for classification (see Lien Search: Basics for the full enum)
statusWhether the lien is currently active, terminated, or lapsed
lapse_dateWhether the lien is still within its effective period
search_entity_nameWhich entity in your request this filing matched, useful when searching multiple entities
amendmentsLifecycle history, look for termination or continuation entries
collateral_statementsScope of pledged assets
document_filenameNon-null means a document PDF is available

Active lien check: A lien should be considered currently effective only if both of the following are true: status == "active" and lapse_date is in the future (or null). Some state registries do not automatically update status after lapse - always check lapse_date independently.

For full guidance on interpreting and classifying results, see Lien Search: Best Practices.


Step 4: Retrieve Lien Documents

PDF documents are available for many filings at no additional cost.

Check availability: document_filename is non-null on the filing.

Retrieve the document:

curl --request GET \
  --url https://api.baselayer.com/lien_searches/SEARCH_ID/filings/FILING_ID \
  --header 'X-API-Key: YOUR_API_KEY' \
  --output lien_document.pdf

This returns a consolidated PDF of all documents associated with that filing.


Full Example: Business + Guarantor Lien Search (Synchronous)

import requests
from datetime import date

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.baselayer.com"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

# Step 1: Submit lien search — business + guarantor in one call
payload = {
    "business_search_id": "1504f313-9721-4006-b813-82faf6c6f02d",
    "additional_search_entities": [
        {
            "name": "Jane Smith",        # Personal guarantor
            "type": "Person",
            "search_states": ["DE"]
        }
    ]
}

response = requests.post(f"{BASE_URL}/lien_searches", json=payload, headers=headers)
result = response.json()

today = str(date.today())
filings = result.get("filings", [])

for filing in filings:
    filing_type = filing.get("filing_type", "")
    status = filing.get("status")
    lapse_date = filing.get("lapse_date")
    entity = filing.get("search_entity_name")

    # Effectiveness check: active status + lapse date in the future
    is_active = status == "active" and (lapse_date is None or lapse_date > today)
    if not is_active:
        continue

    label = f"[{entity}]"

    if filing_type.startswith("tax."):
        print(f"HIGH RISK {label} Active tax lien: {filing_type} (filed {filing['filing_date']})")

    elif filing_type.startswith("judicial."):
        print(f"HIGH RISK {label} Active judgment lien: {filing_type} (filed {filing['filing_date']})")

    else:
        print(f"ACTIVE LIEN {label} {filing_type} (filed {filing['filing_date']})")

        # Log collateral scope
        for stmt in filing.get("collateral_statements", []):
            print(f"  Collateral: {stmt['text']}")

    # Retrieve document if available
    if filing.get("document_filename"):
        doc = requests.get(
            f"{BASE_URL}/lien_searches/{result['id']}/filings/{filing['id']}",
            headers=headers
        )
        with open(f"lien_{filing['id']}.pdf", "wb") as f:
            f.write(doc.content)
        print(f"  Document saved: lien_{filing['id']}.pdf")

Where to Go Next