> ## Documentation Index
> Fetch the complete documentation index at: https://docs.herondata.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Background Checks

> Screen a deal's owners and business and retrieve the structured results via the Heron API

The Background Check API screens a deal's **owners** and **business** against public-records data and returns Heron's structured work product: a per-subject breakdown of criminal records, bankruptcies, liens and judgments, lawsuits, UCC filings, sanctions / OFAC matches, corporate filings, and more, plus the outcome of each policy check you've configured.

The flow is:

1. Make sure the deal's owner and business details have reached Heron - usually automatically from the ISO applications you already send us.
2. Trigger the background check.
3. Poll for completion and fetch the results.

<Note>
  The background check runs **asynchronously**. Triggering it returns immediately; you poll the results endpoint until the run completes.
</Note>

This page is the narrative walkthrough. The full request and response schema for each endpoint is generated from our OpenAPI spec and lives in the API reference, so it always matches the live API:

* [Trigger a background check](/api-reference/enduserenrichers/start-enricher-execution-for-a-specific-end-user-asynchronously)
* [Get background check results](/api-reference/endusers/get-enduser-background-check-dashboard-payload)
* [Set application data](/api-reference/endusers/patch-enduser-information)

## Prerequisites

Before following this guide, you will need:

* An API key (see [Authentication](/api-reference/authentication)). All requests send it in the `x-api-key` header.
* The background check product enabled for your account. Speak to your Heron rep to switch it on - it is not enabled by default.
* An end user representing the deal you want to screen. Most integrations already have these - an end user is created whenever you send Heron an ISO application, or you can create one directly ([Create EndUser](/api-reference/endusers/create-enduser)). The calls below address it by its `heron_id` (an `eus_` string) or your own `end_user_id`.

## Steps

### 1. Make sure the deal's details have reached Heron

The background check searches on the owner and business identity Heron holds for the deal. There are two ways that data gets there.

#### From your ISO applications (most common)

If you already send Heron the deal's ISO application - by API or email forwarding - Heron extracts the owner and business details from it automatically. There's nothing extra to do here; skip to step 2.

#### Send the details over the API

If you don't send ISO applications, supply the identity directly with `PATCH /end_users/{id}/end_user_information` ([reference](/api-reference/endusers/patch-enduser-information)):

```python app.py theme={null}
import requests

BASE_URL = "https://app.herondata.io"
API_KEY = "key_xxxxxxxx"
end_user_heron_id = "eus_xxxxxxxx"  # the deal you're screening

requests.patch(
  f"{BASE_URL}/api/end_users/{end_user_heron_id}/end_user_information",
  headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
  json={
    "company_legal_business_name": "ACME Logistics LLC",
    "federal_tax_id": "12-3456789",
    "company_physical_address": {"line_1": "123 Main St", "city": "Austin", "state": "TX", "zip": "78701"},
    "owner_1": {
      "first_name": "Jane",
      "last_name": "Doe",
      "date_of_birth": "1985-03-20",
      "social_security_number": "123-45-6789",
      "home_address": {"line_1": "456 Oak Ave", "city": "Austin", "state": "TX", "zip": "78704"},
    },
  },
).raise_for_status()
```

The [Set application data](/api-reference/endusers/patch-enduser-information) reference lists every accepted field. The fields that drive the background check search are:

| Subject  | Fields used                                                                                                |
| -------- | ---------------------------------------------------------------------------------------------------------- |
| Owners   | `first_name`, `last_name`, `social_security_number`, `date_of_birth`, `home_address`                       |
| Business | `company_legal_business_name`, `dba`, `federal_tax_id`, `company_physical_address`, `company_phone_number` |

<Note>
  The more identity available, the more precise the match. A **name** is the minimum for an owner (first + last) and a **legal name or DBA** is the minimum for the business, but an owner's **SSN and date of birth** is what reliably resolves them to the right person and avoids false matches. Up to two owners (`owner_1`, `owner_2`) are supported.
</Note>

### 2. Trigger the background check

Start the check with the `background_check` enricher ([reference](/api-reference/enduserenrichers/start-enricher-execution-for-a-specific-end-user-asynchronously)). It returns `202 Accepted` as soon as the run is dispatched:

