# TX Insurance Network - Agencies, Appointments & Relationships (`j0401/tx-tdi-network`) Actor

Four Texas Department of Insurance registers in one actor: licensed agencies and businesses (57k), company appointments for agencies (628k), owner/officer business relationships (133k) and company appointments for individual agents (4.48M). Joined by NPN, EIN and NAIC id.

- **URL**: https://apify.com/j0401/tx-tdi-network.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 tx insurance network records

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

## TX Insurance Network - Agencies, Appointments & Relationships

Four Texas Department of Insurance registers in one actor: who is licensed to sell insurance in Texas, which insurers appointed them, and who owns or runs the agency. The registers share NPN, EIN and NAIC keys, so you can join them client-side on those ids.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.**

### Registers

| `corpus` | Rows | One row is |
|---|---:|---|
| `agencies` (default) | ~57,000 | a licensed insurance agency or business |
| `agency-appointments` | ~628,000 | a company appointment for an agency or business |
| `business-relationships` | ~133,000 | an owner / officer link between two licensees |
| `agent-appointments` | ~4,480,000 | a company appointment for an individual agent |

### What you get

`npn`, `ein`, `naicId`, `licenseNumber`, `licenseType`/`agencyType`,
`qualification`, `holderName`/`orgName`, `company`, `appointmentType`,
`associationType`, `associatedName`, `associatedNpn`, `city`, `county`, `state`, `zip`,
`issueDate`, `expirationDate`, `eventDate`, `sourceUpdatedAt`.

### Profile mode - one NPN, every register

`mode=profile` takes one **NPN** and returns every record the four registers hold for that party, joined on **exact keys only**: NPN across all four registers, plus EIN (from the agency's appointments) into business relationships. No name matching is used anywhere.

Each row says which part of the profile it came from in `profileSection` (`agencies`, `agency-appointments`, `agent-appointments`, `business-relationships`) and how it matched in `matchedOn`. A final summary row carries `sourceStatus` per section (`ok` / `empty` / `error: `) **and the number of rows delivered from that section** - the summary row is not charged. `maxResults` is the cap **per section**, not for the whole profile; a section holding more rows than the cap is truncated (raise `maxResults` to see more).

```json
{ "mode": "profile", "npn": "20762385", "maxResults": 50 }
```

Measured with that input (2026-10-24): `agencies` ok, `agency-appointments` ok, `business-relationships` ok, `agent-appointments` empty - 79 rows plus the summary. This NPN holds ~690 agency-appointment rows, so the 50-row section cap was reached; the summary row reports the delivered count. The row count grows as new appointments are filed; the section statuses are the stable part.

### Examples

Agencies licensed in Texas, newest first:

```json
{ "corpus": "agencies", "maxResults": 50 }
```

One agency by NPN:

```json
{ "corpus": "agencies", "npn": "17392597" }
```

Which insurers appointed an agency:

```json
{ "corpus": "agency-appointments", "agencyName": "HAVEN NATIONAL", "maxResults": 100 }
```

Owners and officers of a licensed business:

```json
{ "corpus": "business-relationships", "licenseeName": "1BROKER", "maxResults": 100 }
```

Appointments for one agent:

```json
{ "corpus": "agent-appointments", "npn": "16185407", "maxResults": 100 }
```

Appointments by company:

```json
{ "corpus": "agent-appointments", "mode": "aggregate", "groupBy": "company" }
```

### Honest limits

- **The four registers do not share a row shape.** They are offered side by side, never as one joined row; `corpus` says which view you are reading.
- `agent-appointments` is a **4.48 million-row fact table** with no id of its own. It is never the default; choose it deliberately and use a filter.
- Every name here is a **licensed producer or registered business** in a public regulatory register. No phone, email, SSN or home address is present in any of the four datasets.
- **Appointments are a cumulative history, not a live roster.** TDI never marks an appointment terminated; a later appointment date is a new row. Use `since` to narrow to recent activity. The source carries no expiration date.
- Registrations and appointments change daily; each register has its own integrity guard and freshness check.
- A filter that the chosen register cannot serve is rejected with a clear error rather than ignored.
- **`mode=profile` is an exact-key view, not an entity-resolution service.** It joins on NPN and EIN only, never on names, and it does not assert that two licences belong to the same legal person beyond the shared identifier. An NPN that is not present in a register comes back as that section's `sourceStatus: "empty"`; a malformed NPN (not 5-10 digits) is rejected before any query.
- **`maxResults` in profile mode is per section.** A profile can therefore deliver up to four sections  the cap (plus the uncharged summary row); the summary states how many rows each section actually delivered.
- **The EIN bridge reads at most five EINs** from the agency's appointments when looking for business relationships. It is an exact-key enrichment, not an exhaustive walk; a sixth EIN on the same party is not followed. Its status is reported separately in the summary as `business-relationships-ein`.

### Related

- **TX Insurance Agent & Adjuster Licenses** - every producer licence line (~975k rows). Use it to check who holds which licence; use this actor to see agencies, appointments and ownership.
- **TX Insurance Appointments** - a single-purpose actor over the same `agent-appointments` register. If you only need individual agent appointments, that actor is the smaller choice; this one adds the agency and relationship views.

# Actor input Schema

## `corpus` (type: `string`):

Which register to query (blank = agencies). agent-appointments is a 4.48M-row fact table - pick it deliberately.

## `mode` (type: `string`):

rows = matching records (default). aggregate = one count row per group (see groupBy). profile = every register record for one NPN, joined on exact NPN/EIN keys, plus a summary row with each section's sourceStatus.

## `name` (type: `string`):

Name prefix (agencies).

## `agencyName` (type: `string`):

Name prefix (agency-appointments).

## `agentName` (type: `string`):

Name prefix (agent-appointments).

## `licenseeName` (type: `string`):

Name prefix of the licensee (business-relationships).

## `associatedName` (type: `string`):

Name prefix of the associated licensee, e.g. the owner (business-relationships).

## `npn` (type: `string`):

National Producer Number (exact, 5-10 digits). Required for mode=profile, where it is the join key across all four registers.

## `ein` (type: `string`):

Employer Identification Number (exact; agency-appointments / relationships).

## `naicId` (type: `string`):

Insurer NAIC company id (exact; appointments).

## `licenseNumber` (type: `string`):

Exact agency licence number (agencies).

## `company` (type: `string`):

Company name prefix (appointments).

## `agencyType` (type: `string`):

Agency type (agencies), e.g. Corporation.

## `licenseType` (type: `string`):

Licence type (agencies), e.g. Life Agency.

## `appointmentType` (type: `string`):

Appointment type (appointments), e.g. Underwriter.

## `associationType` (type: `string`):

Relationship type (business-relationships), e.g. Owner.

## `city` (type: `string`):

City prefix. Not available for business-relationships.

## `state` (type: `string`):

Two-letter state code (exact). Not available for business-relationships, whose source has no state column.

## `since` (type: `string`):

ISO date; only records on or after this date (agencies by licence issue date; appointments and relationships by their event date).

## `groupBy` (type: `string`):

Dimension for mode=aggregate. Availability differs per register; an unavailable dimension is rejected rather than ignored.

## `maxResults` (type: `integer`):

Cap on records delivered in rows mode (0 = default 50; up to 5,000 per run). Aggregate mode ignores it and returns up to 20,000 groups. Each record is metered individually.

## `licenseeNpn` (type: `string`):

NPN of the licensee (business-relationships).

## `associatedNpn` (type: `string`):

NPN of the associated licensee, e.g. the owner (business-relationships).

## Actor input object example

```json
{
  "corpus": "",
  "mode": "",
  "groupBy": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

Texas insurance network records - as JSON

## `datasetUrl` (type: `string`):

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/tx-tdi-network").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("j0401/tx-tdi-network").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 j0401/tx-tdi-network --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/tx-tdi-network"
        }
    }
}
```

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/6HDcfJWsDgZMbzEXT/builds/kfBfOan6giViquHFF/openapi.json