```python app.py theme={null}
import requests

BASE_URL = "https://app.herondata.io"
API_KEY = "key_xxxxxxxx"
end_user_heron_id = "eus_xxxxxxxx"  # the deal you're screening

requests.post(
  f"{BASE_URL}/api/end_user_enrichers/definitions/background_check/start_enrich",
  headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
  json={"end_user_heron_id": end_user_heron_id},
).raise_for_status()
```

### 3. Poll and fetch the results

Fetch the background check ([reference](/api-reference/endusers/get-enduser-background-check-dashboard-payload)) and read the top-level `status` until it is no longer `processing`:

```python app.py theme={null}
import requests, time

BASE_URL = "https://app.herondata.io"
API_KEY = "key_xxxxxxxx"
end_user_heron_id = "eus_xxxxxxxx"  # the deal you're screening

def get_background_check():
  response = requests.get(
    f"{BASE_URL}/api/end_users/{end_user_heron_id}/background_check",
    headers={"x-api-key": API_KEY},
  )
  response.raise_for_status()
  return response.json()

result = get_background_check()
while result["status"] == "processing":
  time.sleep(10)
  result = get_background_check()

# status is now "succeeded", "failed", or "missing_input_data"
```

#### Status lifecycle

| `status`             | Meaning                                                                                                |
| -------------------- | ------------------------------------------------------------------------------------------------------ |
| `never_run`          | No background check has been triggered for this end user yet.                                          |
| `processing`         | A run is in flight. `processing_stage` reports the phase: `searching`, `pulling_reports`, `analysing`. |
| `succeeded`          | The run completed; `overall`, `subjects`, and `policy` are populated.                                  |
| `failed`             | The run errored. No results are available.                                                             |
| `missing_input_data` | No owner or business identity was available to search on (see step 1).                                 |

## Understanding the result

A succeeded response has three parts:

* **`overall`** - the headline: a `result` (`pass` / `review_required` / `failed` / `missing_data`), a `severity`, and pass / review / fail counts.
* **`subjects[]`** - one entry per `owner_1`, `owner_2`, and `business`, each with how it was matched (`resolution`), the search trail (`searches`), and the findings grouped by record type (`sections`).
* **`policy`** - the outcome of your configured checks, each with its status and the evidence (subject, section, and records) behind it.

The full field-level schema - every section type, record shape, and enum - is on the [Get background check results](/api-reference/endusers/get-enduser-background-check-dashboard-payload) reference page, generated from the live API. An abridged example to show the shape:

```json theme={null}
{
  "end_user_id": "eus_xxxxxxxx",
  "status": "succeeded",
  "overall": { "result": "review_required", "severity": "medium", "check_counts": { "pass": 12, "review": 2, "fail": 0 } },
  "subjects": [
    {
      "key": "owner_1",
      "kind": "person",
      "name": "Jane A Doe",
      "resolution": { "status": "found", "method": "ssn_dob", "confidence_score": 0.97 },
      "sections": [
        {
          "key": "criminal",
          "label": "Criminal Records",
          "count": 1,
          "severity": "medium",
          "flag": "fail",
          "records": [{ "offense": "Theft - petit", "disposition": "Convicted", "is_felony": false }]
        }
      ]
    },
    {
      "key": "business",
      "kind": "business",
      "name": "ACME Logistics LLC",
      "resolution": { "status": "found", "method": "name_state" },
      "duns_numbers": ["123456789"],
      "unreported_officers": ["John Smith"]
    }
  ],
  "policy": {
    "result": "review_required",
    "checks": [
      { "id": "owner_felony_recent", "auto_status": "pass", "evidence": { "subject_key": "owner_1", "section": "criminal" } }
    ]
  }
}
```

## Downloading a report as a PDF

Heron returns the background check as **structured data** (above), which is the source of truth and the most flexible format to integrate against - you can render it however suits your product.

We can also generate a **single combined PDF** covering all owners and the business in one document, branded as Heron's work product.

<Note>
  Heron provides its own background check work product. We can't redistribute the raw third-party reports our data comes from. If a rendered PDF is something you need, talk to your Heron rep about format and branding.
</Note>
